blob: 1de616272f2d84e38d0949588393b79a751e2ad6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.processors.platform.dotnet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.ignite.IgniteException;
import org.apache.ignite.configuration.BinaryConfiguration;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.configuration.PlatformConfiguration;
import org.apache.ignite.internal.binary.BinaryMarshaller;
import org.apache.ignite.internal.binary.BinaryRawWriterEx;
import org.apache.ignite.internal.binary.BinaryReaderExImpl;
import org.apache.ignite.internal.binary.GridBinaryMarshaller;
import org.apache.ignite.internal.logger.platform.PlatformLogger;
import org.apache.ignite.internal.processors.platform.PlatformAbstractConfigurationClosure;
import org.apache.ignite.internal.processors.platform.lifecycle.PlatformLifecycleBean;
import org.apache.ignite.internal.processors.platform.memory.PlatformMemory;
import org.apache.ignite.internal.processors.platform.memory.PlatformMemoryManagerImpl;
import org.apache.ignite.internal.processors.platform.memory.PlatformOutputStream;
import org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils;
import org.apache.ignite.internal.processors.platform.utils.PlatformUtils;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lifecycle.LifecycleBean;
import org.apache.ignite.marshaller.Marshaller;
import org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction;
import org.apache.ignite.platform.dotnet.PlatformDotNetConfiguration;
import org.apache.ignite.platform.dotnet.PlatformDotNetLifecycleBean;
/**
* Closure to apply dot net configuration.
*/
public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigurationClosure {
/** */
private static final long serialVersionUID = 0L;
/** Whether to use platform logger (when custom logger is defined on .NET side). */
private final boolean useLogger;
/** Configuration. */
private IgniteConfiguration cfg;
/** Memory manager. */
private PlatformMemoryManagerImpl memMgr;
/**
* Constructor.
*
* @param envPtr Environment pointer.
*/
public PlatformDotNetConfigurationClosure(long envPtr, boolean useLogger) {
super(envPtr);
this.useLogger = useLogger;
}
/** {@inheritDoc} */
@Override protected void apply0(IgniteConfiguration igniteCfg) {
// Validate and copy Interop configuration setting environment pointer along the way.
PlatformConfiguration interopCfg = igniteCfg.getPlatformConfiguration();
if (interopCfg != null && !(interopCfg instanceof PlatformDotNetConfiguration))
throw new IgniteException("Illegal platform configuration (must be of type " +
PlatformDotNetConfiguration.class.getName() + "): " + interopCfg.getClass().getName());
PlatformDotNetConfiguration dotNetCfg = interopCfg != null ? (PlatformDotNetConfiguration)interopCfg : null;
if (dotNetCfg == null)
dotNetCfg = new PlatformDotNetConfiguration();
memMgr = new PlatformMemoryManagerImpl(gate, 1024);
PlatformLogger logger = null;
if (useLogger) {
logger = new PlatformLogger();
logger.setGateway(gate);
igniteCfg.setGridLogger(logger);
}
PlatformDotNetConfigurationEx dotNetCfg0 = new PlatformDotNetConfigurationEx(dotNetCfg, gate, memMgr,
logger);
igniteCfg.setPlatformConfiguration(dotNetCfg0);
// Set Ignite home so that marshaller context works.
String ggHome = igniteCfg.getIgniteHome();
if (ggHome != null)
U.setIgniteHome(ggHome);
// Callback to .Net.
prepare(igniteCfg, dotNetCfg0);
// Make sure binary config is right.
setBinaryConfiguration(igniteCfg, dotNetCfg0);
}
/**
* Sets binary config.
*
* @param igniteCfg Ignite config.
* @param dotNetCfg .NET config.
*/
private void setBinaryConfiguration(IgniteConfiguration igniteCfg, PlatformDotNetConfigurationEx dotNetCfg) {
// Check marshaller.
Marshaller marsh = igniteCfg.getMarshaller();
if (marsh == null) {
igniteCfg.setMarshaller(new BinaryMarshaller());
dotNetCfg.warnings(Collections.singleton("Marshaller is automatically set to " +
BinaryMarshaller.class.getName() + " (other nodes must have the same marshaller type)."));
}
else if (!(marsh instanceof BinaryMarshaller))
throw new IgniteException("Unsupported marshaller (only " + BinaryMarshaller.class.getName() +
" can be used when running Apache Ignite.NET): " + marsh.getClass().getName());
BinaryConfiguration bCfg = igniteCfg.getBinaryConfiguration();
}
/**
* Prepare .Net size.
*
* @param igniteCfg Ignite configuration.
* @param interopCfg Interop configuration.
*/
private void prepare(IgniteConfiguration igniteCfg, PlatformDotNetConfigurationEx interopCfg) {
cfg = igniteCfg;
try (PlatformMemory outMem = memMgr.allocate()) {
try (PlatformMemory inMem = memMgr.allocate()) {
PlatformOutputStream out = outMem.output();
GridBinaryMarshaller marshaller = PlatformUtils.marshaller();
BinaryRawWriterEx writer = marshaller.writer(out);
PlatformConfigurationUtils.writeDotNetConfiguration(writer, interopCfg.unwrap());
// Write .NET beans
List<PlatformDotNetLifecycleBean> beans = beans(igniteCfg);
writer.writeInt(beans.size());
for (PlatformDotNetLifecycleBean bean : beans) {
writer.writeString(bean.getTypeName());
writer.writeMap(bean.getProperties());
}
// Write .NET affinity functions
List<PlatformDotNetAffinityFunction> affFuncs = affinityFunctions(igniteCfg);
writer.writeInt(affFuncs.size());
for (PlatformDotNetAffinityFunction func : affFuncs) {
writer.writeString(func.getTypeName());
writer.writeMap(func.getProperties());
}
out.synchronize();
gate.extensionCallbackInLongLongOutLong(
PlatformUtils.OP_PREPARE_DOT_NET, outMem.pointer(), inMem.pointer());
processPrepareResult(marshaller.reader(inMem.input()));
}
}
}
/**
* Process prepare result.
*
* @param in Input stream.
*/
private void processPrepareResult(BinaryReaderExImpl in) {
assert cfg != null;
PlatformConfigurationUtils.readIgniteConfiguration(in, cfg);
// Process beans
List<PlatformDotNetLifecycleBean> beans = beans(cfg);
List<PlatformLifecycleBean> newBeans = new ArrayList<>();
int len = in.readInt();
for (int i = 0; i < len; i++) {
if (i < beans.size())
// Existing bean.
beans.get(i).initialize(gate, in.readLong());
else
// This bean is defined in .Net.
newBeans.add(new PlatformLifecycleBean(gate, in.readLong()));
}
if (!newBeans.isEmpty()) {
LifecycleBean[] newBeans0 = newBeans.toArray(new LifecycleBean[newBeans.size()]);
// New beans were added. Let's append them to the tail of the rest configured lifecycle beans.
LifecycleBean[] oldBeans = cfg.getLifecycleBeans();
if (oldBeans == null)
cfg.setLifecycleBeans(newBeans0);
else {
LifecycleBean[] mergedBeans = new LifecycleBean[oldBeans.length + newBeans.size()];
System.arraycopy(oldBeans, 0, mergedBeans, 0, oldBeans.length);
System.arraycopy(newBeans0, 0, mergedBeans, oldBeans.length, newBeans0.length);
cfg.setLifecycleBeans(mergedBeans);
}
}
// Process affinity functions
List<PlatformDotNetAffinityFunction> affFuncs = affinityFunctions(cfg);
if (!affFuncs.isEmpty()) {
for (PlatformDotNetAffinityFunction aff : affFuncs)
aff.init(PlatformConfigurationUtils.readAffinityFunction(in));
}
}
/**
* Find .Net lifecycle beans in configuration.
*
* @param cfg Configuration.
* @return Beans.
*/
private static List<PlatformDotNetLifecycleBean> beans(IgniteConfiguration cfg) {
List<PlatformDotNetLifecycleBean> res = new ArrayList<>();
if (cfg.getLifecycleBeans() != null) {
for (LifecycleBean bean : cfg.getLifecycleBeans()) {
if (bean instanceof PlatformDotNetLifecycleBean)
res.add((PlatformDotNetLifecycleBean)bean);
}
}
return res;
}
/**
* Find .NET affinity functions in configuration.
*
* @param cfg Configuration.
* @return affinity functions.
*/
private static List<PlatformDotNetAffinityFunction> affinityFunctions(IgniteConfiguration cfg) {
List<PlatformDotNetAffinityFunction> res = new ArrayList<>();
CacheConfiguration[] cacheCfg = cfg.getCacheConfiguration();
if (cacheCfg != null) {
for (CacheConfiguration ccfg : cacheCfg) {
if (ccfg.getAffinity() instanceof PlatformDotNetAffinityFunction)
res.add((PlatformDotNetAffinityFunction)ccfg.getAffinity());
}
}
return res;
}
}