/// <summary> /// Updates or Adds the object to the cluster. /// </summary> /// <param name="key">key of the entry.</param> /// <returns>cache entry.</returns> /// <remarks> /// This method invokes <see cref="handleInsert"/> on the specified node. /// </remarks> protected CacheInsResultWithEntry Clustered_Insert(Address dest, object key, CacheEntry cacheEntry, string taskId, object lockId, ulong version, LockAccessType accessType, OperationContext operationContext) { if (ServerMonitor.MonitorActivity) { ServerMonitor.LogClientActivity("PartCacheBase.Insert", ""); } CacheInsResultWithEntry retVal = null; CacheEntry cloneValue = null; try { operationContext?.MarkInUse(NCModulesConstants.Topology); Array userPayLoad; long payLoadSize; _context.CachingSubSystemDataService.GetEntryClone(cacheEntry, out cloneValue, out userPayLoad, out payLoadSize); Function func = new Function((int)OpCodes.Insert, new object[] { key, cloneValue, taskId, lockId, accessType, version, operationContext }); func.UserPayload = userPayLoad; func.ResponseExpected = true; object result = Cluster.SendMessage(dest, func, GroupRequest.GET_FIRST, false); if (result == null) { return(retVal); } retVal = (CacheInsResultWithEntry)((OperationResponse)result).SerializablePayload; if (retVal.Entry != null && ((OperationResponse)result).UserPayload != null) { retVal.Entry.Value = ((OperationResponse)result).UserPayload; } } catch (Runtime.Exceptions.SuspectedException se) { throw; } catch (Runtime.Exceptions.TimeoutException te) { throw; } catch (CacheException e) { throw; } catch (Exception e) { throw new GeneralFailureException(e.Message, e); } finally { operationContext?.MarkFree(NCModulesConstants.Topology); if (retVal == null) { retVal = CacheInsResultWithEntry.CreateCacheInsResultWithEntry(_context.TransactionalPoolManager); } MiscUtil.ReturnEntryToPool(cloneValue, Context.TransactionalPoolManager); } return(retVal); }
/// <summary> /// Returns the set of nodes where the insertion was performed as an atomic operation. /// </summary> /// <param name="results">responses collected from all members of cluster.</param> /// <returns>list of nodes where the operation succeeded</returns> public static CacheInsResultWithEntry FindAtomicInsertStatusReplicated(RspList results, PoolManager poolManager) { int needEvictCount = 0; int timeoutCount = 0; int suspectedCount = 0; int successCount = 0; CacheInsResultWithEntry res = new CacheInsResultWithEntry(); if (results == null) { return(res); } for (int i = 0; i < results.size(); i++) { Rsp rsp = (Rsp)results.elementAt(i); if (!rsp.wasReceived() && !rsp.wasSuspected()) { timeoutCount++; continue; } if (rsp.wasSuspected()) { suspectedCount++; continue; } res = (CacheInsResultWithEntry)((OperationResponse)rsp.Value).SerializablePayload; if (res == null) { res = CacheInsResultWithEntry.CreateCacheInsResultWithEntry(poolManager); } if (res.Result == CacheInsResult.Success || res.Result == CacheInsResult.SuccessOverwrite) { successCount++; } /* If all the nodes in the Cluster return NeedsEviction response then we do not need to remove */ if (res.Result == CacheInsResult.NeedsEviction) { needEvictCount++; } } if (needEvictCount == results.size()) { //every node returned the NeedEviction; so we need not remove the item //as data is not corrupted. res.Result = CacheInsResult.NeedsEvictionNotRemove; } if (timeoutCount > 0 && (timeoutCount + successCount == results.size())) { if (successCount > 0) { //operation is not succeeded on some of the nodes; therefore we throw timeout exception. res.Result = CacheInsResult.PartialTimeout; } else { //operation timed out on all of the node; no need to rollback. res.Result = CacheInsResult.FullTimeout; } } if (timeoutCount > 0 && suspectedCount > 0) { if (successCount > 0) { //operation is not succeeded on some of the nodes; therefore we throw timeout exception. res.Result = CacheInsResult.PartialTimeout; } else { //operation timed out on all of the node; no need to rollback. res.Result = CacheInsResult.FullTimeout; } } return(res); }