Esempio n. 1
0
        /// <summary>
        /// Send changes to server
        /// </summary>
        public async Task <(SyncContext, ChangesApplied)> ApplyChangesAsync(SyncContext context, MessageApplyChanges message)
        {
            if (message.Changes == null || message.Changes.BatchPartsInfo.Count == 0)
            {
                return(context, new ChangesApplied());
            }

            SyncContext    syncContext    = null;
            ChangesApplied changesApplied = null;

            // Foreach part, will have to send them to the remote
            // once finished, return context
            foreach (var bpi in message.Changes.BatchPartsInfo.OrderBy(bpi => bpi.Index))
            {
                var applyChanges = new HttpMessageApplyChanges
                {
                    FromScope           = message.FromScope,
                    Schema              = new DmSetSurrogate(message.Schema),
                    Policy              = message.Policy,
                    UseBulkOperations   = message.UseBulkOperations,
                    ScopeInfoTableName  = message.ScopeInfoTableName,
                    SerializationFormat = message.SerializationFormat
                };

                HttpMessage httpMessage = new HttpMessage
                {
                    Step        = HttpStep.ApplyChanges,
                    SyncContext = context,
                    Content     = applyChanges
                };

                // If BPI is InMempory, no need to deserialize from disk
                // Set already contained in part.Set
                if (!message.Changes.InMemory)
                {
                    // get the batch
                    var partBatch = bpi.GetBatch();

                    // get the surrogate dmSet
                    if (partBatch != null)
                    {
                        applyChanges.Set = partBatch.DmSetSurrogate;
                    }
                }
                else if (bpi.Set != null)
                {
                    applyChanges.Set = new DmSetSurrogate(bpi.Set);
                }

                if (applyChanges.Set == null || applyChanges.Set.Tables == null)
                {
                    throw new ArgumentException("No changes to upload found.");
                }

                // no need to send filename
                applyChanges.BatchPartInfo = new BatchPartInfo
                {
                    FileName    = null,
                    Index       = bpi.Index,
                    IsLastBatch = bpi.IsLastBatch,
                    Tables      = bpi.Tables
                };
                applyChanges.InMemory   = message.Changes.InMemory;
                applyChanges.BatchIndex = bpi.Index;

                //Post request and get response
                var httpMessageResponse = await this.httpRequestHandler.ProcessRequest(httpMessage, message.SerializationFormat, cancellationToken);

                // Clear surrogate
                applyChanges.Set.Dispose();
                applyChanges.Set = null;

                if (httpMessageResponse == null)
                {
                    throw new Exception("Can't have an empty body");
                }

                HttpMessageApplyChanges httpMessageContent;
                if (httpMessageResponse.Content is HttpMessageApplyChanges)
                {
                    httpMessageContent = httpMessageResponse.Content as HttpMessageApplyChanges;
                }
                else
                {
                    httpMessageContent = (httpMessageResponse.Content as JObject).ToObject <HttpMessageApplyChanges>();
                }

                syncContext    = httpMessageResponse.SyncContext;
                changesApplied = httpMessageContent.ChangesApplied;
            }

            return(syncContext, changesApplied);
        }
Esempio n. 2
0
        public async Task <(SyncContext, BatchInfo, ChangesSelected)> GetChangeBatchAsync(
            SyncContext context, MessageGetChangesBatch message)
        {
            // While we have an other batch to process
            var isLastBatch = false;

            // Create the BatchInfo and SyncContext to return at the end
            BatchInfo changes = new BatchInfo
            {
                Directory = BatchInfo.GenerateNewDirectoryName()
            };
            SyncContext     syncContext     = null;
            ChangesSelected changesSelected = null;

            while (!isLastBatch)
            {
                HttpMessage httpMessage = new HttpMessage
                {
                    SyncContext = context,
                    Step        = HttpStep.GetChangeBatch,

                    Content = new HttpMessageGetChangesBatch
                    {
                        ScopeInfo             = message.ScopeInfo,
                        BatchIndexRequested   = changes.BatchIndex,
                        DownloadBatchSizeInKB = message.DownloadBatchSizeInKB,
                        BatchDirectory        = message.BatchDirectory,
                        Schema              = new DmSetSurrogate(message.Schema),
                        Filters             = message.Filters,
                        Policy              = message.Policy,
                        SerializationFormat = message.SerializationFormat
                    }
                };

                var httpMessageResponse = await this.httpRequestHandler.ProcessRequest(httpMessage, message.SerializationFormat, cancellationToken);

                if (httpMessageResponse == null)
                {
                    throw new Exception("Can't have an empty body");
                }

                HttpMessageGetChangesBatch httpMessageContent;
                if (httpMessageResponse.Content is HttpMessageGetChangesBatch)
                {
                    httpMessageContent = httpMessageResponse.Content as HttpMessageGetChangesBatch;
                }
                else
                {
                    httpMessageContent = (httpMessageResponse.Content as JObject).ToObject <HttpMessageGetChangesBatch>();
                }

                if (httpMessageContent == null)
                {
                    throw new Exception("Can't have an empty GetChangeBatch");
                }

                changesSelected  = httpMessageContent.ChangesSelected;
                changes.InMemory = httpMessageContent.InMemory;
                syncContext      = httpMessageResponse.SyncContext;

                // get the bpi and add it to the BatchInfo
                var bpi = httpMessageContent.BatchPartInfo;
                if (bpi != null)
                {
                    changes.BatchIndex = bpi.Index;
                    changes.BatchPartsInfo.Add(bpi);
                    isLastBatch = bpi.IsLastBatch;
                }
                else
                {
                    changes.BatchIndex = 0;
                    isLastBatch        = true;

                    // break the while { } story
                    break;
                }

                if (changes.InMemory)
                {
                    // load the DmSet in memory
                    bpi.Set = httpMessageContent.Set.ConvertToDmSet();
                }
                else
                {
                    // Serialize the file !
                    var bpId     = BatchInfo.GenerateNewFileName(changes.BatchIndex.ToString());
                    var fileName = Path.Combine(message.BatchDirectory, changes.Directory, bpId);
                    BatchPart.Serialize(httpMessageContent.Set, fileName);
                    bpi.FileName = fileName;
                    bpi.Clear();
                }

                // Clear the DmSetSurrogate from response, we don't need it anymore
                if (httpMessageContent.Set != null)
                {
                    httpMessageContent.Set.Dispose();
                    httpMessageContent.Set = null;
                }

                // if not last, increment batchIndex for next request
                if (!isLastBatch)
                {
                    changes.BatchIndex++;
                }
            }

            return(syncContext, changes, changesSelected);
        }
Esempio n. 3
0
        private async Task <HttpMessage> ApplyChangesAsync(HttpMessage httpMessage)
        {
            if (httpMessage.ApplyChanges == null)
            {
                throw new ArgumentException("ApplyChanges message could not be null");
            }

            var scopeInfo = httpMessage.ApplyChanges.ScopeInfo;

            if (scopeInfo == null)
            {
                throw new ArgumentException("ApplyChanges ScopeInfo could not be null");
            }

            BatchInfo batchInfo;
            var       bpi = httpMessage.ApplyChanges.BatchPartInfo;

            if (httpMessage.ApplyChanges.InMemory)
            {
                batchInfo = new BatchInfo
                {
                    BatchIndex     = 0,
                    BatchPartsInfo = new List <BatchPartInfo>(new[] { bpi }),
                    InMemory       = true
                };

                bpi.Set = httpMessage.ApplyChanges.Set.ConvertToDmSet();

                httpMessage.ApplyChanges.Set.Dispose();
                httpMessage.ApplyChanges.Set = null;

                var(c, s) = await this.ApplyChangesAsync(httpMessage.SyncContext, scopeInfo, batchInfo);

                httpMessage.SyncContext = c;
                httpMessage.ApplyChanges.ChangesApplied = s;

                httpMessage.ApplyChanges.BatchPartInfo.Clear();
                httpMessage.ApplyChanges.BatchPartInfo.FileName = null;

                return(httpMessage);
            }

            // not in memory
            batchInfo = this.LocalProvider.CacheManager.GetValue <BatchInfo>("ApplyChanges_BatchInfo");

            if (batchInfo == null)
            {
                batchInfo = new BatchInfo
                {
                    BatchIndex     = 0,
                    BatchPartsInfo = new List <BatchPartInfo>(new[] { bpi }),
                    InMemory       = false,
                    Directory      = BatchInfo.GenerateNewDirectoryName()
                };
            }
            else
            {
                batchInfo.BatchPartsInfo.Add(bpi);
            }

            var bpId     = BatchInfo.GenerateNewFileName(httpMessage.ApplyChanges.BatchIndex.ToString());
            var fileName = Path.Combine(this.LocalProvider.GetCacheConfiguration().BatchDirectory,
                                        batchInfo.Directory, bpId);

            BatchPart.Serialize(httpMessage.ApplyChanges.Set, fileName);
            bpi.FileName = fileName;
            this.LocalProvider.CacheManager.Set("ApplyChanges_BatchInfo", batchInfo);

            // Clear the httpMessage set
            if (httpMessage.ApplyChanges != null)
            {
                httpMessage.ApplyChanges.Set.Dispose();
                httpMessage.ApplyChanges.Set = null;
            }


            // if it's last batch sent
            if (bpi.IsLastBatch)
            {
                var(c, s) = await this.ApplyChangesAsync(httpMessage.SyncContext, scopeInfo, batchInfo);

                this.LocalProvider.CacheManager.Remove("ApplyChanges_BatchInfo");
                httpMessage.SyncContext = c;
                httpMessage.ApplyChanges.ChangesApplied = s;
            }

            httpMessage.ApplyChanges.BatchPartInfo.Clear();
            httpMessage.ApplyChanges.BatchPartInfo.FileName = null;

            return(httpMessage);
        }
Esempio n. 4
0
        /// <summary>
        /// Call this method to handle requests on the server, sent by the client
        /// </summary>
        public async Task HandleRequestAsync(HttpContext context, CancellationToken cancellationToken)
        {
            var httpRequest  = context.Request;
            var httpResponse = context.Response;
            var streamArray  = httpRequest.Body;

            // Check if we should handle a session store to handle configuration
            if (!this.IsRegisterAsSingleton)
            {
                // try to get the session store service from DI
                var sessionStore = context.RequestServices.GetService(typeof(ISessionStore));

                if (sessionStore != null)
                {
                    this.LocalProvider.CacheManager = new SessionCache(context);
                }
            }

            try
            {
                var httpMessage = serializer.Deserialize(streamArray);

                HttpMessage httpMessageResponse = null;
                switch (httpMessage.Step)
                {
                case HttpStep.BeginSession:
                    httpMessageResponse = await BeginSessionAsync(httpMessage);

                    break;

                case HttpStep.EnsureScopes:
                    httpMessageResponse = await EnsureScopesAsync(httpMessage);

                    break;

                case HttpStep.EnsureConfiguration:
                    httpMessageResponse = await EnsureConfigurationAsync(httpMessage);

                    break;

                case HttpStep.EnsureDatabase:
                    httpMessageResponse = await EnsureDatabaseAsync(httpMessage);

                    break;

                case HttpStep.GetChangeBatch:
                    httpMessageResponse = await GetChangeBatchAsync(httpMessage);

                    break;

                case HttpStep.ApplyChanges:
                    httpMessageResponse = await ApplyChangesAsync(httpMessage);

                    break;

                case HttpStep.GetLocalTimestamp:
                    httpMessageResponse = await GetLocalTimestampAsync(httpMessage);

                    break;

                case HttpStep.WriteScopes:
                    httpMessageResponse = await WriteScopesAsync(httpMessage);

                    break;

                case HttpStep.EndSession:
                    httpMessageResponse = await EndSessionAsync(httpMessage);

                    break;
                }

                var binaryData = serializer.Serialize(httpMessageResponse);
                await httpResponse.Body.WriteAsync(binaryData, 0, binaryData.Length);
            }
            catch (Exception ex)
            {
                await this.WriteExceptionAsync(httpResponse, ex);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// From request, I get a BI
        /// I need to send back a BPI
        /// </summary>
        /// <param name="httpMessage"></param>
        /// <returns></returns>
        private async Task <HttpMessage> GetChangeBatchAsync(HttpMessage httpMessage)
        {
            if (httpMessage.GetChangeBatch == null)
            {
                throw new ArgumentException("GetChangeBatch message could not be null");
            }

            var scopeInfo = httpMessage.GetChangeBatch.ScopeInfo;

            if (scopeInfo == null)
            {
                throw new ArgumentException("GetChangeBatch ScopeInfo could not be null");
            }

            // if we get the first batch info request, made it.
            // Server is able to define if it's in memory or not
            if (httpMessage.GetChangeBatch.BatchIndexRequested == 0)
            {
                var(syncContext, bi, changesSelected) = await this.GetChangeBatchAsync(httpMessage.SyncContext, scopeInfo);

                // Select the first bpi needed (index == 0)
                if (bi.BatchPartsInfo.Count > 0)
                {
                    httpMessage.GetChangeBatch.BatchPartInfo = bi.BatchPartsInfo.First(bpi => bpi.Index == 0);
                }

                httpMessage.SyncContext                    = syncContext;
                httpMessage.GetChangeBatch.InMemory        = bi.InMemory;
                httpMessage.GetChangeBatch.ChangesSelected = changesSelected;

                // if no changes, return
                if (httpMessage.GetChangeBatch.BatchPartInfo == null)
                {
                    return(httpMessage);
                }

                // if we are not in memory, we set the BI in session, to be able to get it back on next request
                if (!bi.InMemory)
                {
                    // Save the BatchInfo
                    this.LocalProvider.CacheManager.Set("GetChangeBatch_BatchInfo", bi);
                    this.LocalProvider.CacheManager.Set("GetChangeBatch_ChangesSelected", changesSelected);

                    // load the batchpart set directly, to be able to send it back
                    var batchPart = httpMessage.GetChangeBatch.BatchPartInfo.GetBatch();
                    httpMessage.GetChangeBatch.Set = batchPart.DmSetSurrogate;
                }
                else
                {
                    // We are in memory, so generate the DmSetSurrogate to be able to send it back
                    httpMessage.GetChangeBatch.Set = new DmSetSurrogate(httpMessage.GetChangeBatch.BatchPartInfo.Set);
                    httpMessage.GetChangeBatch.BatchPartInfo.Set.Clear();
                    httpMessage.GetChangeBatch.BatchPartInfo.Set = null;
                }

                // no need fileName info
                httpMessage.GetChangeBatch.BatchPartInfo.FileName = null;

                return(httpMessage);
            }

            // We are in batch mode here
            var batchInfo = this.LocalProvider.CacheManager.GetValue <BatchInfo>("GetChangeBatch_BatchInfo");
            var stats     = this.LocalProvider.CacheManager.GetValue <ChangesSelected>("GetChangeBatch_ChangesSelected");

            if (batchInfo == null)
            {
                throw new ArgumentNullException("batchInfo stored in session can't be null if request more batch part info.");
            }

            httpMessage.GetChangeBatch.ChangesSelected = stats;
            httpMessage.GetChangeBatch.InMemory        = batchInfo.InMemory;

            var batchPartInfo = batchInfo.BatchPartsInfo.FirstOrDefault(bpi => bpi.Index == httpMessage.GetChangeBatch.BatchIndexRequested);

            httpMessage.GetChangeBatch.BatchPartInfo = batchPartInfo;

            // load the batchpart set directly, to be able to send it back
            httpMessage.GetChangeBatch.Set = httpMessage.GetChangeBatch.BatchPartInfo.GetBatch().DmSetSurrogate;

            if (httpMessage.GetChangeBatch.BatchPartInfo.IsLastBatch)
            {
                this.LocalProvider.CacheManager.Remove("GetChangeBatch_BatchInfo");
                this.LocalProvider.CacheManager.Remove("GetChangeBatch_ChangesSelected");
            }

            return(httpMessage);
        }