/// <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; }
/// <summary> /// Creates new instance of MutableParentMapProvider type /// </summary> /// <param name="nodes">Node provider which stores parent information nodes (must not be same as data nodes provider) </param> /// <param name="dataNodeProvider">Data nodes provider, being read only</param> /// <param name="fallbackParentMapProvider">Parent map provider used in case the parent information is asked for snapshot other than the last one</param> public ParentMapProvider(INodeProvider <Guid, object, EdgeData> nodes, INodeProvider <Guid, object, EdgeData> dataNodeProvider, IParentMapProvider <Guid, object, EdgeData> fallbackParentMapProvider, bool filterMutable) { if (nodes == dataNodeProvider) { throw new ArgumentException(); } this.nodes = nodes; this.dataNodeProvider = dataNodeProvider; this.fallbackParentMapProvider = fallbackParentMapProvider; this.filterMutable = filterMutable; }
private void GetCollectedNodesRecursive(Guid nodeId, AppendableChangeSet <Guid, object, EdgeData> changeSet, IParentMapProvider <Guid, object, EdgeData> mutableParentMap, IParentMapProvider <Guid, object, EdgeData> immutableParentMap, Hashtable collectedNodes, Hashtable visitedNodes) { if (visitedNodes.ContainsKey(nodeId)) { return; } visitedNodes.Add(nodeId, null); if (changeSet.ReusedNodes.ContainsKey(nodeId)) { // Reused nodes and their children are not to be collected return; } if (HasReusedParent(nodeId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, new Hashtable())) { return; } collectedNodes.Add(nodeId, null); var node = dataNodes.GetNode(nodeId, NodeAccess.Read); foreach (var edge in node.Edges.Values) { if (edge.Data.Semantic != EdgeType.OfType && edge.ToNodeId != Constants.NullReferenceNodeId) { GetCollectedNodesRecursive(edge.ToNodeId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, visitedNodes); } } }
/// <summary> /// Stores collectable nodes for a change set /// </summary> /// <param name="changeSet">Change set</param> /// <param name="mutableParentMap">Parent map of mutable data</param> /// <param name="immutableParentMap">Parent map of immutable data</param> public void StoreChangeset(AppendableChangeSet <Guid, object, EdgeData> changeSet, IParentMapProvider <Guid, object, EdgeData> mutableParentMap, IParentMapProvider <Guid, object, EdgeData> immutableParentMap) { Guid snapshotId = changeSet.SourceSnapshotId; var snapshotRoot = BPlusTreeOperations.CreateRootNode(NodeType.Collection, snapshotId); nodes.SetNode(snapshotId, snapshotRoot); Hashtable collectedNodes = new Hashtable(); GetCollectedNodesRecursive(changeSet.SourceSnapshotId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, new Hashtable()); foreach (Guid nodeId in collectedNodes.Keys) { BPlusTreeOperations.InsertEdge(nodes, snapshotId, new Edge <Guid, EdgeData>(nodeId, new EdgeData(EdgeType.ListItem, nodeId)), TreeOrder); } }
private bool HasReusedParent(Guid nodeId, AppendableChangeSet <Guid, object, EdgeData> changeSet, IParentMapProvider <Guid, object, EdgeData> mutableParentMap, IParentMapProvider <Guid, object, EdgeData> immutableParentMap, Hashtable collectedNodes, Hashtable visitedNodes) { if (visitedNodes.ContainsKey(nodeId)) { return((bool)visitedNodes[nodeId]); } visitedNodes.Add(nodeId, false); if (changeSet.ReusedNodes.ContainsKey(nodeId)) { return(true); } if (collectedNodes.ContainsKey(nodeId)) { return(false); } using (var mutableParentEnumerator = mutableParentMap.ParentEdges(changeSet.SourceSnapshotId, nodeId)) { if (mutableParentEnumerator != null) { while (mutableParentEnumerator.MoveNext()) { if (HasReusedParent(mutableParentEnumerator.Current.ToNodeId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, visitedNodes)) { return(true); } } } } using (var immutableParentEnumerator = immutableParentMap.ParentEdges(changeSet.SourceSnapshotId, nodeId)) { if (immutableParentEnumerator != null) { while (immutableParentEnumerator.MoveNext()) { if (HasReusedParent(immutableParentEnumerator.Current.ToNodeId, changeSet, mutableParentMap, immutableParentMap, collectedNodes, visitedNodes)) { return(true); } } } } return(false); }
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); }