/// <summary>
        /// Hanlde cluster-wide Remove(key) requests.
        /// </summary>
        /// <param name="info">the object containing parameters for this operation.</param>
        /// <returns>object to be sent back to the requestor.</returns>
        /// <remarks>
        /// Removes an item locally; however without generating notifications. 
        /// <para>
        /// <b>Note:</b> When a client invokes <see cref="handleRemove"/>; it is the clients reponsibility
        /// to actaully initiate the notification.
        /// </para>
        /// </remarks>
        private object handleRemove(Address src, object info)
        {
            try
            {
                object result = null;

                if (info is object[])
                {
                    object[] args = info as Object[];
                    CallbackEntry cbEntry = null;
                    OperationContext operationContext = null;

                    if (args.Length > 3)
                        cbEntry = args[3] as CallbackEntry;

                    if (args.Length > 6)
                        operationContext = args[6] as OperationContext;
                    else if (args.Length > 4)
                        operationContext = args[4] as OperationContext;
                    else if (args.Length > 2)
                        operationContext = args[2] as OperationContext;
                    if (args != null && args.Length > 0)
                    {
                        object tmp = args[0];
                        if (tmp is Object[])
                        {
                            result = Local_Remove((object[])tmp, ItemRemoveReason.Removed, src, cbEntry,  true, operationContext);
                        }
                        else
                        {
                            object lockId = args[4];
                            LockAccessType accessType = (LockAccessType)args[5];

                            CacheEntry entry = Local_Remove(tmp, ItemRemoveReason.Removed, src, cbEntry,  true, lockId,  accessType, operationContext);
                            /* send value and entry seperaty*/
                            OperationResponse opRes = new OperationResponse();
                            if (entry != null)
                            {
                                opRes.UserPayload = (entry.Value is CallbackEntry ? ((CallbackEntry)entry.Value).UserData : entry.UserData);
                                opRes.SerializablePayload = entry.CloneWithoutValue();
                            }
                            result = opRes;
                        }
                    }
                }

                /// Only the coordinator returns the object, this saves a lot of traffic because
                /// only one reply actually contains the object other replies are simply dummy objects.
                if (Cluster.IsCoordinator)
                    return result;
            }
            catch (Exception)
            {
                if (_clusteredExceptions) throw;
            }
            return null;
        }
        /// <summary>
        /// Hanlde cluster-wide Get(key) requests.
        /// </summary>
        /// <param name="info">the object containing parameters for this operation.</param>
        /// <returns>object to be sent back to the requestor.</returns>
        private object handleGet(object info)
        {
            try
            {
                object[] objs = info as object[];
                OperationContext operationContext = null;
                bool isUserOperation = true;
                if (objs.Length > 1) operationContext = objs[1] as OperationContext;
                if (objs.Length > 2) isUserOperation = (bool)objs[2];

                if (objs[0] is object[]) return Local_Get((object[])objs[0], operationContext);
                else
                {
                    CacheEntry entry = Local_Get(objs[0],isUserOperation, operationContext);
                    /* send value and entry seperaty*/
                    OperationResponse opRes = new OperationResponse();
                    if (entry != null)
                    {
                        UserBinaryObject ubObject = (UserBinaryObject)(entry.Value is CallbackEntry ? ((CallbackEntry)entry.Value).Value : entry.Value);
                        opRes.UserPayload = ubObject.Data;
                        opRes.SerializablePayload = entry.CloneWithoutValue();
                    }
                    return opRes;
                }
            }
            catch (Exception)
            {
                if (_clusteredExceptions) throw;
            }
            return null;
        }
        /// <summary>
        /// Adds a pair of key and value to the cache. If the specified key already exists 
        /// in the cache; it is updated, otherwise a new item is added to the cache.
        /// </summary>
        /// <param name="info">the object containing parameters for this operation.</param>
        /// <returns>object to be sent back to the requestor.</returns>
        private object handleInsert(Address src, object info, Array userPayload)
        {
            try
            {
                object[] objs = (object[])info;
                bool returnEntry = false;
                OperationContext operationContext = null;

                //KS: operation Context
                if (objs.Length == 3)
                {
                    operationContext = objs[2] as OperationContext;
                }
                
                //muds: 
                //if client node is requesting for the previous cache entry
                //then cluster coordinator must send it back...
                if (objs.Length == 6)
                {
                    returnEntry = (bool)objs[2] && Cluster.IsCoordinator;
                    operationContext = objs[5] as OperationContext;
                }

                if (objs[0] is object[])
                {
                    object[] keys = (object[])objs[0];
                    CacheEntry[] entries = objs[1] as CacheEntry[];
                    return Local_Insert(keys, entries, src,  true, operationContext);
                }
                else
                {
                    object key = objs[0];
                    CacheEntry e = objs[1] as CacheEntry;
                    e.Value = userPayload;
                    object lockId = null;
                    LockAccessType accessType = LockAccessType.IGNORE_LOCK;
                
                    if (objs.Length == 6)
                    {
                        lockId = objs[3];
                        accessType = (LockAccessType)objs[4];
                    }
                    CacheInsResultWithEntry resultWithEntry = Local_Insert(key, e, src, true, lockId,  accessType, operationContext);


                    /* send value and entry seperately*/
                    OperationResponse opRes = new OperationResponse();
                    if (resultWithEntry.Entry != null)
                    {
                        if (resultWithEntry.Entry.Value is CallbackEntry)
                        {
                            opRes.UserPayload = null;
                        }
                        else
                        {
                            //muds: 
                            //we need not to send this entry back... it is needed only for custom notifications and/or key dependencies...
                            opRes.UserPayload = null;
                        }

                        if (returnEntry)
                            resultWithEntry.Entry = resultWithEntry.Entry.CloneWithoutValue() as CacheEntry;
                        else
                            resultWithEntry.Entry = null;
                    }

                    opRes.SerializablePayload = resultWithEntry;
                    return opRes;
                }
            }
            catch (Exception e)
            {
                if (_clusteredExceptions) throw;
            }
            return CacheInsResult.Failure;
        }
        private OperationResponse handleTransferBucket(Address sender, object info)
        {
            object[] pack = info as object[];

            ArrayList bucketIds = pack[0] as ArrayList;
            byte transferType = (byte) pack[1];
            bool sparsedBuckets = (bool) pack[2];
            int expectedTxfrId = (int) pack[3];
            bool isBalanceDataLoad = (bool) pack[4];

            if (_corresponders == null)
                _corresponders = new Hashtable();

            StateTxfrCorresponder corresponder = null;
            lock (_corresponders.SyncRoot)
            {
                corresponder = _corresponders[sender] as StateTxfrCorresponder;

                if (corresponder == null)
                {
                    corresponder = new StateTxfrCorresponder(this, _distributionMgr, sender, transferType);
                    _corresponders[sender] = corresponder;
                }
            }
            corresponder.IsBalanceDataLoad = isBalanceDataLoad;
            //ask the corresponder to transfer data for the bucket(s).

            Alachisoft.NCache.Caching.Topologies.Clustered.StateTxfrInfo transferInfo =
                corresponder.TransferBucket(bucketIds, sparsedBuckets, expectedTxfrId);
            OperationResponse rsp = new OperationResponse();
            rsp.SerializablePayload = transferInfo;
            rsp.SerilizationStream = transferInfo.SerlizationStream;
            //if (transferInfo.PayLoad != null)
            //    rsp.UserPayload = transferInfo.PayLoad;
            return rsp;
        }
        /// <summary>
        /// Hanlde cluster-wide Remove(key) requests.
        /// </summary>
        /// <param name="info">the object containing parameters for this operation.</param>
        /// <returns>object to be sent back to the requestor.</returns>
        /// <remarks>
        /// This method triggers <see cref="OnItemsRemoved"/>, which then triggers a cluster-wide 
        /// Item removed notification. 
        /// </remarks>
        private object handleRemove(Address src, object info)
        {
            try
            {
                object[] param = (object[]) info;
                CallbackEntry cbEntry = null;
                OperationContext oc = null;

                if (param.Length > 3)
                    cbEntry = param[3] as CallbackEntry;
               if (param.Length == 2)
                    oc = param[1] as OperationContext;

                if (param.Length == 7)
                    oc = param[6] as OperationContext;

                if (param.Length == 5)
                    oc = param[4] as OperationContext;

                if (param[0] is object[])
                {
                    Hashtable table = Local_Remove((object[])param[0], (ItemRemoveReason)param[1], src, cbEntry, (bool)param[2], oc);
                    return table;
                }
                else
                {
                    object lockId = param[4];
                    LockAccessType accessType = (LockAccessType)param[5];
                    CacheEntry e = Local_Remove(param[0], (ItemRemoveReason)param[1], src, cbEntry, (bool)param[2], lockId, accessType, oc);
                    OperationResponse opRes = new OperationResponse();
                    if (e != null)
                    {
                        UserBinaryObject ubObject =
                            (UserBinaryObject) (e.Value is CallbackEntry ? ((CallbackEntry) e.Value).Value : e.Value);
                        opRes.UserPayload = ubObject.Data;

                        opRes.SerializablePayload = e.CloneWithoutValue();
                    }
                    return opRes;
                }
            }
            catch (Exception)
            {
                if (_clusteredExceptions) throw;
            }
            return null;
        }
        /// <summary>
        /// Adds a pair of key and value to the cache. If the specified key already exists 
        /// in the cache; it is updated, otherwise a new item is added to the cache.
        /// </summary>
        /// <param name="info">the object containing parameters for this operation.</param>
        /// <returns>object to be sent back to the requestor.</returns>
        /// <remarks>
        /// This method triggers either <see cref="OnItemAdded"/> or <see cref="OnItemUpdated"/>, which
        /// in turn trigger either an item-added or item-updated cluster-wide notification.
        /// </remarks>
        private object handleInsert(Address src, object info, Array userPayload)
        {
            try
            {
                OperationContext operationContext = null;
                object[] objs = (object[]) info;

                if (objs.Length == 3)
                {
                    operationContext = objs[2] as OperationContext;
                }
                else if (objs.Length == 5)
                {
                    operationContext = objs[4] as OperationContext;
                }

                if (objs[0] is object[])
                {
                    object[] keyArr = (object[])objs[0];
                    CacheEntry[] valArr = (CacheEntry[])objs[1];
                    return Local_Insert(keyArr, valArr, src, true, operationContext);
                }
                else
                {
                    object key = objs[0];
                    CacheEntry e = objs[1] as CacheEntry;
                    e.Value = userPayload;
                    object lockId = objs[2];
                    LockAccessType accessType = (LockAccessType) objs[3];
                    CacheInsResultWithEntry retVal = Local_Insert(key, e, src, true, lockId, accessType,
                        operationContext);
                    /* send value and entry seperaty*/
                    OperationResponse opRes = new OperationResponse();
                    if (retVal.Entry != null)
                    {
                        opRes.UserPayload = null; 
                        retVal.Entry = null;
                    }
                    opRes.SerializablePayload = retVal;
                    return opRes;
                }
            }
            catch (Exception)
            {
                if (_clusteredExceptions) throw;
            }
            return null;
        }
        /// <summary>
        /// Hanlde cluster-wide Get(key) requests.
        /// </summary>
        /// <param name="info">the object containing parameters for this operation.</param>
        /// <returns>object to be sent back to the requestor.</returns>
        private object handleGet(object info)
        {
            try
            {
                object[] args = info as object[];
                if (args[0] is object[])
                {
                    Hashtable table = Local_Get((object[]) args[0], args[1] as OperationContext);
                    return table;
                }
                else
                {
                    object key = args[0];
                    object lockId = args[1];
                    DateTime lockDate = (DateTime) args[2];
                    LockAccessType accessType = (LockAccessType) args[3];
                    LockExpiration lockExpiration = (LockExpiration) args[4];
                    OperationContext operationContext = args[5] as OperationContext;

                    CacheEntry entry = Local_Get(key, ref lockId, ref lockDate, lockExpiration, accessType,
                        operationContext);
                    OperationResponse opRes = new OperationResponse();
                    object[] response = new object[4];
                    if (entry != null)
                    {
                        UserBinaryObject ubObject =
                            (UserBinaryObject)
                                (entry.Value is CallbackEntry ? ((CallbackEntry) entry.Value).Value : entry.Value);
                        opRes.UserPayload = ubObject.Data;
                        response[0] = entry.CloneWithoutValue();
                    }
                    response[1] = lockId;
                    response[2] = lockDate;
                    opRes.SerializablePayload = response;

                    return opRes;
                }
            }
            catch (Exception)
            {
                if (_clusteredExceptions) throw;
            }
            return null;
        }
Beispiel #8
0
        /* ---------------------- Interface RspCollector -------------------------- */
        /// <summary> <b>Callback</b> (called by RequestCorrelator or Transport).
        /// Adds a response to the response table. When all responses have been received,
        /// <code>execute()</code> returns.
        /// </summary>

        public virtual void receiveResponse(Message m)
        {
            Address sender = m.Src, mbr;
            object val = null;
            if (_done)
            {
                NCacheLog.Warn("GroupRequest.receiveResponse()", "command is done; cannot add response !");
                return;
            }
            if (suspects != null && suspects.Count > 0 && suspects.Contains(sender))
            {
                NCacheLog.Warn("GroupRequest.receiveResponse()", "received response from suspected member " + sender + "; discarding");
                return;
            }
            if (m.Length > 0)
            {
                try
                {
                    if (m.responseExpected)
                    {
                        OperationResponse opRes = new OperationResponse();
                        opRes.SerializablePayload = m.getFlatObject();
                        opRes.UserPayload = m.Payload;
                        val = opRes;
                    }
                    else
                    {
                        val = m.getFlatObject();
                    }
                }
                catch (System.Exception e)
                {
                    NCacheLog.Error("GroupRequest.receiveResponse()", "exception=" + e.Message);
                }
            }

            lock (rsp_mutex)
            {
                bool isMainMember = false;
                for (int i = 0; i < membership.Length; i++)
                {
                    mbr = membership[i];
                    if (mbr.Equals(sender))
                    {
                        isMainMember = true;

                        if (received[i] == NOT_RECEIVED)
                        {
                            responses[i] = val;
                            received[i] = RECEIVED;
                            if (NCacheLog.IsInfoEnabled) NCacheLog.Info("GroupRequest.receiveResponse()", "received response for request " + req_id + ", sender=" + sender + ", val=" + val);
                            System.Threading.Monitor.PulseAll(rsp_mutex); // wakes up execute()
                            break;
                        }
                    }
                }

                if (!isMainMember)
                {

                    receivedFromNHops[sender] = RECEIVED;
                    System.Threading.Monitor.PulseAll(rsp_mutex);

                }
            }
        }