private async Task Runner()
        {
            while (true)
            {
                WorkItem it = await queue.ReceiveAsync();

                switch (it.Methode)
                {
                case MethodID.Init: {
                    var promise = (TaskCompletionSource <InitResult>)it.Promise;
                    try {
                        InitResult res = await adapter.Initialize((InitParameter)it.Param1 !, (AdapterCallback)it.Param2 !);

                        promise.SetResult(res);
                    }
                    catch (Exception exp) {
                        promise.SetException(exp);
                    }
                    break;
                }

                case MethodID.Step: {
                    var promise = (TaskCompletionSource <StepResult>)it.Promise;
                    try {
                        var result = await adapter.Step((Timestamp)it.Param1 !, (InputValue[])it.Param2 !);

                        promise.SetResult(result);
                    }
                    catch (Exception exp) {
                        promise.SetException(exp);
                    }
                    break;
                }

                case MethodID.Shutdown: {
                    var promise = (TaskCompletionSource <bool>)it.Promise;
                    try {
                        await adapter.Shutdown();

                        promise.SetResult(true);
                    }
                    catch (Exception exp) {
                        promise.SetException(exp);
                    }
                    return;         // Exit loop
                }
                }
            } // while
        }
Пример #2
0
        public override async Task <InitResult> Initialize(InitParameter parameter, AdapterCallback callback)
        {
            this.callback    = callback;
            this.adapterName = parameter.Calculation.Name;

            var config = new Config(parameter.ModuleConfig);

            string cmd  = GetCommand(config);
            string args = GetArgs(config);

            if (!File.Exists(cmd))
            {
                throw new Exception($"External adapter command '{cmd}' not found.");
            }

            const string portPlaceHolder = "{PORT}";

            if (!args.Contains(portPlaceHolder))
            {
                throw new Exception("Missing port placeholder in args parameter: {PORT}");
            }

            var server = TcpConnectorServer.ListenOnFreePort();
            int port   = server.Port;

            args = args.Replace(portPlaceHolder, port.ToString());

            try {
                var taskConnect = server.WaitForConnect(TimeSpan.FromSeconds(60));

                process = StartProcess(cmd, args);

                while (!process.HasExited && !taskConnect.IsCompleted)
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(50));
                }

                if (process.HasExited)
                {
                    throw new Exception($"Failed to start command \"{cmd}\" with arguments \"{args}\"");
                }

                connection = await taskConnect;

                var parentInfo = new ParentInfoMsg()
                {
                    PID = Process.GetCurrentProcess().Id
                };
                Task ignored = SendVoidRequest(parentInfo);

                var initMsg = new InititializeMsg()
                {
                    Parameter = parameter,
                };

                Task <InitResult> tInit = SendRequest <InitResult>(initMsg);

                taskReceive = connection.ReceiveAndDistribute(onEvent);

                Task t = await Task.WhenAny(tInit, taskReceive);

                if (t != tInit)
                {
                    if (process.HasExited)
                    {
                        throw new Exception("Adapter process terminated during Init call.");
                    }
                    else
                    {
                        throw new Exception("TCP connection broken to Adapter process during Init call.");
                    }
                }

                InitResult res = await tInit;

                Task ignored2 = Supervise();

                return(res);
            }
            catch (Exception) {
                if (connection != null)
                {
                    connection.Close("Init failed.");
                }
                StopProcess(process);
                process = null;
                throw;
            }
            finally {
                server.StopListening();
            }
        }
Пример #3
0
        private async Task InitAdapter(CalcInstance adapter)
        {
            if (adapter.Instance == null)
            {
                throw new Exception("InitAdapter: instance is null");
            }
            Calculation info = adapter.CalcConfig.ToCalculation();

            try {
                var initParams = new InitParameter()
                {
                    Calculation  = info,
                    LastOutput   = adapter.LastOutputValues,
                    LastState    = adapter.LastStateValues,
                    ConfigFolder = Path.GetDirectoryName(base.modelFileName) ?? "",
                    DataFolder   = initInfo.DataFolder,
                    ModuleConfig = moduleConfig.ToNamedValues()
                };
                adapter.State = State.InitStarted;
                InitResult res = await adapter.Instance.Initialize(initParams, new Wrapper(this, info));

                if (adapter.State == State.InitStarted)
                {
                    Config.Input[]  newInputs  = res.Inputs.Select(ip => MakeInput(ip, adapter.CalcConfig)).ToArray();
                    Config.Output[] newOutputs = res.Outputs.Select(ip => MakeOutput(ip, adapter.CalcConfig)).ToArray();
                    Config.State[]  newStates  = res.States.Select(MakeState).ToArray();

                    bool inputsChanged  = !StdJson.ObjectsDeepEqual(adapter.CalcConfig.Inputs, newInputs);
                    bool outputsChanged = !StdJson.ObjectsDeepEqual(adapter.CalcConfig.Outputs, newOutputs);
                    bool statesChanged  = !StdJson.ObjectsDeepEqual(adapter.CalcConfig.States, newStates);

                    var changedMembers = new List <MemberValue>(2);

                    if (inputsChanged)
                    {
                        changedMembers.Add(MemberValue.Make(moduleID, adapter.CalcConfig.ID, "Inputs", DataValue.FromObject(newInputs)));
                    }

                    if (outputsChanged)
                    {
                        changedMembers.Add(MemberValue.Make(moduleID, adapter.CalcConfig.ID, "Outputs", DataValue.FromObject(newOutputs)));
                    }

                    if (statesChanged)
                    {
                        changedMembers.Add(MemberValue.Make(moduleID, adapter.CalcConfig.ID, "States", DataValue.FromObject(newStates)));
                    }

                    if (changedMembers.Count > 0)
                    {
                        await UpdateConfig(GetModuleOrigin(),
                                           updateOrDeleteObjects : new ObjectValue[0],
                                           updateOrDeleteMembers : changedMembers.ToArray(),
                                           addArrayElements : new AddArrayElement[0]);
                    }

                    adapter.State = State.InitComplete;
                }
            }
            catch (Exception e) {
                Exception exp = e.GetBaseException() ?? e;
                adapter.State     = State.InitError;
                adapter.LastError = exp.Message;
                throw new Exception($"Initialize of calculation {info.Name} failed: " + exp.Message, exp);
            }
        }