/// <summary> /// Returns nodes with suppled StartsWith name or complete name /// </summary> /// <param name="nameStartsWithPart"></param> /// <param name="tran"></param> /// <returns></returns> public IEnumerable <DataAsTree> GetNodesByName(string nameStartsWithPart, DBreeze.Transactions.Transaction tran) { HashSet <DataAsTree> ret = new HashSet <DataAsTree>(); CheckTransaction(tran); SetupReadTables(tran); byte[] val = null; byte[] prt = null; DBreeze.DataTypes.Row <byte[], byte[]> nodeRow = null; foreach (var row in nt3Read.SelectForwardStartsWith <string, byte[]>(nameStartsWithPart)) { val = row.Value; int i = 0; while ((prt = val.Substring(i, 16)) != null) { nodeRow = nt2Read.Select <byte[], byte[]>(prt); if (nodeRow.Exists) { yield return(SetupNodeFromRow(nodeRow)); } i += 16; } } }
/// <summary> /// Internal /// </summary> /// <param name="row"></param> /// <returns></returns> DataAsTree SetupNodeFromRow(DBreeze.DataTypes.Row <byte[], byte[]> row) { DataAsTree node = null; byte[] val = row.Value; /* * Protocol: * 1byte - protocol version (starting from 1) * ... * than due to the protocol description */ node = new DataAsTree(); switch (val[0]) { case 1: //First protocol type /* * Protocol: * 1byte - protocol version (starting from 1) * 16bytes link to content (or 0) * 1byte - lenght of NodeName * Nbytes - Name */ if ((val[1] | val[2] | val[3] | val[4] | val[5] | val[6] | val[7] | val[8]) != 0) { //We got content node.ContentRef = val.Substring(1, 16); } node.NodeName = val.Substring(18, val[17]).UTF8_GetString(); break; } node.ParentNodeId = row.Key.Substring(0, 8).To_Int64_BigEndian(); node.NodeId = row.Key.Substring(8, 8).To_Int64_BigEndian(); CopyInternals(node); return(node); }
/// <summary> /// <para>Adding children to the node</para> /// Table, storing data structure, must be in tran.SynchronizeTables list. /// Then transaction must be Committed in the end by the programmer. /// </summary> /// <param name="node"></param> /// <returns>return node with setup parent id</returns> public DataAsTree AddNode(DataAsTree node) { CheckTransaction(); if (node == null) { throw new Exception("Nodes is not supplied"); } SetupWriteTables(); byte[] val = null; long maxId = this.RootNode.Transaction.Select <byte[], long>(this.RootNode.DBreezeTableName, new byte[] { 1 }).Value; bool skipToFillNameIndex = false; if (node.NodeId == 0) { //Insert node.ParentNodeId = this.NodeId; maxId++; node.NodeId = maxId; } else { //Update if (node.NodeId == node.ParentNodeId) { throw new Exception("node.NodeId can't be equal to node.ParentNodeId"); } var oldRow = this.RootNode.nt2Write.Select <byte[], byte[]>(node.ParentNodeId.To_8_bytes_array_BigEndian().Concat(node.NodeId.To_8_bytes_array_BigEndian())); if (oldRow.Exists) { var oldNode = SetupNodeFromRow(oldRow); if (!oldNode.NodeName.Equals(node.NodeName, StringComparison.OrdinalIgnoreCase)) { RemoveOldNodeFromNameIndex(oldNode.NodeName, node.ParentNodeId.To_8_bytes_array_BigEndian().Concat(node.NodeId.To_8_bytes_array_BigEndian())); } else { skipToFillNameIndex = true; } } else { if (maxId >= node.NodeId && maxId >= node.ParentNodeId) { //Such NodeId was probably deleted, and now wants to be reconnected. //We allow that } else { if (node.NodeId == node.ParentNodeId) { throw new Exception("Supplied node.NodeId or node.ParentNodeId don't exist"); } } } } //ParentNodeId(long),NodeId(long) byte[] key = node.ParentNodeId.To_8_bytes_array_BigEndian() .Concat(node.NodeId.To_8_bytes_array_BigEndian()); if (node.NodeContent != null) { node.ContentRef = this.RootNode.nt2Write.InsertDataBlock(node.ContentRef, node.NodeContent); } else { node.ContentRef = null; } val = SetupValueRowFromNode(node, 1); CopyInternals(node); this.RootNode.nt2Write.Insert <byte[], byte[]>(key, val); /*node.NodeName index support*/ if (!skipToFillNameIndex) { DBreeze.DataTypes.Row <string, byte[]> nodeNameIndexRow = null; byte[] btNodeNameIndex = null; nodeNameIndexRow = nt3Write.Select <string, byte[]>(node.NodeName.ToLower()); if (nodeNameIndexRow.Exists) { btNodeNameIndex = nodeNameIndexRow.Value.Concat(key); } else { btNodeNameIndex = key; } this.RootNode.nt3Write.Insert <string, byte[]>(node.NodeName.ToLower(), btNodeNameIndex); } /*-----------------------------*/ //Latest used Id this.RootNode.Transaction.Insert <byte[], long>(this.RootNode.DBreezeTableName, new byte[] { 1 }, maxId); return(node); }//eo func
/// <summary> /// <para>Adding children to the node</para> /// Table, storing data structure, must be in tran.SynchronizeTables list. /// Then transaction must be Committed in the end by the programmer. /// </summary> /// <param name="nodes">Nodes to add to current node</param> /// <param name="tran">Existing transaction. Table, storing data structure, must be in tran.SynchronizeTables list</param> /// <param name="maximalSpeed">set it to true to gain maximal saving speed</param> /// <returns>return node with setup parent id</returns> public DataAsTree AddNode(DataAsTree node, DBreeze.Transactions.Transaction tran, bool maximalSpeed = false) { CheckTransaction(tran); if (node == null) { throw new Exception("Nodes is not supplied"); } SetupWriteTables(tran, maximalSpeed); byte[] val = null; long maxId = tran.Select <byte[], long>(this.DBreezeTableName, new byte[] { 1 }).Value; bool skipToFillNameIndex = false; if (node.NodeId == 0) { //Insert node.ParentNodeId = this.NodeId; maxId++; node.NodeId = maxId; } else { //Update var oldRow = nt2Write.Select <byte[], byte[]>(node.ParentNodeId.To_8_bytes_array_BigEndian().Concat(node.NodeId.To_8_bytes_array_BigEndian())); if (oldRow.Exists) { var oldNode = SetupNodeFromRow(oldRow); if (!oldNode.NodeName.Equals(node.NodeName, StringComparison.OrdinalIgnoreCase)) { RemoveOldNodeFromNameIndex(oldNode.NodeName, node.ParentNodeId.To_8_bytes_array_BigEndian().Concat(node.NodeId.To_8_bytes_array_BigEndian())); } else { skipToFillNameIndex = true; } } else { //Fake? We create new row node.ParentNodeId = this.NodeId; maxId++; node.NodeId = maxId; } } //ParentNodeId(long),NodeId(long) byte[] key = node.ParentNodeId.To_8_bytes_array_BigEndian() .Concat(node.NodeId.To_8_bytes_array_BigEndian()); if (node.NodeContent != null) { node.ContentRef = nt2Write.InsertDataBlock(node.ContentRef, node.NodeContent); } else { node.ContentRef = null; } val = SetupValueRowFromNode(node, 1); CopyInternals(node); nt2Write.Insert <byte[], byte[]>(key, val); /*node.NodeName index support*/ if (!skipToFillNameIndex) { DBreeze.DataTypes.Row <string, byte[]> nodeNameIndexRow = null; byte[] btNodeNameIndex = null; nodeNameIndexRow = nt3Write.Select <string, byte[]>(node.NodeName.ToLower()); if (nodeNameIndexRow.Exists) { btNodeNameIndex = nodeNameIndexRow.Value.Concat(key); } else { btNodeNameIndex = key; } nt3Write.Insert <string, byte[]>(node.NodeName.ToLower(), btNodeNameIndex); } /*-----------------------------*/ //Latest used Id tran.Insert <byte[], long>(this.DBreezeTableName, new byte[] { 1 }, maxId); return(node); }//eo func