public void DoWork(NorthwindConfig config, SyncFeedDigest syncDigestInfo) { ExecuteDelegate worker = new ExecuteDelegate(Execute); AsyncCallback completedCallback = new AsyncCallback(ExecuteCompletedCallback); AsyncOperation async = AsyncOperationManager.CreateOperation(null); // Begin asynchronous method call worker.BeginInvoke(config, syncDigestInfo, completedCallback, async); }
public static int GetConflictPriority(SyncFeedDigest digest, string endpoint) { foreach (SyncFeedDigestEntry entry in digest.Entries) { if ((entry.Endpoint != null) && (entry.Endpoint.Equals(endpoint, StringComparison.InvariantCultureIgnoreCase))) { return(entry.ConflictPriority); } } return(10000); }
public static SyncState GetSyncState(SyncFeedDigest digest, string endpoint) { foreach (SyncFeedDigestEntry entry in digest.Entries) { if ((entry.Endpoint != null) && (entry.Endpoint.Equals(endpoint, StringComparison.InvariantCultureIgnoreCase))) { SyncState result = new SyncState(); result.Endpoint = entry.Endpoint; result.Stamp = entry.Stamp; result.Tick = entry.Tick; return(result); } } return(null); }
//private NorthwindConfig _config; #endregion #region IRequestProcess Members public void DoWork(IRequest request) { // If an asyncState object already exists, an exception is thrown as the performer only accepts // one call after each other. The Request receiver has to manage a queued execution. // Before calling the performers execution implementation method a new AsyncState object is created // and set to an initial tracking state. lock (_asyncStateObj) { if (null != _asyncStateObj.Tracking) { throw new InvalidOperationException("The performer cannot be executed because it is already running."); } SyncTracking tracking = new SyncTracking(); tracking.ElapsedSeconds = 1; tracking.Phase = TrackingPhase.INIT; tracking.PhaseDetail = "Tracking Id was: " + _requestContext.TrackingId.ToString(); tracking.PollingMillis = 100; tracking.RemainingSeconds = 100; _asyncStateObj.Tracking = tracking; } // *** Initialization for the async execution *** // - Read SyncDigest from request stream. // - Read trackingId from request URL //// Load input stream (throws RequestException if it fails.) //XmlDocument xmlInputDoc; //InputStreamHelpers.Get(request, out xmlInputDoc); //// load syncDigest info from input stream of the request //SyncDigestInfo syncDigestInfo = SyncDigestInfoHelpers.Load(xmlInputDoc); SyncFeedEntry entry = new SyncFeedEntry(); XmlReader reader = XmlReader.Create(request.Stream); reader.MoveToContent(); entry.ReadXml(reader, typeof(SyncDigestPayload)); if (entry.Payload == null) { throw new RequestException("Invalid Content"); } SyncFeedDigest syncDigestInfo = ((SyncDigestPayload)entry.Payload).Digest; // convert tracking ID from request to type Guid string strTrackingId = request.Uri.TrackingID; if (String.IsNullOrEmpty(strTrackingId)) { throw new RequestException("TrackingId is missing"); } GuidConverter converter = new GuidConverter(); this.TrackingId = (Guid)converter.ConvertFrom(strTrackingId); // *** Do work asynchronously *** _asyncPerformer = new InternalAsyncPerformer(this); _asyncPerformer.DoWork(_requestContext.Config, syncDigestInfo); // *** set the tracking to the request response *** this.GetTrackingState(request); }
// Asynchronous called method private void Execute(NorthwindConfig config, SyncFeedDigest syncDigestInfo) { #region Declaration SdataContext sdataContext; SupportedResourceKinds resource; IAppBookmarkInfoStore appBookmarkInfoStore; ICorrelatedResSyncInfoStore correlatedResSyncInfoStore; ISyncSyncDigestInfoStore syncDigestStore; ISyncTickProvider tickProvider; string resourceKind; string endpoint; int nextTick = 0; Token lastToken; Token nextToken; Identity[] changedIdentites; IEntityWrapper wrapper; #endregion #region init sdataContext = _parentPerformer._requestContext.SdataContext; resource = _parentPerformer._requestContext.ResourceKind; resourceKind = resource.ToString(); endpoint = _parentPerformer._requestContext.DatasetLink + resourceKind; appBookmarkInfoStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetAppBookmarkStore(sdataContext); correlatedResSyncInfoStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetCorrelatedResSyncStore(sdataContext); syncDigestStore = RequestReceiver.NorthwindAdapter.StoreLocator.GetSyncDigestStore(sdataContext); tickProvider = RequestReceiver.NorthwindAdapter.StoreLocator.GetTickProvider(sdataContext); wrapper = EntityWrapperFactory.Create(resource, _parentPerformer._requestContext); #endregion #region get last token or create a new one if (!appBookmarkInfoStore.Get <Token>(resourceKind, out lastToken)) { lastToken = new Token(); lastToken.InitRequest = true; } #endregion #region Get local identities of changed entries since last synchronisation changedIdentites = wrapper.Entity.GetLastChanges(lastToken, config, out nextToken); #endregion if (resource == SupportedResourceKinds.phoneNumbers) { #region workaround for phones for (int index = 0; index < changedIdentites.Length; index++) { string phoneid = changedIdentites[index].Id + Sage.Integration.Northwind.Application.API.Constants.PhoneIdPostfix; string faxId = changedIdentites[index].Id + Sage.Integration.Northwind.Application.API.Constants.FaxIdPostfix; // receive the feed entry for local identity SyncFeedEntry phoneentry = wrapper.GetFeedEntry(phoneid); SyncFeedEntry faxentry = wrapper.GetFeedEntry(faxId); if (phoneentry == null && faxentry == null) { continue; } // receive the correlation for the local identity if (phoneentry != null) { CorrelatedResSyncInfo[] correlatedResSyncInfos = correlatedResSyncInfoStore.GetByLocalId(resourceKind, new string[] { phoneid }); string etag = EtagServices.ComputeEtag(phoneentry.Payload, true); // new etag if (correlatedResSyncInfos.Length == 0) { nextTick = tickProvider.CreateNextTick(resourceKind); // create next tick ResSyncInfo resyncInfo = new ResSyncInfo(Guid.NewGuid(), endpoint, nextTick, etag, DateTime.Now); CorrelatedResSyncInfo info = new CorrelatedResSyncInfo(phoneid, resyncInfo); correlatedResSyncInfoStore.Put(resourceKind, info); syncDigestStore.PersistNewer(resourceKind, info.ResSyncInfo); } else if (!correlatedResSyncInfos[0].ResSyncInfo.Etag.Equals(etag)) { nextTick = tickProvider.CreateNextTick(resourceKind); correlatedResSyncInfos[0].ResSyncInfo.Etag = etag; correlatedResSyncInfos[0].ResSyncInfo.Tick = nextTick; correlatedResSyncInfos[0].ResSyncInfo.Endpoint = endpoint; correlatedResSyncInfos[0].ResSyncInfo.ModifiedStamp = DateTime.Now; correlatedResSyncInfoStore.Put(resourceKind, correlatedResSyncInfos[0]); syncDigestStore.PersistNewer(resourceKind, correlatedResSyncInfos[0].ResSyncInfo); } } if (faxentry != null) { CorrelatedResSyncInfo[] correlatedResSyncInfos = correlatedResSyncInfoStore.GetByLocalId(resourceKind, new string[] { faxId }); string etag = EtagServices.ComputeEtag(faxentry.Payload, true); // new etag if (correlatedResSyncInfos.Length == 0) { nextTick = tickProvider.CreateNextTick(resourceKind); // create next tick ResSyncInfo resyncInfo = new ResSyncInfo(Guid.NewGuid(), endpoint, nextTick, etag, DateTime.Now); CorrelatedResSyncInfo info = new CorrelatedResSyncInfo(faxId, resyncInfo); correlatedResSyncInfoStore.Put(resourceKind, info); syncDigestStore.PersistNewer(resourceKind, info.ResSyncInfo); } else if (!correlatedResSyncInfos[0].ResSyncInfo.Etag.Equals(etag)) { nextTick = tickProvider.CreateNextTick(resourceKind); correlatedResSyncInfos[0].ResSyncInfo.Etag = etag; correlatedResSyncInfos[0].ResSyncInfo.Tick = nextTick; correlatedResSyncInfos[0].ResSyncInfo.Endpoint = endpoint; correlatedResSyncInfos[0].ResSyncInfo.ModifiedStamp = DateTime.Now; correlatedResSyncInfoStore.Put(resourceKind, correlatedResSyncInfos[0]); syncDigestStore.PersistNewer(resourceKind, correlatedResSyncInfos[0].ResSyncInfo); } } } #endregion } else { for (int index = 0; index < changedIdentites.Length; index++) { string id = changedIdentites[index].Id; // receive the feed entry for local identity SyncFeedEntry entry = wrapper.GetFeedEntry(id); if (entry == null) { continue; } // receive the correlation for the local identity CorrelatedResSyncInfo[] correlatedResSyncInfos = correlatedResSyncInfoStore.GetByLocalId(resourceKind, new string[] { id }); string etag = EtagServices.ComputeEtag(entry.Payload, true); // new etag if (correlatedResSyncInfos.Length == 0) { nextTick = tickProvider.CreateNextTick(resourceKind); // create next tick ResSyncInfo resyncInfo = new ResSyncInfo(Guid.NewGuid(), endpoint, nextTick, etag, DateTime.Now); CorrelatedResSyncInfo info = new CorrelatedResSyncInfo(id, resyncInfo); correlatedResSyncInfoStore.Put(resourceKind, info); syncDigestStore.PersistNewer(resourceKind, info.ResSyncInfo); } else if (!correlatedResSyncInfos[0].ResSyncInfo.Etag.Equals(etag)) { nextTick = tickProvider.CreateNextTick(resourceKind); correlatedResSyncInfos[0].ResSyncInfo.Etag = etag; correlatedResSyncInfos[0].ResSyncInfo.Tick = nextTick; correlatedResSyncInfos[0].ResSyncInfo.Endpoint = endpoint; correlatedResSyncInfos[0].ResSyncInfo.ModifiedStamp = DateTime.Now; correlatedResSyncInfoStore.Put(resourceKind, correlatedResSyncInfos[0]); syncDigestStore.PersistNewer(resourceKind, correlatedResSyncInfos[0].ResSyncInfo); } } } #region store next token appBookmarkInfoStore.Put(resourceKind, nextToken); #endregion // set tracking phase lock (_parentPerformer._asyncStateObj) { _parentPerformer._asyncStateObj.Tracking.Phase = TrackingPhase.GETCHANGESBYTICK; } // Receive syncDigestInfo if (null != syncDigestInfo) { ICorrelatedResSyncInfoEnumerator enumerator; List <string> endpoints = new List <string>(); foreach (SyncFeedDigestEntry digestEntry in syncDigestInfo.Entries) { endpoints.Add(digestEntry.Endpoint); enumerator = correlatedResSyncInfoStore.GetSinceTick(resourceKind, digestEntry.Endpoint, digestEntry.Tick - 2); while (enumerator.MoveNext()) { // No lock needed, as we expect that CorrelatedResSyncInfos list is // only acceeded anywhere else when Tracking phase is 'finish'. //lock(_parentPerformer._asyncStateObj) //{ _parentPerformer._asyncStateObj.CorrelatedResSyncInfos.Add(enumerator.Current); //} } } SyncDigestInfo sourceSyncDigestInfo = syncDigestStore.Get(resourceKind); foreach (SyncDigestEntryInfo digestEntry in sourceSyncDigestInfo) { if (endpoints.Contains(digestEntry.Endpoint)) { continue; } endpoints.Add(digestEntry.Endpoint); enumerator = correlatedResSyncInfoStore.GetSinceTick(resourceKind, digestEntry.Endpoint, -1); while (enumerator.MoveNext()) { // No lock needed, as we expect that CorrelatedResSyncInfos list is // only acceeded anywhere else when Tracking phase is 'finish'. //lock(_parentPerformer._asyncStateObj) //{ _parentPerformer._asyncStateObj.CorrelatedResSyncInfos.Add(enumerator.Current); //} } } if (!endpoints.Contains(endpoint)) { enumerator = correlatedResSyncInfoStore.GetSinceTick(resourceKind, endpoint, -1); while (enumerator.MoveNext()) { // No lock needed, as we expect that CorrelatedResSyncInfos list is // only acceeded anywhere else when Tracking phase is 'finish'. //lock(_parentPerformer._asyncStateObj) //{ _parentPerformer._asyncStateObj.CorrelatedResSyncInfos.Add(enumerator.Current); //} } } } // Set tracking phase lock (_parentPerformer._asyncStateObj.Tracking) { _parentPerformer._asyncStateObj.Tracking.Phase = TrackingPhase.FINISH; } }