예제 #1
0
        /// <summary>
        ///
        /// </summary>
        public void Dispose()
        {
            try
            {
                if (sm != null)
                {
                    sm.Dispose();
                    sm = null;
                }
            }
            catch
            {}

            try
            {
                ResponseCrate rc = null;
                foreach (var el in df.ToList())
                {
                    if (df.TryRemove(el.Key, out rc))
                    {
                        if (rc.mre != null)
                        {
                            rc.IsRespOk = false;
                            rc.mre.Set();
                            rc.mre.Dispose();
                            rc.mre = null;
                        }
                    }
                }
            }
            catch
            {
            }
        }
예제 #2
0
        public async Task <bool> AddLogEntryAsync(byte[] data, string entityName = "default", int timeoutMs = 20000)
        {
            if (System.Threading.Interlocked.Read(ref disposed) == 1)
            {
                return(false);
            }

            RaftNode rn = null;

            if (this.raftNodes.TryGetValue(entityName, out rn))
            {
                //Generating externalId
                var msgId    = AsyncResponseHandler.GetMessageId();
                var msgIdStr = msgId.ToBytesString();
                var resp     = new ResponseCrate();
                resp.TimeoutsMs = timeoutMs; //enable for amre
                                             //resp.TimeoutsMs = Int32.MaxValue; //using timeout of the wait handle (not the timer), enable for mre

                //resp.Init_MRE();
                resp.Init_AMRE();

                AsyncResponseHandler.df[msgIdStr] = resp;

                var aler = rn.AddLogEntry(data, msgId);

                switch (aler.AddResult)
                {
                case AddLogEntryResult.eAddLogEntryResult.LOG_ENTRY_IS_CACHED:
                case AddLogEntryResult.eAddLogEntryResult.NODE_NOT_A_LEADER:

                    //async waiting
                    await resp.amre.WaitAsync();        //enable for amre

                    resp.Dispose_MRE();

                    if (AsyncResponseHandler.df.TryRemove(msgIdStr, out resp))
                    {
                        if (resp.IsRespOk)
                        {
                            return(true);
                        }
                    }

                    break;

                default:
                    //case AddLogEntryResult.eAddLogEntryResult.ERROR_OCCURED:
                    //case AddLogEntryResult.eAddLogEntryResult.NO_LEADER_YET:

                    resp.Dispose_MRE();
                    AsyncResponseHandler.df.TryRemove(msgIdStr, out resp);

                    return(false);
                }
            }

            //return new AddLogEntryResult { AddResult = AddLogEntryResult.eAddLogEntryResult.NODE_NOT_FOUND_BY_NAME };
            //return new Tuple<bool, byte[]>(false, null);
            return(false);
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="args">payload which must be send to remote partner</param>
        /// <param name="callBack">if specified then response for the request will be returned into callBack (async). Default is sync.</param>
        /// <param name="timeoutMs">Default 30 sec</param>
        /// <returns></returns>
        public Tuple <bool, byte[]> RemoteRequest(byte[] args, Action <Tuple <bool, byte[]> > callBack = null, int timeoutMs = 30000)
        {
            ulong msgId = sm.GetMessageId();
            var   resp  = new ResponseCrate();

            if (callBack != null)
            {
                //Async return
                resp.callBack = callBack;
                df[msgId]     = resp;
                if (!sm.SendMessage(eMsgType.RpcRequest, msgId, args))
                {
                    df.TryRemove(msgId, out resp);
                    callBack(new Tuple <bool, byte[]>(false, null));
                    return(new Tuple <bool, byte[]>(false, null));
                }

                return(new Tuple <bool, byte[]>(true, null));
            }

            resp.mre = new ManualResetEvent(false);

            df[msgId] = resp;

            if (!sm.SendMessage(eMsgType.RpcRequest, msgId, args))
            {
                if (resp.mre != null)
                {
                    resp.mre.Dispose();
                }
                resp.mre = null;
                df.TryRemove(msgId, out resp);
                return(new Tuple <bool, byte[]>(false, null));
            }
            else if (!resp.mre.WaitOne(timeoutMs))
            {
                if (resp.mre != null)
                {
                    resp.mre.Dispose();
                }
                resp.mre = null;
                df.TryRemove(msgId, out resp);
                return(new Tuple <bool, byte[]>(false, null));
            }

            if (resp.mre != null)
            {
                resp.mre.Dispose();
            }
            resp.mre = null;

            if (df.TryRemove(msgId, out resp))
            {
                return(new Tuple <bool, byte[]>(resp.IsRespOk, resp.res));
            }

            return(new Tuple <bool, byte[]>(false, null));
        }
예제 #4
0
        /// <summary>
        ///
        /// </summary>
        public void Dispose()
        {
            if (System.Threading.Interlocked.CompareExchange(ref Disposed, 1, 0) != 0)
            {
                return;
            }

            //this.sm.SharmIPC.LogException("dispose test",new Exception("p1 "));
            try
            {
                if (tmr != null)
                {
                    tmr.Dispose();
                    tmr = null;
                }
            }
            catch
            { }

            //this.sm.SharmIPC.LogException("dispose test", new Exception("p2"));
            try
            {
                ResponseCrate rc = null;
                foreach (var el in df.ToList())
                {
                    if (df.TryRemove(el.Key, out rc))
                    {
                        rc.IsRespOk = false;
                        rc.Dispose_MRE();
                    }
                }
            }
            catch
            {
            }

            //this.sm.SharmIPC.LogException("dispose test", new Exception("p3"));

            try
            {
                if (sm != null)
                {
                    sm.Dispose();
                    sm = null;
                }
            }
            catch
            { }
        }
예제 #5
0
        /// <summary>
        /// Usage var x = await RemoteRequestAsync(...);
        /// </summary>
        /// <param name="args">payload which must be send to remote partner</param>
        /// <param name="timeoutMs">Default 30 sec</param>
        /// <returns></returns>
        public async Task <Tuple <bool, byte[]> > RemoteRequestAsync(byte[] args, int timeoutMs = 30000)
        {
            if (Interlocked.Read(ref Disposed) == 1)
            {
                return(new Tuple <bool, byte[]>(false, null));
            }

            ulong msgId = sm.GetMessageId();
            var   resp  = new ResponseCrate();

            resp.TimeoutsMs = timeoutMs; //enable for amre
            //resp.TimeoutsMs = Int32.MaxValue; //using timeout of the wait handle (not the timer), enable for mre

            //resp.Init_MRE();
            resp.Init_AMRE();


            df[msgId] = resp;

            if (!sm.SendMessage(eMsgType.RpcRequest, msgId, args))
            {
                resp.Dispose_MRE();
                //if (resp.mre != null)
                //    resp.mre.Dispose();
                //resp.mre = null;
                df.TryRemove(msgId, out resp);
                return(new Tuple <bool, byte[]>(false, null));
            }

            //await resp.mre.AsTask(TimeSpan.FromMilliseconds(timeoutMs));        //enable for mre
            await resp.amre.WaitAsync();    //enable for amre


            resp.Dispose_MRE();

            if (df.TryRemove(msgId, out resp))
            {
                return(new Tuple <bool, byte[]>(resp.IsRespOk, resp.res));
            }

            return(new Tuple <bool, byte[]>(false, null));
        }
예제 #6
0
        /// <summary>
        /// called by external service
        /// </summary>
        /// <param name="data"></param>
        /// <param name="entityName"></param>
        /// <param name="timeoutMs"></param>
        /// <returns></returns>

        public async Task <object> AddLogEntryRequestAsync(byte[] data, string entityName = "default", int timeoutMs = 20000)
        {
            if (System.Threading.Interlocked.Read(ref disposed) == 1)
            {
                return(false);
            }

            RaftStateMachine rn = this.raftNode;;

            {
                //Generating externalId
                var msgId    = AsyncResponseHandler.GetMessageId();
                var msgIdStr = msgId.ToBytesString();
                var resp     = new ResponseCrate();
                resp.TimeoutsMs = timeoutMs; //enable for amre
                resp.Init_AMRE();
                AsyncResponseHandler.df[msgIdStr] = resp;
                var aler = rn.logHandler.ProcessAddLogRequest(data, msgId);
                switch (aler.AddResult)
                {
                case AddLogEntryResult.eAddLogEntryResult.LOG_ENTRY_IS_CACHED:
                case AddLogEntryResult.eAddLogEntryResult.NODE_NOT_A_LEADER:
                    //async waiting
                    resp.amre.Wait();        //enable for amre
                    resp.Dispose_MRE();
                    if (AsyncResponseHandler.df.TryRemove(msgIdStr, out resp))
                    {
                        if (resp.IsRespOk)
                        {
                            return(resp.ReturnValue);
                        }
                    }
                    break;

                default:
                    resp.Dispose_MRE();
                    AsyncResponseHandler.df.TryRemove(msgIdStr, out resp);
                    return(resp.ReturnValue);
                }
            }
            return(null);
        }
예제 #7
0
        SharmIpc(string uniqueHandlerName, long bufferCapacity = 50000, int maxQueueSizeInBytes = 20000000, Action <string, System.Exception> ExternalExceptionHandler = null,
                 eProtocolVersion protocolVersion = eProtocolVersion.V1)
        {
            this.Statistic.ipc = this;

            tmr = new Timer(new TimerCallback((state) =>
            {
                DateTime now = DateTime.UtcNow;

                //This timer is necessary for Calls based on Callbacks, calls based on WaitHandler have their own timeout,
                //That's why for non-callback calls, timeout will be infinite
                List <ulong> toRemove = new List <ulong>();

                //foreach (var el in df.Where(r => now.Subtract(r.Value.created).TotalMilliseconds >= r.Value.TimeoutsMs))
                foreach (var el in df.Where(r => now.Subtract(r.Value.created).TotalMilliseconds >= r.Value.TimeoutsMs).ToList())
                {
                    if (el.Value.callBack != null)
                    {
                        toRemove.Add(el.Key);
                    }
                    else
                    {
                        el.Value.Set_MRE();
                    }
                }

                ResponseCrate rc = null;
                foreach (var el in toRemove)
                {
                    if (df.TryRemove(el, out rc))
                    {
                        rc.callBack(new Tuple <bool, byte[]>(false, null));  //timeout
                    }
                }
            }), null, 10000, 10000);


            this.ExternalExceptionHandler = ExternalExceptionHandler;
            sm = new SharedMemory(uniqueHandlerName, this, bufferCapacity, maxQueueSizeInBytes, protocolVersion);
        }
예제 #8
0
        /// <summary>
        /// Any incoming data from remote partner is accumulated here
        /// </summary>
        /// <param name="msgType"></param>
        /// <param name="msgId"></param>
        /// <param name="bt"></param>
        void InternalDataArrived(eMsgType msgType, ulong msgId, byte[] bt)
        {
            ResponseCrate rsp = null;

            switch (msgType)
            {
            case eMsgType.Request:

                Task.Run(() =>
                {
                    if (AsyncRemoteCallHandler != null)
                    {
                        AsyncRemoteCallHandler(msgId, bt);
                        //Answer must be supplied via AsyncAnswerOnRemoteCall
                    }
                    else
                    {
                        this.remoteCallHandler(bt);
                    }
                });

                break;

            case eMsgType.RpcRequest:

                Task.Run(() =>
                {
                    if (AsyncRemoteCallHandler != null)
                    {
                        AsyncRemoteCallHandler(msgId, bt);
                        //Answer must be supplied via AsyncAnswerOnRemoteCall
                    }
                    else
                    {
                        var res = this.remoteCallHandler(bt);
                        sm.SendMessage(res.Item1 ? eMsgType.RpcResponse : eMsgType.ErrorInRpc, sm.GetMessageId(), res.Item2, msgId);
                    }
                });

                break;

            case eMsgType.ErrorInRpc:
            case eMsgType.RpcResponse:

                if (df.TryGetValue(msgId, out rsp))
                {
                    rsp.res      = bt;
                    rsp.IsRespOk = msgType == eMsgType.RpcResponse;

                    if (rsp.callBack == null)
                    {
                        rsp.mre.Set();
                    }
                    else
                    {
                        df.TryRemove(msgId, out rsp);
                        rsp.callBack(new Tuple <bool, byte[]>(rsp.IsRespOk, bt));
                    }
                }

                break;
            }
        }
예제 #9
0
        //internal void InternalDataArrived(eMsgType msgType, ulong msgId, byte[] bt)
        //{
        //    ResponseCrate rsp = null;

        //    switch (msgType)
        //    {
        //        case eMsgType.Request:


        //            if (AsyncRemoteCallHandler != null)
        //            {
        //                RunAsync(msgId, bt);
        //            }
        //            else
        //            {
        //                RunV1(bt);

        //            }

        //            break;
        //        case eMsgType.RpcRequest:

        //            if (AsyncRemoteCallHandler != null)
        //            {
        //                RunAsync(msgId, bt);
        //                //Answer must be supplied via AsyncAnswerOnRemoteCall
        //            }
        //            else
        //            {
        //                Run(msgId, bt);
        //            }


        //            break;
        //        case eMsgType.ErrorInRpc:
        //        case eMsgType.RpcResponse:

        //            if (df.TryGetValue(msgId, out rsp))
        //            {
        //                rsp.res = bt;
        //                rsp.IsRespOk = msgType == eMsgType.RpcResponse;

        //                if (rsp.callBack == null)
        //                {

        //                    //rsp.mre.Set();  //Signalling, to make waiting in parallel thread to proceed
        //                    rsp.Set_MRE();
        //                }
        //                else
        //                {
        //                    df.TryRemove(msgId, out rsp);
        //                    //Calling callback in parallel thread, quicly to return to ReaderWriterhandler.Reader procedure
        //                    RunV2(rsp, bt);

        //                }
        //            }

        //            break;
        //    }
        //}

        //async Task RunAsync(ulong msgId, byte[] bt)
        //{
        //    AsyncRemoteCallHandler(msgId, bt);
        //}

        //async Task Run(ulong msgId, byte[] bt)
        //{
        //    var res = this.remoteCallHandler(bt);
        //    sm.SendMessage(res.Item1 ? eMsgType.RpcResponse : eMsgType.ErrorInRpc, sm.GetMessageId(), res.Item2, msgId);
        //}

        //async Task RunV1(byte[] bt)
        //{
        //    this.remoteCallHandler(bt);
        //}

        //async Task RunV2(ResponseCrate rsp, byte[] bt)
        //{
        //    rsp.callBack(new Tuple<bool, byte[]>(rsp.IsRespOk, bt));
        //}


        /// <summary>
        ///
        /// </summary>
        /// <param name="args">payload which must be send to remote partner</param>
        /// <param name="callBack">if specified then response for the request will be returned into callBack (async). Default is sync.</param>
        /// <param name="timeoutMs">Default 30 sec</param>
        /// <returns></returns>
        public Tuple <bool, byte[]> RemoteRequest(byte[] args, Action <Tuple <bool, byte[]> > callBack = null, int timeoutMs = 30000)
        {
            ulong msgId = sm.GetMessageId();
            var   resp  = new ResponseCrate();


            if (callBack != null)
            {
                resp.TimeoutsMs = timeoutMs; //IS NECESSARY FOR THE CALLBACK TYPE OF RETURN

                //Async return
                resp.callBack = callBack;
                df[msgId]     = resp;
                if (!sm.SendMessage(eMsgType.RpcRequest, msgId, args))
                {
                    df.TryRemove(msgId, out resp);
                    callBack(new Tuple <bool, byte[]>(false, null));
                    return(new Tuple <bool, byte[]>(false, null));
                }

                return(new Tuple <bool, byte[]>(true, null));
            }

            resp.TimeoutsMs = Int32.MaxValue; //using timeout of the wait handle (not the timer)


            //resp.mre = new ManualResetEvent(false);
            resp.Init_MRE();

            df[msgId] = resp;

            if (!sm.SendMessage(eMsgType.RpcRequest, msgId, args))
            {
                resp.Dispose_MRE();
                //if (resp.mre != null)
                //    resp.mre.Dispose();
                //resp.mre = null;
                df.TryRemove(msgId, out resp);
                return(new Tuple <bool, byte[]>(false, null));
            }
            //else if (!resp.mre.WaitOne(timeoutMs))
            else if (!resp.WaitOne_MRE(timeoutMs))
            {
                //--STAT
                this.Statistic.Timeout();

                //if (resp.mre != null)
                //    resp.mre.Dispose();
                //resp.mre = null;
                resp.Dispose_MRE();
                df.TryRemove(msgId, out resp);
                return(new Tuple <bool, byte[]>(false, null));
            }

            //if (resp.mre != null)
            //    resp.mre.Dispose();
            //resp.mre = null;
            resp.Dispose_MRE();

            if (df.TryRemove(msgId, out resp))
            {
                return(new Tuple <bool, byte[]>(resp.IsRespOk, resp.res));
            }

            return(new Tuple <bool, byte[]>(false, null));
        }
예제 #10
0
        //async Task CallAsyncRemoteHandler(ulong msgId, byte[] bt)
        //{
        //    AsyncRemoteCallHandler(msgId, bt);
        //}

        /// <summary>
        /// Any incoming data from remote partner is accumulated here
        /// </summary>
        /// <param name="msgType"></param>
        /// <param name="msgId"></param>
        /// <param name="bt"></param>
        internal void InternalDataArrived(eMsgType msgType, ulong msgId, byte[] bt)
        {
            ResponseCrate rsp = null;

            switch (msgType)
            {
            case eMsgType.Request:

                Task.Run(() =>
                {
                    if (AsyncRemoteCallHandler != null)
                    {
                        //CallAsyncRemoteHandler(msgId, bt);
                        AsyncRemoteCallHandler(msgId, bt);
                        //Answer must be supplied via AsyncAnswerOnRemoteCall
                    }
                    else
                    {
                        this.remoteCallHandler(bt);
                    }
                });

                break;

            case eMsgType.RpcRequest:

                Task.Run(() =>
                {
                    if (AsyncRemoteCallHandler != null)
                    {
                        AsyncRemoteCallHandler(msgId, bt);
                        //Answer must be supplied via AsyncAnswerOnRemoteCall
                    }
                    else
                    {
                        var res = this.remoteCallHandler(bt);
                        sm.SendMessage(res.Item1 ? eMsgType.RpcResponse : eMsgType.ErrorInRpc, sm.GetMessageId(), res.Item2, msgId);
                    }
                });

                break;

            case eMsgType.ErrorInRpc:
            case eMsgType.RpcResponse:

                if (df.TryGetValue(msgId, out rsp))
                {
                    rsp.res      = bt;
                    rsp.IsRespOk = msgType == eMsgType.RpcResponse;

                    if (rsp.callBack == null)
                    {
                        //rsp.mre.Set();  //Signalling, to make waiting in parallel thread to proceed
                        rsp.Set_MRE();
                    }
                    else
                    {
                        df.TryRemove(msgId, out rsp);
                        //Calling callback in parallel thread, quicly to return to ReaderWriterhandler.Reader procedure
                        Task.Run(() =>
                        {
                            rsp.callBack(new Tuple <bool, byte[]>(rsp.IsRespOk, bt));
                        });
                    }
                }

                break;
            }
        }
예제 #11
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="args">payload which must be send to remote partner</param>
        /// <param name="callBack">if specified then response for the request will be returned into callBack (async). Default is sync.</param>
        /// <param name="timeoutMs">Default 30 sec</param>
        /// <returns></returns>
        public Tuple<bool, byte[]> RemoteRequest(byte[] args, Action<Tuple<bool, byte[]>> callBack = null, int timeoutMs = 30000)
        {
       
            ulong msgId = sm.GetMessageId();
            var resp = new ResponseCrate();

            if (callBack != null)
            {
                //Async return
                resp.callBack = callBack;
                df[msgId] = resp;
                if (!sm.SendMessage(eMsgType.RpcRequest, msgId, args))
                {
                    df.TryRemove(msgId, out resp);
                    callBack(new Tuple<bool, byte[]>(false, null));
                    return new Tuple<bool, byte[]>(false, null);
                }

                return new Tuple<bool, byte[]>(true, null);
            }

            resp.mre = new ManualResetEvent(false);

            df[msgId] = resp;          

            if (!sm.SendMessage(eMsgType.RpcRequest, msgId, args))
            {
                if (resp.mre != null)
                    resp.mre.Dispose();
                resp.mre = null;
                df.TryRemove(msgId, out resp);
                return new Tuple<bool, byte[]>(false, null);
            }
            else if (!resp.mre.WaitOne(timeoutMs))
            {
                if (resp.mre != null)
                    resp.mre.Dispose();
                resp.mre = null;
                df.TryRemove(msgId, out resp);
                return new Tuple<bool, byte[]>(false, null);
            }

            if (resp.mre != null)
                resp.mre.Dispose();
            resp.mre = null;

            if (df.TryRemove(msgId, out resp))
            {
                return new Tuple<bool, byte[]>(resp.IsRespOk, resp.res);
            }

            return new Tuple<bool, byte[]>(false, null);
        }