Example #1
0
            /// <summary>
            /// Seek an async handler on the min number of requests queued in memory and its associated socket connection
            /// </summary>
            /// <returns>An async handler if found; and null or nothing if no connection is found</returns>
            public virtual THandler Seek()
            {
                THandler h = null;

                lock (m_cs)
                {
                    foreach (CClientSocket cs in m_dicSocketHandler.Keys)
                    {
                        if (cs.ConnectionState < tagConnectionState.csSwitched)
                        {
                            continue;
                        }
                        if (h == null)
                        {
                            h = m_dicSocketHandler[cs];
                        }
                        else
                        {
                            IClientQueue cq       = h.Socket.ClientQueue;
                            ulong        cs_coriq = cq.Available ? cq.MessageCount : cs.CountOfRequestsInQueue;
                            cq = h.Socket.ClientQueue;
                            ulong h_coriq = cq.Available ? cq.MessageCount : h.Socket.CountOfRequestsInQueue;
                            if (cs_coriq < h_coriq)
                            {
                                h = m_dicSocketHandler[cs];
                            }
                            else if (cs_coriq == h_coriq && cs.BytesSent < h.Socket.BytesSent)
                            {
                                h = m_dicSocketHandler[cs];
                            }
                        }
                    }
                }
                return(h);
            }
Example #2
0
            /// <summary>
            /// Seek an async handler on the min number of requests queued and its associated socket connection
            /// </summary>
            /// <returns>An async handler if found; and null or nothing if no proper queue is available</returns>
            public virtual THandler SeekByQueue()
            {
                THandler h = null;

                lock (m_cs)
                {
                    foreach (CClientSocket cs in m_dicSocketHandler.Keys)
                    {
                        IClientQueue cq = cs.ClientQueue;
                        if (!cq.Available || cq.JobSize > 0 /*queue is in transaction at this time*/)
                        {
                            continue;
                        }
                        if (h == null)
                        {
                            h = m_dicSocketHandler[cs];
                        }
                        else if ((cq.MessageCount < h.Socket.ClientQueue.MessageCount) || (cs.Connected && !h.Socket.Connected))
                        {
                            h = m_dicSocketHandler[cs];
                        }
                    }
                }
                return(h);
            }
Example #3
0
            /// <summary>
            /// End enqueuing messages with transaction style. Currently, total size of queued messages must be less than 4 G bytes
            /// </summary>
            /// <param name="rollback">true for rollback, and false for committing</param>
            /// <param name="qt">A callback for tracking returning error code, which can be one of QUEUE_OK, QUEUE_TRANS_NOT_STARTED_YET, and so on</param>
            /// <param name="discarded">a callback for tracking cancel or socket closed event</param>
            /// <returns>true for sending the request successfully, and false for failure</returns>
            public virtual bool EndQueueTrans(bool rollback, DQueueTrans qt, DDiscarded discarded)
            {
                bool ok = SendRequest(idEndTrans, rollback, (ar) =>
                {
                    if (qt != null)
                    {
                        int errCode;
                        ar.UQueue.Load(out errCode);
                        qt((CAsyncQueue)ar.AsyncServiceHandler, errCode);
                    }
                    else
                    {
                        ar.UQueue.SetSize(0);
                    }
                }, discarded, (DOnExceptionFromServer)null);
                IClientQueue cq = AttachedClientSocket.ClientQueue;

                if (cq.Available)
                {
                    if (rollback)
                    {
                        cq.AbortJob();
                    }
                    else
                    {
                        cq.EndJob();
                    }
                }
                return(ok);
            }
Example #4
0
            /// <summary>
            /// Start enqueuing messages with transaction style. Currently, total size of queued messages must be less than 4 G bytes
            /// </summary>
            /// <param name="key">An ASCII string for identifying a queue at server side</param>
            /// <param name="qt">A callback for tracking returning error code, which can be one of QUEUE_OK, QUEUE_TRANS_ALREADY_STARTED, and so on</param>
            /// <returns>true for sending the request successfully, and false for failure</returns>
            public bool StartQueueTrans(byte[] key, DQueueTrans qt)
            {
                IClientQueue cq = AttachedClientSocket.ClientQueue;

                if (cq.Available)
                {
                    cq.StartJob();
                }
                using (CScopeUQueue sq = new CScopeUQueue())
                {
                    sq.UQueue.Save(key);
                    return(SendRequest(idStartTrans, sq, (ar) =>
                    {
                        if (qt != null)
                        {
                            int errCode;
                            ar.UQueue.Load(out errCode);
                            qt((CAsyncQueue)ar.AsyncServiceHandler, errCode);
                        }
                        else
                        {
                            ar.UQueue.SetSize(0);
                        }
                    }));
                }
            }
Example #5
0
            /// <summary>
            /// Seek an async handler on the min number of requests queued and its associated socket connection
            /// </summary>
            /// <returns>An async handler if found; and null or nothing if no proper queue is available</returns>
            public virtual THandler SeekByQueue()
            {
                THandler h = null;

                lock (m_cs)
                {
                    bool automerge = (ClientCoreLoader.GetQueueAutoMergeByPool(m_nPoolId) > 0);
                    foreach (CClientSocket cs in m_dicSocketHandler.Keys)
                    {
                        if (automerge && cs.ConnectionState < tagConnectionState.csSwitched)
                        {
                            continue;
                        }
                        IClientQueue cq = cs.ClientQueue;
                        if (!cq.Available || cq.JobSize > 0 /*queue is in transaction at this time*/)
                        {
                            continue;
                        }
                        if (h == null)
                        {
                            h = m_dicSocketHandler[cs];
                        }
                        else if ((cq.MessageCount < h.AttachedClientSocket.ClientQueue.MessageCount) || (cs.Connected && !h.AttachedClientSocket.Connected))
                        {
                            h = m_dicSocketHandler[cs];
                        }
                    }
                }
                return(h);
            }
Example #6
0
        /// <summary>
        /// Lock an asynchronous handler from socket pool. You must call this method with UnlockByMyAlgorithm in pair
        /// </summary>
        /// <param name="timeout">The max time for locking a handler in ms</param>
        /// <returns>A SQL handler from socket pool</returns>
        public CSql LockByMyAlgorithm(int timeout)
        {
            CSql sql = null;

            System.Threading.Monitor.Enter(m_cs);
            while (timeout >= 0)
            {
                CClientSocket ret = null;
                foreach (CClientSocket cs in m_dicSocketHandler.Keys)
                {
                    IClientQueue cq = cs.ClientQueue;
                    if (!cq.Available || cq.JobSize > 0 /*queue is in transaction at this time*/)
                    {
                        continue; //A null handler may return if local message queue is in transaction
                    }
                    if (ret == null)
                    {
                        ret = cs;
                    }
                    else if (cs.Connected)
                    {
                        if (!ret.Connected)
                        {
                            ret = cs;
                        }
                        else if (cq.MessageCount < ret.ClientQueue.MessageCount)
                        {
                            ret = cs;
                        }
                    }
                    else if (!ret.Connected && cq.MessageCount < ret.ClientQueue.MessageCount)
                    {
                        ret = cs;
                    }
                }
                if (ret != null)
                {
                    sql = m_dicSocketHandler[ret];
                    m_dicSocketHandler.Remove(ret);
                }
                if (sql != null)
                {
                    break;
                }
                System.DateTime dtNow = System.DateTime.Now;
                bool            ok    = System.Threading.Monitor.Wait(m_cs, timeout);
                int             ts    = (int)(System.DateTime.Now - dtNow).TotalMilliseconds;
                if (!ok || timeout <= ts)
                {
                    break;
                }
                timeout -= ts;
            }
            System.Threading.Monitor.Exit(m_cs);
            return(sql); //A null handler may return in case time-out
        }
Example #7
0
        public bool AbortJob()
        {
            IClientQueue src = SourceQueue;

            if (src == null || !src.Available)
            {
                return(false);
            }
            return(src.AbortJob());
        }
Example #8
0
        /// <summary>
        /// Make a replication. An invalid operation exception will be thrown if not replicable.
        /// </summary>
        /// <returns>True for success; and false for failure</returns>
        public bool DoReplication()
        {
            if (m_mapQueueConn.Count == 1)
            {
                throw new InvalidOperationException("No replication is allowed because the number of target message queues less than two");
            }
            IClientQueue src = SourceQueue;

            if (src == null)
            {
                return(false);
            }
            return(src.AppendTo(TargetQueues));
        }
Example #9
0
        public bool EndJob()
        {
            IClientQueue src = SourceQueue;

            if (src == null || !src.Available)
            {
                return(false);
            }
            bool ok = src.EndJob();

            if (ok && Replicable)
            {
                ok = src.AppendTo(TargetQueues);
            }
            return(ok);
        }
Example #10
0
        virtual public bool Send(ushort reqId, byte[] data, uint len)
        {
            CAsyncServiceHandler.DAsyncResultHandler ash = null;
            THandler src = SourceHandler;

            if (src == null)
            {
                return(false);
            }
            IClientQueue cq = src.AttachedClientSocket.ClientQueue;

            if (!cq.Available)
            {
                return(false);
            }
            bool ok = src.SendRequest(reqId, data, len, ash);

            if (Replicable && cq.JobSize == 0)
            {
                ok = cq.AppendTo(TargetQueues);
            }
            return(ok);
        }
Example #11
0
 public bool EnsureAppending(IClientQueue clientQueue)
 {
     if (clientQueue == null)
         return true;
     IntPtr[] queueHandles = { clientQueue.Handle };
     return EnsureAppending(queueHandles);
 }
Example #12
0
        /// <summary>
        /// Send affected record set from a trigger for table update, delete or insert onto one or more remote SocketPro servers with auto replication if required.
        /// </summary>
        /// <param name="tableName">A valid table name</param>
        /// <param name="param">An extra info data. For example, a trigger name</param>
        /// <param name="batchSize">The size of a set of records in byte. It defaults to CAsyncAdoSerializationHelper.DEFAULT_BATCH_SIZE</param>
        /// <returns>True for success; and false for failure</returns>
        public virtual bool SendDmlTrigger(string tableName, object param, uint batchSize)
        {
            bool jobing = false;
            bool ok     = true;

            if (tableName == null)
            {
                throw new ArgumentNullException("A valid table name required");
            }
            if (tableName.Length == 0)
            {
                throw new ArgumentException("A valid table name required");
            }

            IClientQueue srcQueue = SourceQueue;

            if (srcQueue == null || !srcQueue.Available)
            {
                throw new InvalidOperationException("No queue available for persisting data");
            }

            TriggerAction ta = SqlContext.TriggerContext.TriggerAction;

            using (SqlConnection conn = new SqlConnection("context connection=true"))
            {
                CAsyncServiceHandler.DAsyncResultHandler arh = null;
                SqlDataReader dr = null;
                try
                {
                    conn.Open();
                    lock (m_csSs)
                    {
                        jobing = (srcQueue.JobSize != 0);
                        THandler h = SourceHandler;
                        try
                        {
                            if (!jobing)
                            {
                                ok = StartJob();
                            }
                            switch (ta)
                            {
                            case TriggerAction.Update:
                            case TriggerAction.Delete:
                            case TriggerAction.Insert:
                                ok = h.SendRequest(CAsyncAdoSerializationHelper.idDmlTriggerMessage, (int)ta, Utilities.GetObjectFullName(conn, tableName, "U"), param, arh);
                                break;

                            default:
                                throw new InvalidOperationException("SendDmlTrigger for table update, insert and delete events only");
                            }

                            if (ta == TriggerAction.Update || ta == TriggerAction.Delete)
                            {
                                SqlCommand cmd = new SqlCommand("select * from deleted", conn);
                                dr = cmd.ExecuteReader();
                                ok = h.Send(dr, batchSize);
                                dr.Close();
                            }

                            if (ta == TriggerAction.Update || ta == TriggerAction.Insert)
                            {
                                SqlCommand cmd = new SqlCommand("select * from inserted", conn);
                                dr = cmd.ExecuteReader();
                                ok = h.Send(dr, batchSize);
                                dr.Close();
                            }

                            if (!jobing)
                            {
                                ok = EndJob();
                            }
                            ok = true;
                        }
                        catch
                        {
                            if (dr != null)
                            {
                                dr.Close();
                            }
                            if (!jobing)
                            {
                                ok = AbortJob();
                            }
                            ok = false;
                        }
                    }
                }
                finally
                {
                    conn.Close();
                }
            }
            return(ok);
        }
Example #13
0
        /// <summary>
        /// Send a record set from a given query statement onto one or more remote SocketPro servers with auto replication if required
        /// </summary>
        /// <param name="sqlQuery">A statement creating a set of records</param>
        /// <param name="recordsetName">An string name for this record set</param>
        /// <param name="batchSize">The size of a set of records in byte. It defaults to CAsyncAdoSerializationHelper.DEFAULT_BATCH_SIZE</param>
        public virtual bool Send(string sqlQuery, string recordsetName, uint batchSize)
        {
            bool ok     = false;
            bool jobing = false;

            if (sqlQuery == null || sqlQuery.Length == 0)
            {
                throw new ArgumentException("A valid sql select query required");
            }
            IClientQueue srcQueue = SourceQueue;

            if (srcQueue == null || !srcQueue.Available)
            {
                throw new InvalidOperationException("No queue available for persisting data");
            }
            using (SqlConnection conn = new SqlConnection("context connection=true"))
            {
                CAsyncServiceHandler.DAsyncResultHandler arh = null;
                SqlDataReader dr = null;
                try
                {
                    conn.Open();
                    lock (m_csSs)
                    {
                        jobing = (srcQueue.JobSize != 0);
                        THandler h = SourceHandler;
                        try
                        {
                            if (!jobing)
                            {
                                ok = StartJob();
                            }
                            ok = h.SendRequest(CAsyncAdoSerializationHelper.idRecordsetName, recordsetName, arh);
                            SqlCommand cmd = new SqlCommand(sqlQuery, conn);
                            dr = cmd.ExecuteReader();
                            do
                            {
                                ok = h.Send(dr, batchSize);
                            } while (dr.NextResult());
                            dr.Close();
                            if (!jobing)
                            {
                                ok = EndJob();
                            }
                            ok = true;
                        }
                        catch
                        {
                            if (dr != null)
                            {
                                dr.Close();
                            }
                            if (!jobing)
                            {
                                ok = AbortJob();
                            }
                            ok = false;
                        }
                    }
                }
                finally
                {
                    conn.Close();
                }
            }
            return(ok);
        }
Example #14
0
 public bool AppendTo(IClientQueue[] clientQueues)
 {
     if (clientQueues == null || clientQueues.Length == 0)
         return true;
     List<IntPtr> qs = new List<IntPtr>();
     foreach (IClientQueue cq in clientQueues)
     {
         qs.Add(cq.Handle);
     }
     return AppendTo(qs.ToArray());
 }
Example #15
0
        private bool Transfer()
        {
            int index = 0;
            DAsyncResultHandler    rh = null;
            DOnExceptionFromServer se = null;
            CClientSocket          cs = AttachedClientSocket;

            if (!cs.Sendable)
            {
                return(false);
            }
            uint sent_buffer_size = cs.BytesInSendingBuffer;

            if (sent_buffer_size > 3 * STREAM_CHUNK_SIZE)
            {
                return(true);
            }
            while (index < m_vContext.Count)
            {
                CContext context = m_vContext[index];
                if (context.Sent)
                {
                    ++index;
                    continue;
                }
                if (context.Uploading && context.Tried && context.File == null)
                {
                    if (index == 0)
                    {
                        if (context.Upload != null)
                        {
                            context.Upload(this, CANNOT_OPEN_LOCAL_FILE_FOR_READING, context.ErrMsg);
                        }
                        m_vContext.RemoveFromFront();
                    }
                    else
                    {
                        ++index;
                    }
                    continue;
                }
                if (context.Uploading)
                {
                    if (!context.Tried)
                    {
                        context.Tried = true;
                        try
                        {
                            FileShare fs = FileShare.None;
                            if ((context.Flags & FILE_OPEN_SHARE_READ) == FILE_OPEN_SHARE_READ)
                            {
                                fs = FileShare.Read;
                            }
                            context.File     = new FileStream(context.LocalFile, FileMode.Open, FileAccess.Read, fs);
                            context.FileSize = context.File.Length;
                            IClientQueue cq = AttachedClientSocket.ClientQueue;
                            if (cq.Available)
                            {
                                if (!cq.StartJob())
                                {
                                    context.File.Close();
                                    context.File = null;
                                    throw new Exception("Cannot start queue job");
                                }
                            }
                            if (!SendRequest(idUpload, context.FilePath, context.Flags, context.FileSize, rh, context.Discarded, se))
                            {
                                return(false);
                            }
                        }
                        catch (Exception err)
                        {
                            context.ErrMsg = err.Message;
                        }
                        finally { }
                    }
                    if (context.File == null)
                    {
                        if (index == 0)
                        {
                            if (context.Upload != null)
                            {
                                context.Upload(this, CANNOT_OPEN_LOCAL_FILE_FOR_READING, context.ErrMsg);
                            }
                            m_vContext.RemoveFromFront();
                        }
                        else
                        {
                            ++index;
                        }
                        continue;
                    }
                    else
                    {
                        using (CScopeUQueue sb = new CScopeUQueue())
                        {
                            if (sb.UQueue.MaxBufferSize < STREAM_CHUNK_SIZE)
                            {
                                sb.UQueue.Realloc(STREAM_CHUNK_SIZE);
                            }
                            byte[] buffer = sb.UQueue.IntenalBuffer;
                            int    ret    = context.File.Read(buffer, 0, (int)STREAM_CHUNK_SIZE);
                            while (ret > 0)
                            {
                                if (!SendRequest(idUploading, buffer, (uint)ret, rh, context.Discarded, se))
                                {
                                    return(false);
                                }
                                sent_buffer_size = cs.BytesInSendingBuffer;
                                if (ret < (int)STREAM_CHUNK_SIZE)
                                {
                                    break;
                                }
                                if (sent_buffer_size >= 5 * STREAM_CHUNK_SIZE)
                                {
                                    break;
                                }
                                ret = context.File.Read(buffer, 0, (int)STREAM_CHUNK_SIZE);
                            }
                            if (ret < (int)STREAM_CHUNK_SIZE)
                            {
                                context.Sent = true;
                                if (!SendRequest(idUploadCompleted, rh, context.Discarded, se))
                                {
                                    return(false);
                                }
                                IClientQueue cq = AttachedClientSocket.ClientQueue;
                                if (cq.Available)
                                {
                                    cq.EndJob();
                                }
                            }
                            if (sent_buffer_size >= 4 * STREAM_CHUNK_SIZE)
                            {
                                break;
                            }
                        }
                    }
                }
                else
                {
                    if (!SendRequest(idDownload, context.FilePath, context.Flags, rh, context.Discarded, se))
                    {
                        return(false);
                    }
                    context.Sent     = true;
                    context.Tried    = true;
                    sent_buffer_size = cs.BytesInSendingBuffer;
                    if (sent_buffer_size > 3 * STREAM_CHUNK_SIZE)
                    {
                        break;
                    }
                }
                ++index;
            }
            return(true);
        }
Example #16
0
            private void OnSPEvent(uint poolId, tagSocketPoolEvent spe, IntPtr h)
            {
                THandler handler = MapToHandler(h);

                switch (spe)
                {
                case tagSocketPoolEvent.speTimer:
                    if (CScopeUQueue.MemoryConsumed / 1024 > CScopeUQueue.SHARED_BUFFER_CLEAN_SIZE)
                    {
                        CScopeUQueue.DestroyUQueuePool();
                    }
                    break;

                case tagSocketPoolEvent.speStarted:
                    lock (m_cs)
                    {
                        m_nPoolId = poolId;
                    }
                    break;

                case tagSocketPoolEvent.speShutdown:
                    lock (m_cs)
                    {
                        m_dicSocketHandler.Clear();
                    }
                    break;

                case tagSocketPoolEvent.speUSocketCreated:
                {
                    CClientSocket cs = new CClientSocket();
                    cs.Set(h);
                    ClientCoreLoader.SetRecvTimeout(h, m_recvTimeout);
                    ClientCoreLoader.SetConnTimeout(h, m_connTimeout);
                    ClientCoreLoader.SetAutoConn(h, (byte)(m_autoConn ? 1 : 0));
                    handler = new THandler();
                    if (handler.SvsID == 0)
                    {
                        handler.m_nServiceId = m_ServiceId;
                    }
                    if (handler.SvsID <= SocketProAdapter.BaseServiceID.sidStartup)
                    {
                        throw new InvalidOperationException("Service id must be larger than SocketProAdapter.BaseServiceID.sidStartup");
                    }
                    handler.Attach(cs);
                    lock (m_cs)
                    {
                        m_dicSocketHandler[cs] = handler;
                    }
                }
                break;

                case tagSocketPoolEvent.speUSocketKilled:
                    if (handler != null)
                    {
                        lock (m_cs)
                        {
                            m_dicSocketHandler.Remove(handler.AttachedClientSocket);
                        }
                    }
                    break;

                case tagSocketPoolEvent.speConnecting:
                    break;

                case tagSocketPoolEvent.speConnected:
                    if (ClientCoreLoader.IsOpened(h) != 0)
                    {
                        CClientSocket cs = handler.AttachedClientSocket;
                        if (DoSslServerAuthentication != null && cs.EncryptionMethod == tagEncryptionMethod.TLSv1 && !DoSslServerAuthentication.Invoke(this, cs))
                        {
                            return;     //don't set password or call SwitchTo in case failure of ssl server authentication on certificate from server
                        }
                        ClientCoreLoader.SetSockOpt(h, tagSocketOption.soRcvBuf, 116800, tagSocketLevel.slSocket);
                        ClientCoreLoader.SetSockOpt(h, tagSocketOption.soSndBuf, 116800, tagSocketLevel.slSocket);
                        ClientCoreLoader.SetSockOpt(h, tagSocketOption.soTcpNoDelay, 1, tagSocketLevel.slTcp);
                        ClientCoreLoader.SetPassword(h, cs.ConnectionContext.GetPassword());
                        bool ok = ClientCoreLoader.StartBatching(h) != 0;
                        ok = ClientCoreLoader.SwitchTo(h, handler.SvsID) != 0;
                        ok = ClientCoreLoader.TurnOnZipAtSvr(h, (byte)(cs.ConnectionContext.Zip ? 1 : 0)) != 0;
                        ok = ClientCoreLoader.SetSockOptAtSvr(h, tagSocketOption.soRcvBuf, 116800, tagSocketLevel.slSocket) != 0;
                        ok = ClientCoreLoader.SetSockOptAtSvr(h, tagSocketOption.soSndBuf, 116800, tagSocketLevel.slSocket) != 0;
                        ok = ClientCoreLoader.SetSockOptAtSvr(h, tagSocketOption.soTcpNoDelay, 1, tagSocketLevel.slTcp) != 0;
                        ok = (ClientCoreLoader.CommitBatching(h, (byte)0) != 0);
                    }
                    break;

                case tagSocketPoolEvent.speQueueMergedFrom:
                    m_pHFrom = MapToHandler(h);
#if DEBUG
                    IClientQueue cq        = m_pHFrom.AttachedClientSocket.ClientQueue;
                    uint         remaining = (uint)m_pHFrom.RequestsQueued;
                    if (cq.MessageCount != remaining)
                    {
                        Console.WriteLine("From: Messages = {0}, remaining requests = {1}", cq.MessageCount, remaining);
                    }
#endif
                    break;

                case tagSocketPoolEvent.speQueueMergedTo:
                {
                    THandler to = MapToHandler(h);
                    m_pHFrom.AppendTo(to);
                    m_pHFrom = null;
                }
                break;

                default:
                    break;
                }
                if (SocketPoolEvent != null)
                {
                    SocketPoolEvent.Invoke(this, spe, handler);
                }
                OnSocketPoolEvent(spe, handler);
                if (spe == tagSocketPoolEvent.speConnected && ClientCoreLoader.IsOpened(h) != 0)
                {
                    SetQueue(handler.AttachedClientSocket);
                }
            }
Example #17
0
 public bool AppendTo(IClientQueue clientQueue)
 {
     if (clientQueue == null)
         return true;
     IntPtr[] queueHandles = { clientQueue.Handle };
     return AppendTo(queueHandles);
 }