//internal bool IfWriteThread() //{ // return (_masterTrie.NestedTablesCoordinator.ModificationThreadId == System.Threading.Thread.CurrentThread.ManagedThreadId); //} internal NestedTable GetTable <TKey>(TKey key, uint tableIndex, bool insertIsAllowed) { byte[] btKey = DataTypesConvertor.ConvertKey <TKey>(key); LTrieRow row = null; if (insertIsAllowed) //Insert of table is allowed by calls generation { row = table.GetKey(ref btKey, null); return(table.GetTable(row, ref btKey, tableIndex, this._masterTrie, true, false)); } //Only selects are allowed if (_masterTrie.NestedTablesCoordinator.ModificationThreadId == System.Threading.Thread.CurrentThread.ManagedThreadId) { //This thread must NOT use cache row = table.GetKey(ref btKey, null); return(table.GetTable(row, ref btKey, tableIndex, this._masterTrie, false, false)); } else { LTrieRootNode readRootNode = new LTrieRootNode(table); row = table.GetKey(ref btKey, readRootNode); return(table.GetTable(row, ref btKey, tableIndex, this._masterTrie, false, true)); } }
private void ReadUserLastFileNumber() { byte[] btKeyName = Encoding.UTF8.GetBytes(LastFileNumberKeyName); LTrieRow row = LTrie.GetKey(btKeyName, false, false); if (row.Exists) { byte[] fullValue = row.GetFullValue(true); LastFileNumber = fullValue.To_UInt64_BigEndian(); } }
/// <summary> /// Returns physical path to the table file, if table doesn't exists in the Scheme returns String.Empty /// </summary> /// <param name="userTableName"></param> /// <returns></returns> public string GetTablePathFromTableName(string userTableName) { //For user usage _sync_openTablesHolder.EnterReadLock(); try { byte[] btTableName = GetUserTableNameAsByte(userTableName); LTrieRow row = LTrie.GetKey(btTableName, true, false); if (!row.Exists) { return(String.Empty); } byte[] fullValue = row.GetFullValue(true); //Can be parsed different. First protocol version is 1 ushort schemeProtocol = fullValue.Substring(0, 2).To_UInt16_BigEndian(); ulong fileName = 0; switch (schemeProtocol) { case 1: fileName = fullValue.Substring(2, 8).To_UInt64_BigEndian(); break; default: throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.SCHEME_FILE_PROTOCOL_IS_UNKNOWN); } string alternativeTableLocation = String.Empty; if (CheckAlternativeTableLocationsIntersections(userTableName, out alternativeTableLocation)) { if (alternativeTableLocation == String.Empty) { return("MEMORY"); } else { return(Path.Combine(alternativeTableLocation, fileName.ToString())); } } else { return(Path.Combine(Engine.MainFolder, fileName.ToString())); } } finally { _sync_openTablesHolder.ExitReadLock(); } }
//byte[] btKey = null; public Row(LTrieRow row, LTrie masterTrie, bool useCache) { if (row == null) { _exists = false; } else { _row = row; //_root = row._root; //_ptrToValue = row.LinkToValue; _exists = row.Exists; } _useCache = useCache; _masterTrie = masterTrie; if (_exists) { _key = DataTypesConvertor.ConvertBack <TKey>(row.Key); } }
/// <summary> /// ItBwdFromTo /// </summary> /// <param name="gn"></param> /// <param name="generationMapLine"></param> /// <param name="useCache"></param> /// <returns></returns> private IEnumerable<LTrieRow> ItBwdFromTo(LTrieGenerationNode gn, byte[] generationMapLine, bool useCache) { byte[] key = null; LTrieRow row = null; long valueStartPtr = 0; uint valueLength = 0; byte[] xValue = null; byte[] gml = null; int startFrom = 0; if (keyIsFound) { startFrom = 255; //will check starting from KidsValue and then 0-255 } else { //Kid is still not found if (generationMapLine.Length > initialKey.Length) { startFrom = 256; } else { startFrom = initialKey[generationMapLine.Length - 1]; } } foreach (var kd in gn.KidsInNode.GetKidsBackward(startFrom)) { if (kd.ValueKid || !kd.LinkToNode) { //Value Kid if (ReturnKeyValuePair) { this._root.Tree.Cache.ReadKeyValue(useCache, kd.Ptr, out valueStartPtr, out valueLength, out key, out xValue); } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); } if (keyIsFound) { //We return this one key if ((includeStopKey) ? key.IfStringArrayBiggerOrEqualThen(endKey) : key.IfStringArrayBiggerThen(endKey)) { row = new LTrieRow(this._root); if (ReturnKeyValuePair) { row.ValueStartPointer = valueStartPtr; row.ValueFullLength = valueLength; row.Value = xValue; row.ValueIsReadOut = true; } row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } else { yield return null; break; } } else { //Checking if key equals to the found element, bigger or smaller //Key is still not found if ((includeStartKey) ? key.IfStringArraySmallerOrEqualThen(initialKey) : key.IfStringArraySmallerThen(initialKey)) { keyIsFound = true; if ((includeStopKey) ? key.IfStringArrayBiggerOrEqualThen(endKey) : key.IfStringArrayBiggerThen(endKey)) { //We return this one key row = new LTrieRow(this._root); if (ReturnKeyValuePair) { row.ValueStartPointer = valueStartPtr; row.ValueFullLength = valueLength; row.Value = xValue; row.ValueIsReadOut = true; } row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } else { yield return null; break; } } } } else { if (!keyIsFound && startFrom != 256 && startFrom > kd.Val) keyIsFound = true; //It's a Link To Node, gettign new generation Node LTrieGenerationNode gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); //generationMapLine = generationMapLine.Concat(gn1.Value); //gn1.ReadSelf(useCache, generationMapLine); //foreach (var xr in ItBwdFromTo(gn1, generationMapLine, useCache)) foreach (var xr in ItBwdFromTo(gn1, gml, useCache)) { if (xr == null) { yield return null; break; } yield return xr; } } } }
private IEnumerable<LTrieRow> ItBwdForMaximal(LTrieGenerationNode gn, byte[] generationMapLine, bool useCache) { byte[] key = null; LTrieRow row = null; long valueStartPtr = 0; uint valueLength = 0; byte[] xValue = null; byte[] gml = null; foreach (var kd in gn.KidsInNode.GetKidsBackward()) { if (kd.ValueKid || !kd.LinkToNode) { //Value Kid //Raise Up Counter, iterate further if counter permits //Console.WriteLine("KN: {0}", key.ToBytesString("")); if (ReturnKeyValuePair) { this._root.Tree.Cache.ReadKeyValue(useCache, kd.Ptr, out valueStartPtr, out valueLength, out key, out xValue); } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); } row = new LTrieRow(this._root); if (ReturnKeyValuePair) { row.ValueStartPointer = valueStartPtr; row.ValueFullLength = valueLength; row.Value = xValue; row.ValueIsReadOut = true; } row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } else { //It's a Link To Node, gettign new generation Node LTrieGenerationNode gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); //generationMapLine = generationMapLine.Concat(gn1.Value); //gn1.ReadSelf(useCache, generationMapLine); foreach (var xr in ItBwdForMaximal(gn1, gml, useCache)) //foreach (var xr in ItBwdForMaximal(gn1, generationMapLine, useCache)) { yield return xr; } } } }
public IEnumerable<LTrieRow> IterateBackwardStartsWith(byte[] initKey, bool useCache) { if (initKey.Length < 1) yield break; LTrieGenerationNode gn = null; initialKey = initKey; LTrieGenerationMap _generationMap = new LTrieGenerationMap(); //_generationMap.Clear(); //if (_generationMap.Count() == 0) //{ //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this._root); gn.Pointer = this._root.LinkToZeroNode; //gn.Value=0; - default _generationMap.Add(0, gn); gn.ReadSelf(useCache, _generationMap.GenerateMapNodesValuesUpToIndex(0)); //} //ulong cnt = 0; byte[] generationMapLine = new byte[1] { 0 }; byte[] gml = null; LTrieGenerationNode gn1 = null; byte[] key = null; LTrieRow row = null; //bool kFnd = false; foreach (var kd in gn.KidsInNode.GetKidsBackward(initialKey[0])) { //For first linke only if (kd.Val != initKey[0]) continue; //Kid can be value link or node link //if value link we can count 1 up if (kd.ValueKid || !kd.LinkToNode) { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); //Console.WriteLine("KN: {0}", key.ToBytesString("")); if (key.IfStringArrayStartsWith(initialKey)) { //cnt++; row = new LTrieRow(this._root); row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } } else { gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); //generationMapLine = generationMapLine.Concat(gn1.Value); //gn1.ReadSelf(useCache, generationMapLine); //foreach (var xr in ItBwdStartsWith(gn1, generationMapLine, 1, true, useCache)) foreach (var xr in ItBwdStartsWith(gn1, gml, 1, useCache)) { //cnt++; yield return xr; } } } //Console.WriteLine("CNT: {0}", cnt); }
public IEnumerable<LTrieRow> IterateBackwardStartFrom(byte[] initKey, bool inclStartKey, bool useCache) { LTrieGenerationNode gn = null; initialKey = initKey; includeStartKey = inclStartKey; LTrieGenerationMap _generationMap = new LTrieGenerationMap(); //if (_generationMap.Count() == 0) //{ //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this._root); gn.Pointer = this._root.LinkToZeroNode; //gn.Value=0; - default _generationMap.Add(0, gn); gn.ReadSelf(useCache, _generationMap.GenerateMapNodesValuesUpToIndex(0)); //} //ulong cnt = 0; //NEED ONLY FOR SKIP byte[] generationMapLine = new byte[1] { 0 }; byte[] gml = null; LTrieGenerationNode gn1 = null; byte[] key = null; LTrieRow row = null; long valueStartPtr = 0; uint valueLength = 0; byte[] xValue = null; //Starting from first key. It's interesting inside of RecursiveYieldReturn to look Starting from value //If intialKey index already bigger then its own length //But for the first must be enough foreach (var kd in gn.KidsInNode.GetKidsBackward(initialKey[0])) { //Console.WriteLine("KN: {0}", key.ToBytesString("")); //Kid can be value link or node link //if value link we can count 1 up if (kd.ValueKid || !kd.LinkToNode) { if (keyIsFound) { //We return this one key //cnt++; row = new LTrieRow(this._root); if (ReturnKeyValuePair) { this._root.Tree.Cache.ReadKeyValue(useCache, kd.Ptr, out valueStartPtr, out valueLength, out key, out xValue); row.ValueStartPointer = valueStartPtr; row.ValueFullLength = valueLength; row.Value = xValue; row.ValueIsReadOut = true; } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); } row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } else { if (ReturnKeyValuePair) { this._root.Tree.Cache.ReadKeyValue(useCache, kd.Ptr, out valueStartPtr, out valueLength, out key, out xValue); } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); } //Checking if key equals to the found element, bigger or smaller //Key is still not found if ((includeStartKey) ? key.IfStringArraySmallerOrEqualThen(initialKey) : key.IfStringArraySmallerThen(initialKey)) //if(key.IfStringArraySmallerThen(initialKey)) //if (IfFirstKeyIsSmallerThenCompareKey(key, initialKey)) { keyIsFound = true; //We return this one key //We dont apply reading key with value here, using LazyLoading //cnt++; row = new LTrieRow(this._root); if (ReturnKeyValuePair) { row.ValueStartPointer = valueStartPtr; row.ValueFullLength = valueLength; row.Value = xValue; row.ValueIsReadOut = true; } row.Key = key; row.LinkToValue = kd.Ptr; yield return row; //going on iteration } } } else { if (!keyIsFound && initialKey[0] > kd.Val) keyIsFound = true; gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; //increasing map line must hold already 2 elements gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); //generationMapLine = generationMapLine.Concat(gn1.Value); //gn1.ReadSelf(useCache, generationMapLine); //foreach (var xr in ItBwdStartFrom(gn1, generationMapLine, useCache)) foreach (var xr in ItBwdStartFrom(gn1, gml, useCache)) { //cnt++; //NEED ONLY FOR SKIP yield return xr; } } } //Console.WriteLine("CNT: {0}", cnt); }
public IEnumerable<LTrieRow> IterateBackward(bool useCache) { LTrieGenerationNode gn = null; LTrieGenerationMap _generationMap = new LTrieGenerationMap(); //_generationMap.Clear(); //if (_generationMap.Count() == 0) //{ //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this._root); gn.Pointer = this._root.LinkToZeroNode; //gn.Value=0; - default _generationMap.Add(0, gn); gn.ReadSelf(useCache, _generationMap.GenerateMapNodesValuesUpToIndex(0)); //} //ulong cnt = 0; byte[] generationMapLine = new byte[1] { 0 }; byte[] gml = null; LTrieGenerationNode gn1 = null; byte[] key = null; LTrieRow row = null; long valueStartPtr = 0; uint valueLength = 0; byte[] xValue = null; foreach (var kd in gn.KidsInNode.GetKidsBackward()) { //Kid can be value link or node link //if value link we can count 1 up if (kd.ValueKid || !kd.LinkToNode) { //Console.WriteLine("KN: {0}", key.ToBytesString("")); //cnt++; row = new LTrieRow(this._root); if (ReturnKeyValuePair) { this._root.Tree.Cache.ReadKeyValue(useCache, kd.Ptr, out valueStartPtr, out valueLength, out key, out xValue); row.ValueStartPointer = valueStartPtr; row.ValueFullLength = valueLength; row.Value = xValue; row.ValueIsReadOut = true; } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); } row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } else { gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); //generationMapLine = generationMapLine.Concat(gn1.Value); //gn1.ReadSelf(useCache, generationMapLine); //foreach (var xr in ItBwd(gn1, generationMapLine, useCache)) foreach (var xr in ItBwd(gn1, gml, useCache)) { //cnt++; yield return xr; } } } //Console.WriteLine("CNT: {0}", cnt); }
private IEnumerable<LTrieRow> ItBwdStartsWith(LTrieGenerationNode gn, byte[] generationMapLine, int deep, bool useCache) { byte[] key = null; LTrieRow row = null; byte[] gml = null; long valueStartPtr = 0; uint valueLength = 0; byte[] xValue = null; foreach (var kd in gn.KidsInNode.GetKidsBackward()) { //deep corresponds to search key(initialKey) index for compare value //deep can be bigger then initKey //in small deep kd.Value can represent link to node if (deep > (initialKey.Length-1)) { //we are bigger then supplied key for search (initialKey) if (kd.ValueKid || !kd.LinkToNode) { //visualize all possible if (ReturnKeyValuePair) { this._root.Tree.Cache.ReadKeyValue(useCache, kd.Ptr, out valueStartPtr, out valueLength, out key, out xValue); } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); } row = new LTrieRow(this._root); row.Key = key; if (ReturnKeyValuePair) { row.ValueStartPointer = valueStartPtr; row.ValueFullLength = valueLength; row.Value = xValue; row.ValueIsReadOut = true; } row.LinkToValue = kd.Ptr; yield return row; } else { //grow with ability to show all LTrieGenerationNode gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); foreach (var xr in ItBwdStartsWith(gn1, gml, deep + 1, useCache)) { yield return xr; } } } else { //search indexes still cooresponds to data if (kd.Val == initialKey[deep]) //and we can compare every supplied byte with index { if (deep == (initialKey.Length - 1)) { //final index length value if (kd.ValueKid || !kd.LinkToNode) { //visualize if (ReturnKeyValuePair) { this._root.Tree.Cache.ReadKeyValue(useCache, kd.Ptr, out valueStartPtr, out valueLength, out key, out xValue); } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); } row = new LTrieRow(this._root); if (ReturnKeyValuePair) { row.ValueStartPointer = valueStartPtr; row.ValueFullLength = valueLength; row.Value = xValue; row.ValueIsReadOut = true; } row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } else { //grow with ability to show all LTrieGenerationNode gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); foreach (var xr in ItBwdStartsWith(gn1, gml, deep + 1, useCache)) { yield return xr; } } } else { //smaller then final index length if (kd.ValueKid || !kd.LinkToNode) { //do nothing in case of ValueKid if (!kd.ValueKid) { //Link to Value, probably this value suits to us key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); if (key.IfStringArrayStartsWith(initialKey)) { //visualize row = new LTrieRow(this._root); row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } } } else { //grow up LTrieGenerationNode gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); foreach (var xr in ItBwdStartsWith(gn1, gml, deep + 1, useCache)) { yield return xr; } } } } else { //do nothing } } } }
//bool keyIsFound = false; private IEnumerable<LTrieRow> ItBwdSkipFrom(LTrieGenerationNode gn, byte[] generationMapLine, bool useCache) { byte[] key = null; LTrieRow row = null; byte[] gml = null; long valueStartPtr = 0; uint valueLength = 0; byte[] xValue = null; int startFrom = 0; if (keyIsFound) { startFrom = 255; //will check starting from KidsValue and then 0-255 } else { //Kid is still not found if (generationMapLine.Length > initialKey.Length) { startFrom = 256; } else { startFrom = initialKey[generationMapLine.Length - 1]; } } foreach (var kd in gn.KidsInNode.GetKidsBackward(startFrom)) { if (kd.ValueKid || !kd.LinkToNode) { //Value Kid if (keyIsFound) { //We return this one key skippedCnt++; if (skippedCnt > skippingTotal) { if (ReturnKeyValuePair) { this._root.Tree.Cache.ReadKeyValue(useCache, kd.Ptr, out valueStartPtr, out valueLength, out key, out xValue); } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); } row = new LTrieRow(this._root); if (ReturnKeyValuePair) { row.ValueStartPointer = valueStartPtr; row.ValueFullLength = valueLength; row.Value = xValue; row.ValueIsReadOut = true; } row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); //Checking if key equals to the found element, bigger or smaller //Key is still not found if (key.IfStringArraySmallerOrEqualThen(initialKey)) //if (key.IfStringArraySmallerThen(initialKey)) //if (IfFirstKeyIsSmallerThenCompareKey(key, initialKey)) { keyIsFound = true; //case if Startkey doesn't exist, then first encountered value can be calculated as first for skipping if (key.IfStringArraySmallerThen(initialKey)) { skippedCnt++; if (skippedCnt > skippingTotal) { // key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); row = new LTrieRow(this._root); row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } } } } } else { //It's a Link To Node, gettign new generation Node LTrieGenerationNode gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); //generationMapLine = generationMapLine.Concat(gn1.Value); //gn1.ReadSelf(useCache, generationMapLine); //foreach (var xr in ItBwdSkipFrom(gn1, generationMapLine, useCache)) foreach (var xr in ItBwdSkipFrom(gn1, gml, useCache)) { yield return xr; } } } }
/// <summary> /// Returns table for READ, WRITE FUNC /// </summary> /// <param name="userTableName"></param> /// <returns></returns> internal LTrie GetTable(string userTableName) { string tableName = GetUserTableNameAsString(userTableName); //TODO pattern based mapping If table doesn't exist we create it with properties which could be supplied after db init as regex theme. //Schema protocol: 2 bytes - protocol version, other data //For protocol 1: first 8 bytes will be TheFileName, starting from db10000-dbN (0-N ulong). up to 10000 are reserved for dbreeze. //Table names are UTF-8 based, no limits ulong fileName = 0; OpenTable otl = null; _sync_openTablesHolder.EnterUpgradeableReadLock(); try { _openTablesHolder.TryGetValue(tableName, out otl); if (otl != null) { //Try to increase usage and return LTrie otl.Add(); return(otl.Trie); } //Probably table Exists in db but not in openTablesHolder _sync_openTablesHolder.EnterWriteLock(); try { //UpgradeableRead recheck _openTablesHolder.TryGetValue(tableName, out otl); if (otl != null) { //Try to increase usage and return LTrie otl.Add(); return(otl.Trie); } byte[] btTableName = GetUserTableNameAsByte(userTableName); //Trying to get fileName from cache fileName = this.cachedTableNames.GetFileName(tableName); // LTrieRow row = null; bool tableExists = false; if (fileName == 0) { LTrieRow row = LTrie.GetKey(btTableName, false, false); if (row.Exists) { tableExists = true; byte[] fullValue = row.GetFullValue(false); //Can be parsed different. First protocol version is 1 ushort schemeProtocol = fullValue.Substring(0, 2).To_UInt16_BigEndian(); switch (schemeProtocol) { case 1: fileName = fullValue.Substring(2, 8).To_UInt64_BigEndian(); break; default: throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.SCHEME_FILE_PROTOCOL_IS_UNKNOWN); } } else { tableExists = false; //Creating new table. //Checking table name validity //this will throw exception, if not valid DbUserTables.UserTableNameIsOk(userTableName); //Creating such table and renewing LastFileNumber counter //Adding to LastFileNumber LastFileNumber++; ////Deleting physical files related to the table, if they existed - normally they should not //DeleteAllReleatedTableFiles(Path.Combine(Engine.MainFolder, LastFileNumber.ToString())); byte[] lft = LastFileNumber.To_8_bytes_array_BigEndian(); //Writing this number to Schema file LTrie.Add(Encoding.UTF8.GetBytes(LastFileNumberKeyName), lft); //Creating table self and writing to Schema file LTrie.Add(btTableName, new byte[] { 0, 1 } //Protocol version 1 .Concat(lft)); //Number of the file //Committing both records LTrie.Commit(); fileName = LastFileNumber; this.cachedTableNames.Add(tableName, fileName); } } else { tableExists = true; } //Creating LTrie, adding it to _openTablesHolder //Seeting up Trie TableName, OTHER SETTINGS TrieSettings ts = new TrieSettings(); IStorage storage = null; ////Checking if default Flusg Disk behaviour was overriden //ts.DiskFlushBehaviour = Engine.Configuration.DiskFlushBehaviour; ////Checking if we have alternative DiskFlush behaviour //foreach (var pattern in Engine.Configuration.AlternativeDiskFlushBehaviour) //{ // //pattern.Key // if (DbUserTables.PatternsIntersect(pattern.Key, userTableName)) // { // ts.DiskFlushBehaviour = pattern.Value; // break; // } //} string alternativeTableLocation = String.Empty; if (CheckAlternativeTableLocationsIntersections(userTableName, out alternativeTableLocation)) { ts.StorageWasOverriden = true; if (alternativeTableLocation == String.Empty) { ts.AlternativeTableStorageType = DBreezeConfiguration.eStorage.MEMORY; storage = new StorageLayer(Path.Combine(Engine.MainFolder, fileName.ToString()), ts, Engine.Configuration); } else { ts.AlternativeTableStorageType = DBreezeConfiguration.eStorage.DISK; ts.AlternativeTableStorageFolder = alternativeTableLocation; DirectoryInfo diAlt = new DirectoryInfo(alternativeTableLocation); if (!diAlt.Exists) { diAlt.Create(); } if (!tableExists) { //Deleting physical files related to the table, if they existed - normally they should not DeleteAllReleatedTableFiles(Path.Combine(ts.AlternativeTableStorageFolder, LastFileNumber.ToString())); } storage = new StorageLayer(Path.Combine(ts.AlternativeTableStorageFolder, fileName.ToString()), ts, Engine.Configuration); } } else { if (!tableExists) { //Deleting physical files related to the table, if they existed - normally they should not DeleteAllReleatedTableFiles(Path.Combine(Engine.MainFolder, LastFileNumber.ToString())); } storage = new StorageLayer(Path.Combine(Engine.MainFolder, fileName.ToString()), ts, Engine.Configuration); } //storage = new StorageLayer(Path.Combine(Engine.MainFolder, fileName.ToString()), ts, Engine.Configuration); LTrie trie = new LTrie(storage); //Setting LTrie user table name trie.TableName = userTableName; //_openTablesHolder.Add(tableName, trie); //Automatically increased usage in OpenTable constructor _openTablesHolder.Add(tableName, new OpenTable(trie)); return(trie); } catch (System.Exception ex) { //CASCADE throw ex; } finally { _sync_openTablesHolder.ExitWriteLock(); } } catch (Exception ex) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.SCHEME_GET_TABLE_WRITE_FAILED, tableName, ex); } finally { _sync_openTablesHolder.ExitUpgradeableReadLock(); } }
/// <summary> /// ONLY FOR INTERNAL NEEDS, lock must be handeled by outer procedure. /// Users must use GetTablePathFromTableName. /// Transactions Journal after start will try to delete RollbackFiles of the finished transactions. /// For this it needs to know exact pathes. /// For now all tables stored in one folder. Later we will have extra config file which lets to reside /// some of tables in the other folders. /// This function is an access globalizer to physical file locations by userTableName. /// !!!!TRAnJRNL, WHEN RESTORES ROLLBACK, MUST REFER TO Scheme trie settings in the future, FOR NOW DEFAULT /// </summary> /// <param name="userTableName"></param> /// <returns></returns> internal string GetPhysicalPathToTheUserTable(string userTableName) { try { byte[] btTableName = GetUserTableNameAsByte(userTableName); ulong fileName = 0; //Getting file name LTrieRow row = LTrie.GetKey(btTableName, false, false); if (row.Exists) { byte[] fullValue = row.GetFullValue(true); //Can be parsed different. First protocol version is 1 ushort schemeProtocol = fullValue.Substring(0, 2).To_UInt16_BigEndian(); switch (schemeProtocol) { case 1: fileName = fullValue.Substring(2, 8).To_UInt64_BigEndian(); break; default: throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.SCHEME_FILE_PROTOCOL_IS_UNKNOWN); } } else { return(String.Empty); } //Getting folder //For now returns path inside working folder, later re-make, take into consideration mapping of DB to tother folders. string alternativeTableLocation = String.Empty; if (CheckAlternativeTableLocationsIntersections(userTableName, out alternativeTableLocation)) { if (alternativeTableLocation == String.Empty) { //In memory table //return Path.Combine(Engine.MainFolder, fileName.ToString()); return("MEMORY"); } else { //returning alternative folder + fileName return(Path.Combine(alternativeTableLocation, fileName.ToString())); } } else { //Standard path (Dbreeze mainFolder + fileName) return(Path.Combine(Engine.MainFolder, fileName.ToString())); } } //catch (System.Threading.ThreadAbortException ex) //{ // //We don'T make DBisOperable = false; // throw ex; //} catch (Exception ex) { this.Engine.DBisOperable = false; this.Engine.DBisOperableReason = "GetPhysicalPathToTheUserTable"; throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.GENERAL_EXCEPTION_DB_NOT_OPERABLE, this.Engine.DBisOperableReason, ex); } }
public IEnumerable<LTrieRow> IterateForwardStartsWith(byte[] initKey, bool useCache) { if (initKey.Length < 1) yield break; LTrieGenerationNode gn = null; initialKey = initKey; LTrieGenerationMap _generationMap = new LTrieGenerationMap(); //if (_generationMap.Count() == 0) //{ //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this._root); gn.Pointer = this._root.LinkToZeroNode; //gn.Value=0; - default _generationMap.Add(0, gn); gn.ReadSelf(useCache, _generationMap.GenerateMapNodesValuesUpToIndex(0)); //} //ulong cnt = 0; //NEED ONLY FOR SKIP byte[] generationMapLine = new byte[1] { 0 }; byte[] gml = null; LTrieGenerationNode gn1 = null; byte[] key = null; LTrieRow row = null; //Starting from first key. It's interesting inside of RecursiveYieldReturn to look Starting from value //If intialKey index already bigger then its own length //But for the first must be enough foreach (var kd in gn.KidsInNode.GetKidsForward(initialKey[0])) { if (kd.Val != initKey[0]) continue; //Console.WriteLine("KN: {0}", key.ToBytesString("")); //Kid can be value link or node link //if value link we can count 1 up if (kd.ValueKid || !kd.LinkToNode) { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); if (key.IfStringArrayStartsWith(initialKey)) { //cnt++; row = new LTrieRow(this._root); row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } } else { gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; //increasing map line must hold already 2 elements gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); //generationMapLine = generationMapLine.Concat(gn1.Value); //gn1.ReadSelf(useCache, generationMapLine); //foreach (var xr in ItFrwStartsWith(gn1, generationMapLine, 1, true, useCache)) foreach (var xr in ItFrwStartsWith(gn1, gml, 1, useCache)) { yield return xr; } } } //Console.WriteLine("CNT: {0}", cnt); }
public IEnumerable<LTrieRow> IterateForwardSkipFrom(byte[] initKey, ulong skippingQuantity, bool useCache) { LTrieGenerationNode gn = null; initialKey = initKey; skippingTotal = skippingQuantity; LTrieGenerationMap _generationMap = new LTrieGenerationMap(); //if (_generationMap.Count() == 0) //{ //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this._root); gn.Pointer = this._root.LinkToZeroNode; //gn.Value=0; - default _generationMap.Add(0, gn); gn.ReadSelf(useCache, _generationMap.GenerateMapNodesValuesUpToIndex(0)); //} //ulong cnt = 0; //NEED ONLY FOR SKIP byte[] generationMapLine = new byte[1] { 0 }; byte[] gml = null; LTrieGenerationNode gn1 = null; byte[] key = null; LTrieRow row = null; long valueStartPtr = 0; uint valueLength = 0; byte[] xValue = null; //Starting from first key. It's interesting inside of RecursiveYieldReturn to look Starting from value //If intialKey index already bigger then its own length //But for the first must be enough foreach (var kd in gn.KidsInNode.GetKidsForward(initialKey[0])) { //Console.WriteLine("KN: {0}", key.ToBytesString("")); //Kid can be value link or node link //if value link we can count 1 up if (kd.ValueKid || !kd.LinkToNode) { if (keyIsFound) { //We return this one key, if quantity of skips is enough skippedCnt++; if (skippedCnt > skippingTotal) { if (ReturnKeyValuePair) { this._root.Tree.Cache.ReadKeyValue(useCache, kd.Ptr, out valueStartPtr, out valueLength, out key, out xValue); } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); } //cnt++; row = new LTrieRow(this._root); if (ReturnKeyValuePair) { row.ValueStartPointer = valueStartPtr; row.ValueFullLength = valueLength; row.Value = xValue; row.ValueIsReadOut = true; } row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } } else { key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); //Checking if key equals to the found element, bigger or smaller //Key is still not found if (key.IfStringArrayBiggerOrEqualThen(initialKey)) { keyIsFound = true; //case if Startkey doesn't exist, then first encountered value can be calculated as first for skipping if (key.IfStringArrayBiggerThen(initialKey)) { skippedCnt++; if (skippedCnt > skippingTotal) { //key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); row = new LTrieRow(this._root); row.Key = key; row.LinkToValue = kd.Ptr; yield return row; } } } } } else { //special case when from key doesn't exist if (initialKey[0] < kd.Val) keyIsFound = true; gn1 = new LTrieGenerationNode(this._root); gn1.Pointer = kd.Ptr; gn1.Value = (byte)kd.Val; //increasing map line must hold already 2 elements gml = generationMapLine.Concat(gn1.Value); gn1.ReadSelf(useCache, gml); //generationMapLine = generationMapLine.Concat(gn1.Value); //gn1.ReadSelf(useCache, generationMapLine); //foreach (var xr in ItFrwSkipFrom(gn1, generationMapLine, useCache)) foreach (var xr in ItFrwSkipFrom(gn1, gml, useCache)) { //cnt++; //NEED ONLY FOR SKIP yield return xr; } } } //Console.WriteLine("CNT: {0}", cnt); }