/// <summary> /// Adds node to collection and cache /// </summary> /// <param name="identifier">Node identifier</param> /// <param name="node">Node to add</param> public void SetNode(TIdentifier identifier, Node <TIdentifier, TNodeData, TEdgeData> node) { if (parentProvider.Contains(identifier)) { parentProvider.Remove(identifier); } cacheProvider.SetNode(identifier, node); }
/// <summary> /// Gets node from collection by an identifier. First attempt to read from cache. /// </summary> /// <param name="nodeId">Node identifier</param> /// <returns>Node object</returns> public Node <TIdentifier, TNodeData, TEdgeData> GetNode(TIdentifier identifier, NodeAccess access) { if (cacheProvider.Contains(identifier)) { return(cacheProvider.GetNode(identifier, access)); } // Read from parent -> move to cache Node <TIdentifier, TNodeData, TEdgeData> node = parentProvider.GetNode(identifier, access); parentProvider.Remove(identifier); cacheProvider.SetNode(identifier, node); return(node); }
/// <summary> /// Initialize global root node if not found /// </summary> private void InitializeRoot() { if (!nodes.Contains(Constants.SnapshotsNodeId)) { var node = BPlusTreeOperations.CreateRootNode(NodeType.Collection, Constants.SnapshotsNodeId); nodes.SetNode(Constants.SnapshotsNodeId, node); } }
/// <summary> /// Adds node to collection and cache /// </summary> /// <param name="identifier">Node identifier</param> /// <param name="node">Node to add</param> public void SetNode(TIdentifier identifier, Node <TIdentifier, TNodeData, TEdgeData> node) { rwLock.AcquireWriterLock(-1); try { if (parentProvider.Contains(identifier)) { parentProvider.Remove(identifier); } cacheProvider.SetNode(identifier, node); } finally { rwLock.ReleaseLock(); } }
/// <summary> /// Initializes snapshots node /// </summary> /// <returns>True if snapshots were initialized for the first time</returns> public bool InitializeSnapshots() { if (!provider.Contains(Constants.SnapshotsNodeId)) { var snapshotsNode = new Node <Guid, object, EdgeData>(NodeType.SnapshotsRoot, null); provider.SetNode(Constants.SnapshotsNodeId, snapshotsNode); return(true); } return(false); }
/// <summary> /// Gets node from collection by an identifier /// </summary> /// <param name="nodeId">Node identifier</param> /// <returns>Node object</returns> public Node <Guid, object, EdgeData> GetNode(Guid nodeId, NodeAccess access) { CheckThread(); if (access == NodeAccess.ReadWrite) { EnsureNode(nodeId); return(isolatedProvider.GetNode(nodeId, access)); } else { if (isolatedProvider.Contains(nodeId)) { return(isolatedProvider.GetNode(nodeId, access)); } else { return(parentProvider.GetNode(nodeId, access)); } } }
/// <summary> /// Returns list of parents for given node witin a snapshot /// </summary> /// <param name="snapshotId">Snapshot within parents are requested</param> /// <param name="nodeId">Node which parents are returned</param> /// <returns>List of parent node identifiers for each node in dictionary format, or null if there are no parent edges</returns> public IEnumerator <Edge <Guid, EdgeData> > ParentEdges(Guid snapshotId, Guid nodeId) { lock (dataSync) { // Generate parents if they dont exist if (!createdNodes) { createdNodes = true; AddParentsRecursive(snapshotId, new Hashtable(), nodes); lastSnapshotId = snapshotId; } // Do we have the last snapshot in the memory if (snapshotId != lastSnapshotId) { // Try going for fallback provider if (fallbackParentMapProvider != null) { return(fallbackParentMapProvider.ParentEdges(snapshotId, nodeId)); } else { // If not, generate asked snapshot nodes.Clear(); AddParentsRecursive(snapshotId, new Hashtable(), nodes); lastSnapshotId = snapshotId; } } // Find edge leading to holder node for given ID if (nodes.Contains(nodeId)) { return(BPlusTreeOperations.GetEnumerator(nodes, nodeId, EdgeType.Contains)); } else { return(null); } } }
/// <summary> /// Determines if collection contains a node with given identifier. Check is done on cache first. /// </summary> /// <param name="identifier">Identifier to check</param> /// <returns>True if contains</returns> public bool Contains(TIdentifier identifier) { rwLock.AcquireReaderLock(-1); try { if (cacheProvider.Contains(identifier)) { return(true); } return(parentProvider.Contains(identifier)); } finally { rwLock.ReleaseLock(); } }
/// <summary> /// Initializes new type system by importing types or upgrading existing type definitions /// </summary> /// <param name="types">Types to import</param> /// <returns>Dictionary mapping between interface type and type Id </returns> public Dictionary<Type, Guid> InitializeTypeSystem(Type[] types) { typeToIdMapping = new Dictionary<Type, Guid>(); typeIdToTypeMapping = new Dictionary<Guid, Type>(); if (provider.Contains(Constants.TypesNodeId)) { // TODO (nsabo) Type and data upgrade procedure } else { provider.SetNode(Constants.TypesNodeId, new Node<Guid, object, EdgeData>(NodeType.TypesRoot, null)); EnsureBasicScalarTypes(); foreach (var type in types) { AddType(type); } //TODO (nsabo) Cleanup on type validation error, or use isolated provider? } foreach(var typeId in GetTypes()) { var type = GetTypeFromId(typeId); typeToIdMapping.Add(type, typeId); typeIdToTypeMapping.Add(typeId, type); Type collectionType = null; if (Utils.IsCollectionType(type, ref collectionType)) { collectionTypesTable.Add(typeId, type); } if (Utils.IsDictionaryType(type, ref collectionType)) { dictionaryTypesTable.Add(typeId, type); } } CacheScalarTypes(); return typeToIdMapping; }
internal static void LogNodesRecursive(Guid nodeId, INodeProvider <Guid, object, EdgeData> nodes, INodeProvider <Guid, object, EdgeData> changes, int tabLevel, Hashtable visited, TypesService typesService) { if (visited.ContainsKey(nodeId)) { Debug.WriteLine(LogTabs(tabLevel) + nodeId); return; } visited.Add(nodeId, null); if (changes.Contains(nodeId)) { var node = changes.GetNode(nodeId, NodeAccess.Read); switch (node.NodeType) { case NodeType.Object: LogObject(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; case NodeType.Collection: LogCollection(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; case NodeType.Dictionary: LogCollection(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; default: Debug.WriteLine(LogTabs(tabLevel) + node.Previous + "->" + nodeId + "[" + node.NodeType + "]"); foreach (var edge in node.Edges) { Debug.WriteLine(LogTabs(tabLevel) + edge.Key + "="); LogNodesRecursive(edge.Value.ToNodeId, nodes, changes, tabLevel + 1, visited, typesService); } break; } } else { Debug.WriteLine(LogTabs(tabLevel) + nodeId); } }
/// <summary> /// Recursive breadth-first pass through node graph which generates parent information /// </summary> /// <param name="snapshotId">Snapshot to generate</param> /// <param name="nodeId">Visited node</param> /// <param name="visitedNodes">List of visited nodes</param> private void AddParentsRecursive(Guid nodeId, Hashtable visitedNodes, INodeProvider <Guid, object, EdgeData> nodes) { if (nodeId.Equals(Constants.NullReferenceNodeId)) { return; } if (visitedNodes.ContainsKey(nodeId)) { return; } else { visitedNodes.Add(nodeId, null); } // Add the node as parent of all child nodes foreach (var edge in dataNodeProvider.GetNode(nodeId, NodeAccess.Read).Edges.Values) { if (EdgeFilter(edge)) { if (!nodes.Contains(edge.ToNodeId)) { var holderNode = BPlusTreeOperations.CreateRootNode(NodeType.Collection, edge.ToNodeId); nodes.SetNode(edge.ToNodeId, holderNode); } 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); } } } foreach (var edge in dataNodeProvider.GetNode(nodeId, NodeAccess.Read).Edges.Values) { AddParentsRecursive(edge.ToNodeId, visitedNodes, nodes); } }
/// <summary> /// Determines if collection contains a node with given identifier /// </summary> /// <param name="identifier">Identifier to check</param> /// <returns>True if contains</returns> public bool Contains(Guid identifier) { CheckThread(); return(isolatedProvider.Contains(identifier) || parentProvider.Contains(identifier)); }
internal static void LogNodesRecursive(Guid nodeId, INodeProvider<Guid, object, EdgeData> nodes, INodeProvider<Guid, object, EdgeData> changes, int tabLevel, Hashtable visited, TypesService typesService) { if (visited.ContainsKey(nodeId)) { Debug.WriteLine(LogTabs(tabLevel) + nodeId); return; } visited.Add(nodeId, null); if (changes.Contains(nodeId)) { var node = changes.GetNode(nodeId, NodeAccess.Read); switch (node.NodeType) { case NodeType.Object: LogObject(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; case NodeType.Collection: LogCollection(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; case NodeType.Dictionary: LogCollection(nodeId, node, nodes, changes, tabLevel, visited, typesService); break; default: Debug.WriteLine(LogTabs(tabLevel) + node.Previous + "->" + nodeId + "[" + node.NodeType + "]"); foreach (var edge in node.Edges) { Debug.WriteLine(LogTabs(tabLevel) + edge.Key + "="); LogNodesRecursive(edge.Value.ToNodeId, nodes, changes, tabLevel + 1, visited, typesService); } break; } } else { Debug.WriteLine(LogTabs(tabLevel) + nodeId); } }