/// <summary> /// Creates new instance of CommitDataService type /// </summary> /// <param name="nodes">Nodes which will accept data changes</param> /// <param name="snapshotsService">Service which handles snapshots</param> /// <param name="mutableParentProvider">Provider of node parent information</param> public CommitDataService(INodeProvider<Guid, object, EdgeData> nodes, TypesService typesService, SnapshotsService snapshotsService, IParentMapProvider<Guid, object, EdgeData> mutableParentProvider, IParentMapProvider<Guid, object, EdgeData> immutableParentProvider, IChangeSetProvider<Guid, object, EdgeData> changeSetProvider, NodeMergeExecutor nodeMergeExecutor, ICollectedNodesProvider<Guid, object, EdgeData> collectedNodesProvider) { this.nodes = nodes; this.snapshotsService = snapshotsService; this.mutableParentProvider = mutableParentProvider; this.immutableParentProvider = immutableParentProvider; this.changeSetProvider = changeSetProvider; this.nodeMergeExecutor = nodeMergeExecutor; this.typesService = typesService; this.collectedNodesProvider = collectedNodesProvider; }
/// <summary> /// Creates new instance of CommitDataService type /// </summary> /// <param name="nodes">Nodes which will accept data changes</param> /// <param name="snapshotsService">Service which handles snapshots</param> /// <param name="mutableParentProvider">Provider of node parent information</param> public CommitDataService(INodeProvider <Guid, object, EdgeData> nodes, TypesService typesService, SnapshotsService snapshotsService, IParentMapProvider <Guid, object, EdgeData> mutableParentProvider, IParentMapProvider <Guid, object, EdgeData> immutableParentProvider, IChangeSetProvider <Guid, object, EdgeData> changeSetProvider, NodeMergeExecutor nodeMergeExecutor, ICollectedNodesProvider <Guid, object, EdgeData> collectedNodesProvider) { this.nodes = nodes; this.snapshotsService = snapshotsService; this.mutableParentProvider = mutableParentProvider; this.immutableParentProvider = immutableParentProvider; this.changeSetProvider = changeSetProvider; this.nodeMergeExecutor = nodeMergeExecutor; this.typesService = typesService; this.collectedNodesProvider = collectedNodesProvider; }
private void InitializeServices(Type rootEntityType, Type[] entityTypes, UpgradeConfiguration upgradeConfiguration) { this.rootEntityType = rootEntityType; this.entityTypes = entityTypes; typesService = new TypesService(provider); objectSerializationService.TypesService = typesService; var interfaceToTypeIdMapping = typesService.InitializeTypeSystem(entityTypes); var completeTypesList = interfaceToTypeIdMapping.Keys; generationService = new GenerationService(typesService); // TODO (nsabo) Optional loading of proxy types from the given assembly (we dont want always to generate on small devices, Silverlight...) // Note: Collection/Dictionary types are not saved in the assembly var interfaceToGeneratedMapping = generationService.GenerateProxyTypes(completeTypesList, Properties.Settings.Default.SaveGeneratedAssemblyToDisk, Properties.Settings.Default.GeneratedAssemblyFileName); proxyCreatorService = new ProxyCreatorService(completeTypesList, interfaceToTypeIdMapping, interfaceToGeneratedMapping); snapshotsService = new SnapshotsService(provider); #region Parent map provider setup if (Properties.Settings.Default.ParentMappingFileStorageUsed) { // Usage of file for caching parent information var indexedFile = new IndexedFileStorage(new FileStream(this.parentMappingFileName, FileMode.Create), Properties.Settings.Default.ParentMappingFileBlockSize, false); indexedFile.Serializer = this.objectSerializationService; disposables.Add(indexedFile); var parentProviderStorage = new CachedWriteNodeProviderUnsafe <Guid, object, EdgeData>( new DirectNodeProviderUnsafe <Guid, object, EdgeData>(indexedFile, true), new LimitedDirectNodeProviderUnsafe <Guid, object, EdgeData>( new LimitedMemoryStorageUnsafe <Guid, object>(Properties.Settings.Default.ParentMappingMemoryMinimumCount, Properties.Settings.Default.ParentMappingMemoryMaximumCount), false) ); disposables.Add(parentProviderStorage); mutableParentProvider = new ParentMapProvider(parentProviderStorage, provider, null, true); } else { // Default parent information is stored in memory and has only the last snapshot available mutableParentProvider = new ParentMapProvider(new DirectNodeProviderUnsafe <Guid, object, EdgeData>(new MemoryStorageUnsafe <Guid, object>(), false), provider, null, true); } #endregion #region Merge rule provider setup IMergeRuleProvider mergeRuleProvider = null; if (SnapshotIsolationEnabled) { if (Properties.Settings.Default.ConcurrencyAutoOverrideResolution) { mergeRuleProvider = new AutoOverrideMergeRuleProvider(); } else { if (Properties.Settings.Default.ConcurrencyAttributesEnabled) { mergeRuleProvider = new AttributeBasedMergeRuleProvider(typesService); } else { throw new ArgumentException("No selected provider for merge rules in snapshot isolation conflicts. Check configuration of merge rule providers."); } } } #endregion #region Setup change set provider // TODO (nsabo) Provide option for change set safety when context goes offline, OfflineWorkspaces should enable commits when context is back online if (Properties.Settings.Default.ChangeSetHistoryFileStorageUsed) { var indexedFile = new IndexedFileStorage(new FileStream(Properties.Settings.Default.ChangeSetHistoryFileStorageFileName, FileMode.Create), 256, false); indexedFile.Serializer = this.objectSerializationService; disposables.Add(indexedFile); var changeSetProviderStorage = new CachedWriteNodeProviderUnsafe <Guid, object, EdgeData>( new DirectNodeProviderUnsafe <Guid, object, EdgeData>(indexedFile, true), new LimitedDirectNodeProviderUnsafe <Guid, object, EdgeData>( new LimitedMemoryStorageUnsafe <Guid, object>(Properties.Settings.Default.ChangeSetHistoryWriteCacheMinimumCount, Properties.Settings.Default.ChangeSetHistoryWriteCacheMaximumCount), false) ); disposables.Add(changeSetProviderStorage); changeSetProvider = new TrackingChangeSetProvider(changeSetProviderStorage); } else { changeSetProvider = new TrackingChangeSetProvider(new DirectNodeProviderUnsafe <Guid, object, EdgeData>(new MemoryStorageUnsafe <Guid, object>(), false)); } #endregion var immutableParentProvider = new ParentMapProvider(new DirectNodeProviderUnsafe <Guid, object, EdgeData>(new MemoryStorageUnsafe <Guid, object>(), false), provider, null, false); collectedNodesProvider = new CollectedNodesProvider(new DirectNodeProviderUnsafe <Guid, object, EdgeData>(new MemoryStorageUnsafe <Guid, object>(), false), provider); commitDataService = new CommitDataService(provider, typesService, snapshotsService, mutableParentProvider, immutableParentProvider, changeSetProvider, new NodeMergeExecutor(mergeRuleProvider, typesService), collectedNodesProvider); workspaceExclusiveLockProvider = new WorkspaceExclusiveLockProvider(); disposables.Add(workspaceExclusiveLockProvider); trackingWorkspaceStateProvider = new TrackingWorkspaceStateProvider(workspaceExclusiveLockProvider); objectInstancesService = new ObjectInstancesService(provider, typesService); subscriptionManagerService = new SubscriptionManagerService(typesService, objectInstancesService); workspaceFacade = new WorkspaceFacade(commitDataService, trackingWorkspaceStateProvider, subscriptionManagerService, snapshotsService, workspaceExclusiveLockProvider); backupService = new BackupService(); bool firstRun = snapshotsService.InitializeSnapshots(); if (firstRun) { InitializeDefaultSnapshot(); } else { OptimizeData(); } StaticProxyFacade.Initialize(typesService); }
/// <summary> /// Updates parent information based on change set /// </summary> /// <param name="changeSet">Data change description</param> public void UpdateParents(AppendableChangeSet <Guid, object, EdgeData> changeSet, ICollectedNodesProvider <Guid, object, EdgeData> collectedNodesProvider) { lock (dataSync) { if (changeSet.SourceSnapshotId != lastSnapshotId) { // If the last snapshot is not in the memory, clear and return nodes.Clear(); createdNodes = false; return; } using (var enumerator = collectedNodesProvider.GetEdges(changeSet.SourceSnapshotId)) { if (enumerator != null) { while (enumerator.MoveNext()) { if (nodes.Contains(enumerator.Current.ToNodeId)) { DeleteTree(enumerator.Current.ToNodeId); } // Get the old node var node = dataNodeProvider.GetNode(enumerator.Current.ToNodeId, NodeAccess.Read); // For every edge in old node foreach (var edge in node.Edges.Values) { if (EdgeFilter(edge)) { // Find holder in destination snapshot for referenced node if (nodes.Contains(edge.ToNodeId)) { BPlusTreeOperations.RemoveEdge(nodes, edge.ToNodeId, new EdgeData(EdgeType.Contains, enumerator.Current.ToNodeId), ParentsTreeOrder); } } } } } } // Add new node ids to map foreach (Guid nodeId in changeSet.Nodes.EnumerateNodes()) { var holderNode = BPlusTreeOperations.CreateRootNode(NodeType.Collection, nodeId); nodes.SetNode(nodeId, holderNode); } // Add reused nodes if needed foreach (Guid nodeId in changeSet.ReusedNodes.Keys) { if (!nodes.Contains(nodeId)) { var holderNode = BPlusTreeOperations.CreateRootNode(NodeType.Collection, nodeId); nodes.SetNode(nodeId, holderNode); } } // Add new node edges to map foreach (Guid nodeId in changeSet.Nodes.EnumerateNodes()) { var node = changeSet.Nodes.GetNode(nodeId, NodeAccess.Read); // Add this id into all referenced nodes foreach (var edge in node.Edges.Values) { if (EdgeFilter(edge)) { var edgeData = new EdgeData(EdgeType.Contains, nodeId); Edge <Guid, EdgeData> existingEdge = null; if (!BPlusTreeOperations.TryFindEdge(nodes, edge.ToNodeId, edgeData, out existingEdge)) { BPlusTreeOperations.InsertEdge(nodes, edge.ToNodeId, new Edge <Guid, EdgeData>(nodeId, edgeData), ParentsTreeOrder); } } } } // Set last snapshot as the destination ID lastSnapshotId = changeSet.DestinationSnapshotId; } }