//public IFeedSession BeginFeed(TypeDescriptionConfig typeDescription, int packetSize, bool excludeFromEviction) //{ // //RegisterTypeIfNeeded() // //return new FeedSession<TItem>(packetSize, excludeFromEviction); // throw new NotImplementedException(); //} /// <summary> /// As an alternative to <see cref="FeedMany{T}(IEnumerable{T},bool,int)" /> you can use /// <see cref="BeginFeed{TItem}" /> <see cref="Add{TItem}" /> <see cref="EndFeed{TItem}" /> /// </summary> /// <typeparam name="TItem"></typeparam> /// <param name="session"></param> /// <param name="item"></param> public void Add <TItem>(IFeedSession session, TItem item) where TItem : class { var sessionImplementation = (FeedSession <TItem>)session; if (sessionImplementation.IsClosed) { throw new CacheException("The feed session is closed"); } var description = RegisterTypeIfNeeded(typeof(TItem)); var packedItem = CachedObject.Pack(item, description); sessionImplementation.Request.Items.Add(packedItem); if (sessionImplementation.Request.Items.Count == sessionImplementation.PacketSize) { var request = sessionImplementation.Request; sessionImplementation.Request = null; // only one packet at a time is fed asynchronously. If the previous send is still pending wait fot it to finish sessionImplementation.WaitForAsyncCompletion(); ThreadPool.QueueUserWorkItem(state => { try { var rq = (Request)state; sessionImplementation.StartAsync(); var response = Channel.SendRequest(rq); if (response is ExceptionResponse exResponse) { sessionImplementation.EndAsync( new CacheException( "Error while writing an object to the cache", exResponse.Message, exResponse.CallStack)); } else { sessionImplementation.EndAsync(null); } } catch (Exception e) { sessionImplementation.EndAsync(e); } }, request); // prepare a new empty put request that will receive new items sessionImplementation.Request = new PutRequest(typeof(TItem)); } }
/// <summary> /// Close a feed session. Send all the remaining data and wait for all asynchronous operations to finish /// </summary> /// <typeparam name="TItem"></typeparam> /// <param name="session"></param> public void EndFeed <TItem>(IFeedSession session) where TItem : class { var sessionImplementation = (ParallelFeedSession <TItem>)session; if (sessionImplementation.IsClosed) { throw new CacheException("The feed session is closed"); } //send the last packet left for each node for (var node = 0; node < CacheClients.Count; node++) { var request = sessionImplementation.Requests[node]; if (request != null && request.Items.Count > 0) { var n = node; // copy to avoid modified closure var task = Task.Factory.StartNew(re => { var response = CacheClients[n].Channel.SendRequest((Request)re); if (response is ExceptionResponse exResponse) { throw new CacheException( "Error while writing an object to the cache", exResponse.Message, exResponse.CallStack); } }, request); sessionImplementation.AddTask(task); } } try { sessionImplementation.WaitForAll(); } catch (AggregateException e) { if (e.InnerException != null) { throw e.InnerException; } } sessionImplementation.IsClosed = true; }
/// <summary> /// As an alternative to <see cref="FeedMany{T}(IEnumerable{T},bool,int)" /> you can use /// <see cref="BeginFeed{TItem}" /> <see cref="Add{TItem}" /> <see cref="EndFeed{TItem}" /> /// </summary> /// <typeparam name="TItem"></typeparam> /// <param name="session"></param> public void EndFeed <TItem>(IFeedSession session) where TItem : class { var feedSession = (FeedSession <TItem>)session; feedSession.WaitForAsyncCompletion(); // the last block is always send synchronously. if (feedSession.Request.Items.Count > 0) { var response = Channel.SendRequest(feedSession.Request); if (response is ExceptionResponse exResponse) { throw new CacheException("Error while writing an object to the cache", exResponse.Message, exResponse.CallStack); } } feedSession.IsClosed = true; }
/// <summary> /// Add an element to the cache during a fill session. Items are effectively send to the server in fixed size packets /// </summary> /// <typeparam name="TItem"></typeparam> /// <param name="session"></param> /// <param name="item"></param> public void Add <TItem>(IFeedSession session, TItem item) where TItem : class { var sessionImplementation = (ParallelFeedSession <TItem>)session; if (sessionImplementation.IsClosed) { throw new CacheException("The feed session is closed"); } var description = RegisterTypeIfNeeded(typeof(TItem)); var packedItem = CachedObject.Pack(item, description); var node = WhichNode(packedItem); var request = sessionImplementation.Requests[node]; request.Items.Add(packedItem); // for each node fill a packet of fixed size and send it to the server only when completed if (request.Items.Count == sessionImplementation.PacketSize) { // create a new empty one for the future objects sessionImplementation.Requests[node] = new PutRequest(typeof(TItem)); var task = Task.Factory.StartNew(re => { var response = CacheClients[node].Channel.SendRequest((Request)re); if (response is ExceptionResponse exResponse) { throw new CacheException( "Error while writing an object to the cache", exResponse.Message, exResponse.CallStack); } }, request); sessionImplementation.AddTask(task); } }