/// <summary> /// Creates the output package. /// </summary> /// <param name="objectSpace">The object space.</param> /// <param name="recipient">The recipient.</param> /// <param name="packageType">Type of the package.</param> /// <returns>Output package</returns> public Package CreateOutputPackage(IObjectSpace objectSpace, ReplicationNode recipient, PackageType packageType) { var result = objectSpace.CreateObject<Package>(); result.ApplicationName = XafDeltaModule.XafApp.ApplicationName; result.SenderNodeId = Owner.CurrentNodeId; result.RecipientNodeId = recipient.NodeId; result.PackageType = packageType; // for broadcast package recipient node Id is "AllNodes" if (result.SenderNodeId == result.RecipientNodeId) result.RecipientNodeId = ReplicationNode.AllNodes; // assign package id if (packageType == PackageType.Snapshot) { recipient.SnapshotDateTime = DateTime.UtcNow; recipient.LastSavedSnapshotNumber++; result.PackageId = recipient.LastSavedSnapshotNumber; } else { recipient.LastSavedPackageNumber++; result.PackageId = recipient.LastSavedPackageNumber; } return result; }
public OutgoingReplicationHandler(ReplicationLoader parent, DocumentDatabase database, ReplicationNode node, bool external, TcpConnectionInfo connectionInfo) { _parent = parent; _database = database; Destination = node; _external = external; _log = LoggingSource.Instance.GetLogger <OutgoingReplicationHandler>(_database.Name); _connectionInfo = connectionInfo; _database.Changes.OnDocumentChange += OnDocumentChange; _cts = CancellationTokenSource.CreateLinkedTokenSource(_database.DatabaseShutdown); }
public long?GetLastReplicatedEtagForDestination(ReplicationNode dest) { foreach (var replicationHandler in _outgoing) { if (replicationHandler.Node.IsEqualTo(dest)) { return(replicationHandler._lastSentDocumentEtag); } } return(null); }
public override bool IsEqualTo(ReplicationNode other) { if (other is ExternalReplication externalReplication) { return(string.Equals(ConnectionStringName, externalReplication.ConnectionStringName, StringComparison.OrdinalIgnoreCase) && TaskId == externalReplication.TaskId && string.Equals(externalReplication.Name, Name, StringComparison.OrdinalIgnoreCase) && string.Equals(externalReplication.Database, Database, StringComparison.OrdinalIgnoreCase)); } return(false); }
public override bool IsEqualTo(ReplicationNode other) { if (other is PullReplicationAsSink sink) { return(base.IsEqualTo(other) && string.Equals(HubDefinitionName, sink.HubDefinitionName) && string.Equals(CertificatePassword, sink.CertificatePassword) && string.Equals(CertificateWithPrivateKey, sink.CertificateWithPrivateKey)); } return(false); }
/// <summary> /// Loads pending packages. /// </summary> /// <param name="worker">The worker.</param> public bool Load(ActionWorker worker) { if (IsLoading) { return(false); } bool loadResult; Owner.DoBeforeLoad(new LoadEventArgs(worker)); worker.ReportProgress(Localizer.LoadingStarted); Interlocked.Increment(ref loadNesting); try { using (var applicationObjectSpace = XafDeltaModule.XafApp.CreateObjectSpace()) { var currentNodeId = ReplicationNode.GetCurrentNodeId(applicationObjectSpace); // select pending input packages var inputPackages = applicationObjectSpace.GetObjects <Package>(CriteriaOperator.Parse( "ApplicationName = ? And (RecipientNodeId = ? Or RecipientNodeId = ?) " + "And (SenderNodeId <> ?)", Owner.ApplicationName, currentNodeId, ReplicationNode.AllNodes, Owner.CurrentNodeId)). Where(x => x.LoadedDateTime == DateTime.MinValue).ToList(); worker.ReportProgress(string.Format(Localizer.PackagesSelectedForLoading, inputPackages.Count)); // load each package until cancellation or error occured loadResult = true; foreach (var inputPackage in inputPackages.OrderBy(x => x.PackageDateTime).TakeWhile(z => !worker.CancellationPending)) { // loadResult &= LoadPackage(new LoadPackageContext(inputReplica,worker, applicationObjectSpace, currentNodeId)); loadResult &= LoadPackage(worker, inputPackage); if (!loadResult) { break; } } applicationObjectSpace.CommitChanges(); } } finally { Interlocked.Decrement(ref loadNesting); worker.ReportProgress(Color.Blue, Localizer.LoadingIsFinished); } Owner.DoAfterLoad(new LoadEventArgs(worker)); return(loadResult); }
public BuildContext(IObjectSpace objectSpace, Dictionary <object, object> doneObjects, IObjectSpace packageObjectSpace, ReplicationNode targetNode, ActionWorker worker, Queue <object> mapQueue, HashSet <string> selectedSourceObjects, List <IModelClass> selectedTypes) { ObjectSpace = objectSpace; DoneObjects = doneObjects; PackageObjectSpace = packageObjectSpace; TargetNode = targetNode; Worker = worker; MapQueue = mapQueue; SelectedSourceObjects = selectedSourceObjects; SelectedTypes = selectedTypes; }
/// <summary> /// Restore the last loaded number from marker. /// </summary> /// <param name="context">The context.</param> /// <param name="snapshotObjectSpace">The snapshot object space.</param> private static void restoreLastLoadedNum(LoadPackageContext context, IObjectSpace snapshotObjectSpace) { var marker = PackageMarker.GetInstance(snapshotObjectSpace); if (marker == null) { return; } var sender = ReplicationNode.FindNode(context.ObjectSpace, marker.SenderNodeId); if (sender != null) { sender.LastLoadedPackageNumber = marker.LastSavedPackageNumber; } }
private TcpConnectionInfo GetConnectionInfo(ReplicationNode node, bool external) { var shutdownInfo = new ConnectionShutdownInfo { Node = node, External = external }; _outgoingFailureInfo.TryAdd(node, shutdownInfo); try { if (node is ExternalReplication exNode) { using (var requestExecutor = RequestExecutor.Create(exNode.ConnectionString.TopologyDiscoveryUrls, exNode.ConnectionString.Database, _server.Server.Certificate.Certificate, DocumentConventions.Default)) using (_server.ContextPool.AllocateOperationContext(out TransactionOperationContext ctx)) { var database = exNode.ConnectionString.Database; var cmd = new GetTcpInfoCommand("extrenal-replication", database); requestExecutor.Execute(cmd, ctx); node.Database = database; node.Url = requestExecutor.Url; return(cmd.Result); } } if (node is InternalReplication internalNode) { using (var cts = new CancellationTokenSource(_server.Engine.TcpConnectionTimeout)) { return(ReplicationUtils.GetTcpInfo(internalNode.Url, internalNode.Database, "Replication", _server.Server.Certificate.Certificate, cts.Token)); } } throw new InvalidOperationException( $"Unexpected replication node type, Expected to be '{typeof(ExternalReplication)}' or '{typeof(InternalReplication)}', but got '{node.GetType()}'"); } catch (Exception e) { // will try to fetch it again later if (_log.IsInfoEnabled) { _log.Info($"Failed to fetch tcp connection information for the destination '{node.FromString()}' , the connection will be retried later.", e); } _reconnectQueue.TryAdd(shutdownInfo); } return(null); }
/// <summary> /// Creates the package object reference. /// </summary> /// <param name="source">The source object.</param> /// <param name="destinationSession">The destination session.</param> /// <param name="targetNode">The target replication node</param> /// <returns>Package object reference</returns> public static PackageObjectReference CreatePackageObjectReference(object source, Session destinationSession, ReplicationNode targetNode) { PackageObjectReference result = null; if (source != null && source is IXPObject) { result = new PackageObjectReference(destinationSession); result.Assign(source); var maps = OidMap.GetOidMaps((IXPObject)source); var sb = new StringBuilder(); foreach (var oidMap in maps) sb.AppendFormat("{0}\a{1}\n", oidMap.NodeId, oidMap.ObjectId); result.KnownMapping = sb.ToString(); } return result; }
private void AddAndStartOutgoingReplication(ReplicationNode node, bool external) { var info = GetConnectionInfo(node, external); if (info == null) { // this means that we were unable to retrive the tcp connection info and will try it again later return; } var outgoingReplication = new OutgoingReplicationHandler(this, Database, node, external, info); outgoingReplication.Failed += OnOutgoingSendingFailed; outgoingReplication.SuccessfulTwoWaysCommunication += OnOutgoingSendingSucceeded; _outgoing.TryAdd(outgoingReplication); // can't fail, this is a brand new instance outgoingReplication.Start(); OutgoingReplicationAdded?.Invoke(outgoingReplication); }
private void AddAndStartOutgoingReplication(ReplicationNode node, bool external) { var outgoingReplication = new OutgoingReplicationHandler(this, Database, node, external); outgoingReplication.Failed += OnOutgoingSendingFailed; outgoingReplication.SuccessfulTwoWaysCommunication += OnOutgoingSendingSucceeded; _outgoing.TryAdd(outgoingReplication); // can't fail, this is a brand new instance node.Url = node.Url.Trim(); _outgoingFailureInfo.TryAdd(node, new ConnectionShutdownInfo { Node = node, External = external }); outgoingReplication.Start(); OutgoingReplicationAdded?.Invoke(outgoingReplication); }
/// <summary> /// Loads the package. /// </summary> /// <param name="worker">The worker.</param> /// <param name="package">The package.</param> public bool LoadPackage(ActionWorker worker, Package package) { bool result; Interlocked.Increment(ref loadNesting); try { using (var applicationObjectSpace = XafDeltaModule.XafApp.CreateObjectSpace()) { var currentNodeId = ReplicationNode.GetCurrentNodeId(applicationObjectSpace); result = LoadPackage(new LoadPackageContext(package, worker, applicationObjectSpace, currentNodeId)); applicationObjectSpace.CommitChanges(); } var packageObjectSpace = ObjectSpace.FindObjectSpaceByObject(package); packageObjectSpace.CommitChanges(); } finally { Interlocked.Decrement(ref loadNesting); } return(result); }
/// <summary> /// Verify package the is valid. /// </summary> /// <param name="context">The context.</param> /// <param name="senderNode">The sender node.</param> /// <returns></returns> private bool packageIsValid(LoadPackageContext context, ReplicationNode senderNode) { var packageIsValid = true; var errors = new List<string>(); if (!Owner.AnonymousPackagesAllowed && senderNode == null) { packageIsValid = false; var errorText = string.Format(Localizer.SenderNodeIsNotFound, context.Package.SenderNodeId, context.Package); context.Worker.ReportError( errorText); errors.Add(errorText); } var expectedPackageId = 1; if (senderNode != null) { switch (context.Package.PackageType) { case PackageType.Protocol: expectedPackageId = senderNode.LastLoadedPackageNumber + 1; break; case PackageType.Snapshot: expectedPackageId = senderNode.LastLoadedSnapshotNumber + 1; break; } } if (context.Package.PackageId != expectedPackageId) { packageIsValid = false; var errorText = string.Format(Localizer.InvalidPackageId, context.Package, context.Package.PackageId, expectedPackageId); context.Worker.ReportError( errorText); errors.Add(errorText); } if(context.Package.PackageData == null || context.Package.PackageData.Length == 0) { packageIsValid = false; var errorText = string.Format(Localizer.PackageDataIsEmpty, context.Package); context.Worker.ReportError( errorText); errors.Add(errorText); } if(!packageIsValid) { var errorString = string.Join("\n", errors.ToArray()); context.Package.CreateLogRecord(PackageEventType.Rejected, errorString); } return packageIsValid; }
public BuildContext(IObjectSpace objectSpace, Dictionary<object, object> doneObjects, IObjectSpace packageObjectSpace, ReplicationNode targetNode, ActionWorker worker, Queue<object> mapQueue, HashSet<string> selectedSourceObjects, List<IModelClass> selectedTypes) { ObjectSpace = objectSpace; DoneObjects = doneObjects; PackageObjectSpace = packageObjectSpace; TargetNode = targetNode; Worker = worker; MapQueue = mapQueue; SelectedSourceObjects = selectedSourceObjects; SelectedTypes = selectedTypes; }
/// <summary> /// Creates package record based on protocol record. /// </summary> /// <param name="packageSession">The package session.</param> /// <param name="protocolRecord">The protocol record.</param> /// <param name="targetNode">The target node.</param> /// <returns>Package record</returns> public static PackageRecord CreateForProtocolRecord(PackageSession packageSession, ProtocolRecord protocolRecord, ReplicationNode targetNode) { var destinationSession = packageSession.Session; var result = new PackageRecord(destinationSession) { PackageSession = packageSession, UserName = protocolRecord.UserName, Description = protocolRecord.Description, ModifiedOn = protocolRecord.ModifiedOn, NewBlobValue = protocolRecord.NewBlobValue, PropertyName = protocolRecord.PropertyName, NewValue = protocolRecord.NewValue, OldValue = protocolRecord.OldValue, OperationType = protocolRecord.OperationType }; if (protocolRecord.AuditedObject != null && protocolRecord.AuditedObject.Target != null) { result.AuditedObject = PackageObjectReference.CreatePackageObjectReference(protocolRecord.AuditedObject.Target, destinationSession, targetNode); result.AuditedObject.ReplicationKey = protocolRecord.ReplicationKey; } if (protocolRecord.NewObject != null) { result.NewObject = PackageObjectReference.CreatePackageObjectReference(protocolRecord.NewObject.Target, destinationSession, targetNode); } if (protocolRecord.OldObject != null) { result.OldObject = PackageObjectReference.CreatePackageObjectReference(protocolRecord.OldObject.Target, destinationSession, targetNode); } return(result); }
public override bool IsEqualTo(ReplicationNode other) { return(base.IsEqualTo(other) && string.Equals(Url, other.Url, StringComparison.OrdinalIgnoreCase)); }
private BuildSessionInfo(ReplicationNode targetNode, ProtocolSession protocolSession) { TargetNode = targetNode; ProtocolSession = protocolSession; ProtocolRecords = new List<ProtocolRecord>(); }
public static BuildSessionInfo GetInstance(ReplicationNode targetNode, ProtocolSession protocolSession) { List<BuildSessionInfo> list; if (!PacketTargets.TryGetValue(targetNode, out list)) { list = new List<BuildSessionInfo>(); PacketTargets.Add(targetNode, list); } var result = (from c in list where ReferenceEquals(c.ProtocolSession, protocolSession) select c).FirstOrDefault(); if (result == null) { result = new BuildSessionInfo(targetNode, protocolSession); list.Add(result); if (protocolSession.Parent != null) result.parent = GetInstance(targetNode, protocolSession.Parent); } return result; }
/// <summary> /// Creates the recipient context. /// </summary> /// <param name="context">The context.</param> /// <param name="recipient">The recipient.</param> /// <param name="genType">Type of the gen.</param> /// <returns></returns> private RecipientsContextBase createRecipientContext(SaveProtocolRecordParams context, ReplicationNode recipient, Type genType) { var result = (RecipientsContextBase)context.ObjectSpace.CreateObject(genType); result.RecipientNode = recipient; result.SenderNode = ReplicationNode.GetCurrentNode(context.ObjectSpace); result.ProtocolRecord = context.ProtocolRecord; /* 11.2.7 */ result.RoutingType = ((IModelReplicationNode)XafDeltaModule.XafApp.Model.GetNode("Replication")).RoutingType; return result; }
protected virtual void ModifyReplicationDestination(ReplicationNode replicationNode) { }
/// <summary> /// Creates package record based on protocol record. /// </summary> /// <param name="packageSession">The package session.</param> /// <param name="protocolRecord">The protocol record.</param> /// <param name="targetNode">The target node.</param> /// <returns>Package record</returns> public static PackageRecord CreateForProtocolRecord(PackageSession packageSession, ProtocolRecord protocolRecord, ReplicationNode targetNode) { var destinationSession = packageSession.Session; var result = new PackageRecord(destinationSession) { PackageSession = packageSession, UserName = protocolRecord.UserName, Description = protocolRecord.Description, ModifiedOn = protocolRecord.ModifiedOn, NewBlobValue = protocolRecord.NewBlobValue, PropertyName = protocolRecord.PropertyName, NewValue = protocolRecord.NewValue, OldValue = protocolRecord.OldValue, OperationType = protocolRecord.OperationType }; if(protocolRecord.AuditedObject != null && protocolRecord.AuditedObject.Target != null) { result.AuditedObject = PackageObjectReference.CreatePackageObjectReference(protocolRecord.AuditedObject.Target, destinationSession, targetNode); result.AuditedObject.ReplicationKey = protocolRecord.ReplicationKey; } if (protocolRecord.NewObject != null) result.NewObject = PackageObjectReference.CreatePackageObjectReference(protocolRecord.NewObject.Target, destinationSession, targetNode); if (protocolRecord.OldObject != null) result.OldObject = PackageObjectReference.CreatePackageObjectReference(protocolRecord.OldObject.Target, destinationSession, targetNode); return result; }
/// <summary> /// Loads the package. /// </summary> /// <param name="context">The load package params.</param> public bool LoadPackage(LoadPackageContext context) { // prevent loading self packages if (context.Package.SenderNodeId == context.CurrentNodeId) { return(false); } // don't load packages builded before last loaded snapshot var lastLoadedSnapshotDateTime = (from c in context.ObjectSpace.GetObjects <ReplicationNode>() select c.InitDateTime).Max(); if (context.Package.PackageDateTime < lastLoadedSnapshotDateTime) { return(true); } var senderNode = ReplicationNode.FindNode(context.ObjectSpace, context.Package.SenderNodeId); context.Worker.ReportProgress(string.Format(Localizer.LoadingPackage, context.Package)); var loadResult = false; if (packageIsValid(context, senderNode)) { Owner.DoBeforeLoadPackage(new LoadPackageEventArgs(context.Package)); context.Package.CreateLogRecord(PackageEventType.Loading, ""); var errorString = ""; switch (context.Package.PackageType) { case PackageType.Protocol: errorString = Owner.ProtocolReplicationService.LoadProtocolPackage(context); break; case PackageType.Snapshot: errorString = Owner.SnapshotService.LoadSnapshotPackage(context); break; } loadResult = string.IsNullOrEmpty(errorString); // rollback changes on error or abort if (!loadResult) { Owner.DoPackageLoadingError(new PackageLoadingErrorArgs(context, errorString)); context.ObjectSpace.Rollback(); // add and save log record context.Package.CreateLogRecord(PackageEventType.Failed, errorString); context.ObjectSpace.CommitChanges(); context.Worker.ReportError(Localizer.PackageLoadingIsFailed, context.Package); } else { // update last loaded package id for sender node senderNode = senderNode ?? ReplicationNode.FindNode(context.ObjectSpace, context.Package.SenderNodeId); if (senderNode != null) { switch (context.Package.PackageType) { case PackageType.Protocol: senderNode.LastLoadedPackageNumber = context.Package.PackageId; break; case PackageType.Snapshot: senderNode.LastLoadedSnapshotNumber = context.Package.PackageId; senderNode.InitDateTime = context.Package.PackageDateTime; break; } } context.Package.CreateLogRecord(PackageEventType.Loaded, ""); // save changes context.ObjectSpace.CommitChanges(); Owner.DoAfterLoadPackage(new LoadPackageEventArgs(context.Package)); context.Worker.ReportProgress(Color.Blue, Localizer.PackageLoadingCompleted, context.Package); } } else { Owner.DoInvalidPackage(new InvalidPackageArgs(context)); context.Worker.ReportError(Localizer.PackageRejected, context.Package); } return(loadResult); }
public BuildContext(IObjectSpace appObjectSpace, ObjectSpace snapObjectSpace, ReplicationNode targetNode, ActionWorker worker) { AppObjectSpace = appObjectSpace; SnapObjectSpace = snapObjectSpace; TargetNode = targetNode; Worker = worker; DoneObjects = new Queue<object>(); Map = new Dictionary<object, object>(); SnapSources = new Dictionary<IModelClass, IList<object>>(); }
public bool BuildSnapshot(ActionWorker worker, ReplicationNode targetNode) { if (targetNode == null) throw new ArgumentNullException("targetNode"); if (targetNode.Session.IsNewObject(targetNode)) throw new UnsavedTargetNodeException(); if (targetNode.Disabled) throw new DisabledTargetNodeException(); var result = false; worker.ReportProgress(string.Format(Localizer.BuildingSnapshotForNode, targetNode.Name)); XafDeltaModule.Instance.LoadService.BeginLoad(); using (var appObjectSpace = XafDeltaModule.XafApp.CreateObjectSpace()) { targetNode = appObjectSpace.GetObjectByKey<ReplicationNode>(targetNode.Oid); Owner.DoBeforeBuildPackages(new BeforeBuildPackagesArgs(appObjectSpace)); var package = Owner.MessagingService.CreateOutputPackage(appObjectSpace, targetNode, PackageType.Snapshot); try { var doneObjectsCount = 0; using (var snapObjectSpace = new ObjectSpace(package.UnitOfWork)) { var rootContext = new BuildContext(appObjectSpace, snapObjectSpace, targetNode, worker); foreach (var modelClass in XafDeltaModule.XafApp.Model.BOModel.Where(x => !x.NonSnapshot()) .TakeWhile(x => !worker.CancellationPending)) { if (!modelClass.TypeInfo.IsAbstract && modelClass.TypeInfo.IsPersistent && (modelClass.TypeInfo.IsInterface || modelClass.TypeInfo.Implements<IXPObject>())) doneObjectsCount += buildClassSnapshot(new ClassBuildContext(rootContext, modelClass)); } if (doneObjectsCount > 0 && !worker.CancellationPending) { worker.ReportProgress(Localizer.CommitChanges); snapObjectSpace.CommitChanges(); //snapshotPostBuild(snapObjectSpace); snapObjectSpace.CommitChanges(); createSnapshotMaps(rootContext); worker.ReportProgress(Localizer.CommitChanges); snapObjectSpace.CommitChanges(); worker.ReportProgress(string.Format(Localizer.TotalObjectsSnapshoted, doneObjectsCount)); result = true; } else { snapObjectSpace.Rollback(); if (worker.CancellationPending) worker.ReportProgress(Color.DarkMagenta, Localizer.Aborted); else worker.ReportProgress(Color.DarkMagenta, Localizer.NoObjectsFoundForSnapshot); } } package.CloseUnitOfWork(doneObjectsCount > 0 && !worker.CancellationPending); result &= !worker.CancellationPending; if (result) Owner.OnAfterBuildSnapshot(new AfterBuildSnapshotArgs(targetNode)); } catch (Exception exception) { worker.ReportError(Localizer.SnapshotFailed, exception.Message); result = false; } // on success, commit changes to app database and package storage if (result) { package.CreateLogRecord(PackageEventType.Created); appObjectSpace.CommitChanges(); } } XafDeltaModule.Instance.LoadService.EndLoad(); if (result) { worker.ReportProgress(Color.Blue, Localizer.SnapshotBuildingIs, (worker.CancellationPending ? Localizer.Aborted : Localizer.Finished)); } return result; }
/// <summary> /// Initializes a new instance of the <see cref="SaveProtocolParams"/> class. /// </summary> /// <param name="worker">The worker.</param> /// <param name="applicationObjectSpace">The modelApplication object space.</param> /// <param name="createdPackagesDict">The created packages dict.</param> /// <param name="allNodes">All nodes.</param> /// <param name="currentNode">The current node.</param> public SaveProtocolParams(ActionWorker worker, IObjectSpace applicationObjectSpace, Dictionary<ReplicationNode, PackageSaveInfo> createdPackagesDict, IEnumerable<ReplicationNode> allNodes, ReplicationNode currentNode) { Worker = worker; ObjectSpace = applicationObjectSpace; CreatedPackages = createdPackagesDict; AllNodes = allNodes; CurrentNode = currentNode; }
/// <summary> /// Initializes a new instance of the <see cref="AfterBuildSnapshotArgs"/> class. /// </summary> /// <param name="targetNode">The target node.</param> public AfterBuildSnapshotArgs(ReplicationNode targetNode) { TargetNode = targetNode; }
public BuildContext(IObjectSpace appObjectSpace, ObjectSpace snapObjectSpace, ReplicationNode targetNode, ActionWorker worker) { AppObjectSpace = appObjectSpace; SnapObjectSpace = snapObjectSpace; TargetNode = targetNode; Worker = worker; DoneObjects = new Queue <object>(); Map = new Dictionary <object, object>(); SnapSources = new Dictionary <IModelClass, IList <object> >(); }
protected override void ModifyReplicationDestination(ReplicationNode replicationNode) { //replicationNode.SkipIndexReplication = true; }
private void OutgoingReplicationConnectionFailed(ReplicationNode node, OutgoingReplicationFailureToConnectReporter outgoingFailureReporter) { _outgoingErrors.AddOrUpdate(node, outgoingFailureReporter, (_, __) => outgoingFailureReporter); }
/// <summary> /// Builds the snapshot. /// </summary> /// <param name="worker">The worker.</param> /// <param name="targetNode">The target node.</param> /// <returns></returns> public bool BuildSnapshot(ActionWorker worker, ReplicationNode targetNode) { if (targetNode == null) { throw new ArgumentNullException("targetNode"); } if (targetNode.Session.IsNewObject(targetNode)) { throw new UnsavedTargetNodeException(); } if (targetNode.Disabled) { throw new DisabledTargetNodeException(); } var result = false; worker.ReportProgress(string.Format(Localizer.BuildingSnapshotForNode, targetNode.Name)); XafDeltaModule.Instance.LoadService.BeginLoad(); using (var applicationObjectSpace = XafDeltaModule.XafApp.CreateObjectSpace()) { targetNode = applicationObjectSpace.GetObjectByKey <ReplicationNode>(targetNode.Oid); Owner.DoBeforeBuildPackages(new BeforeBuildPackagesArgs(applicationObjectSpace)); var package = Owner.MessagingService.CreateOutputPackage(applicationObjectSpace, targetNode, PackageType.Snapshot); try { var doneObjects = new Dictionary <object, object>(); using (var snapshotObjectSpace = new ObjectSpace(package.UnitOfWork)) { var mapStack = new Queue <object>(); var rootContext = new BuildContext(applicationObjectSpace, doneObjects, snapshotObjectSpace, targetNode, worker, mapStack, new HashSet <string>(), new List <IModelClass>()); foreach (var modelClass in XafDeltaModule.XafApp.Model.BOModel.Where(x => !x.NonSnapshot()) .TakeWhile(x => !worker.CancellationPending)) { if (!modelClass.TypeInfo.IsAbstract && modelClass.TypeInfo.IsPersistent && (modelClass.TypeInfo.IsInterface || modelClass.TypeInfo.Implements <IXPObject>())) { buildClassSnapshot(new ClassBuildContext(rootContext, modelClass)); } } if (doneObjects.Keys.Count > 0) { snapshotObjectSpace.CommitChanges(); snapshotPostBuild(snapshotObjectSpace); snapshotObjectSpace.CommitChanges(); createSnapshotMaps(rootContext); snapshotObjectSpace.CommitChanges(); worker.ReportProgress(string.Format(Localizer.TotalObjectsSnapshoted, doneObjects.Keys.Count)); result = true; } else { snapshotObjectSpace.Rollback(); worker.ReportProgress(Color.DarkMagenta, Localizer.NoObjectsFoundForSnapshot); } } package.CloseUnitOfWork(doneObjects.Keys.Count > 0); result &= !worker.CancellationPending; if (result) { Owner.OnAfterBuildSnapshot(new AfterBuildSnapshotArgs(targetNode)); } } catch (Exception exception) { worker.ReportError(Localizer.SnapshotFailed, exception.Message); result = false; } // on success, commit changes to app database and package storage if (result) { package.CreateLogRecord(PackageEventType.Created); applicationObjectSpace.CommitChanges(); } } XafDeltaModule.Instance.LoadService.EndLoad(); if (result) { worker.ReportProgress(Color.Blue, Localizer.SnapshotBuildingIs, (worker.CancellationPending ? Localizer.Aborted : Localizer.Finished)); } return(result); }
private void IncomingReplicationConnectionFailed(ReplicationNode node, IncomingReplicationFailureToConnectReporter incomingFailureReporter) { _incomingErrors.AddOrUpdate(node, incomingFailureReporter, (_, __) => incomingFailureReporter); }
/// <summary> /// Initializes a new instance of the <see cref="TriggerForTableCollection{TEntity}" /> class. /// </summary> /// <param name="table">The table.</param> internal TriggerForTableCollection(LocalDbRepository <TEntity> table) { _table = table; NotForReplication = new ReplicationNode <TEntity>(_table); WithReplication = new ReplicationNode <TEntity>(_table, NotForReplication); }
/// <summary> /// Creates the package record. /// </summary> /// <param name="context">The context.</param> /// <param name="recipient">The recipient.</param> private void createPackageRecord(SaveProtocolRecordParams context, ReplicationNode recipient) { // skip protocol records registered before last snapshot if (context.ProtocolRecord.ModifiedOn <= recipient.SnapshotDateTime) return; // look for recipient package in context.CreatedPackages dictionary. // if not found then create new one. if(!context.CreatedPackages.ContainsKey(recipient)) { var package = Owner.MessagingService.CreateOutputPackage(context.ObjectSpace, recipient, PackageType.Protocol); package.CreateLogRecord(PackageEventType.Created); context.CreatedPackages.Add(recipient, new PackageSaveInfo { Package = package }); context.Worker.ReportProgress(Color.Green, Localizer.PackageCreated, package.FileName); } // create PackageSession if needed var saveInfo = context.CreatedPackages[recipient]; var packageSession = PackageSession.CreateForProtocolSession(saveInfo.Package.UnitOfWork, context.ProtocolSession, context.CurrentNode.NodeId); saveInfo.CurrentSession = packageSession; // create package protocol record PackageRecord.CreateForProtocolRecord(saveInfo.CurrentSession, context.ProtocolRecord, recipient); }
/// <summary> /// Creates the package object reference. /// </summary> /// <param name="source">The source object.</param> /// <param name="destinationSession">The destination session.</param> /// <param name="targetNode">The target replication node</param> /// <returns>Package object reference</returns> public static PackageObjectReference CreatePackageObjectReference(object source, Session destinationSession, ReplicationNode targetNode) { PackageObjectReference result = null; if (source != null && source is IXPObject) { result = new PackageObjectReference(destinationSession); result.Assign(source); var maps = OidMap.GetOidMaps((IXPObject)source); var sb = new StringBuilder(); foreach (var oidMap in maps) { sb.AppendFormat("{0}\a{1}\n", oidMap.NodeId, oidMap.ObjectId); } result.KnownMapping = sb.ToString(); } return(result); }