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; } } } }
/// <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; } } } }
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> 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); }
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 } } } }
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); }
//#region "Checking Of Empty Pointer" ///// <summary> ///// Checks if pointer is empty ///// </summary> ///// <param name="ptr"></param> ///// <returns></returns> //public bool _IfPointerIsEmpty(byte[] ptr) //{ // //Executes 52 ms // #region "Settign up delegate" // switch (this.DefaultPointerLen) // { // case 5: //Gives ability to allocate file up to 1 terrabyte (1.099.511.627.775) // return !( // ptr[4] != 0 // || // ptr[3] != 0 // || // ptr[2] != 0 // || // ptr[1] != 0 // || // ptr[0] != 0 // ); // case 4: //4GB // return !( // ptr[3] != 0 // || // ptr[2] != 0 // || // ptr[1] != 0 // || // ptr[0] != 0 // ); // case 3: //17MB // return !( // ptr[2] != 0 // || // ptr[1] != 0 // || // ptr[0] != 0 // ); // case 6: //281 Terrabytes (281.474.976.710.655) // return !( // ptr[5] != 0 // || // ptr[4] != 0 // || // ptr[3] != 0 // || // ptr[2] != 0 // || // ptr[1] != 0 // || // ptr[0] != 0 // ); // case 7: //72 Petabytes (72.057.594.037.927.935) // return !( // ptr[6] != 0 // || // ptr[5] != 0 // || // ptr[4] != 0 // || // ptr[3] != 0 // || // ptr[2] != 0 // || // ptr[1] != 0 // || // ptr[0] != 0 // ); // case 2: //65 KB // return !( // ptr[1] != 0 // || // ptr[0] != 0 // ); // default: // return ptr._ByteArrayEquals(this.EmptyPointer); // } // #endregion //} //#endregion #region "DATA FETCHING" /// <summary> /// /// </summary> /// <param name="key"></param> /// <returns></returns> public LTrieRow GetKey(byte[] key, bool useCache) { //Later change TreeKVP (for RootNode Interface or smth like this) and make it unversal, this one must return value LTrieRow kv = new LTrieRow(this); kv.Key = key; //if (key == null || key.Length == 0) // return kv; if (key == null) { return(kv); } LTrieGenerationNode gn = null; if (_generationMap.Count() == 0) { //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this); gn.Pointer = this.LinkToZeroNode; //gn.Value=0; - default _generationMap.Add(0, gn); gn.ReadSelf(useCache, _generationMap.GenerateMapNodesValuesUpToIndex(0)); //gn.ReadSelf(); } bool cleanCheck = true; LTrieKid kidDef = null; int p = 0; int len = key.Length; /*SPECIAL CASE key = byte[0]*/ if (key.Length == 0) { kidDef = _generationMap[0].GetKidAsValue(true, 1); if (kidDef.Exists) { kv.LinkToValue = kidDef.Ptr; } return(kv); } /****************************/ for (int i = 0; i < len; i++) { //Getting kid from actual generation map if (cleanCheck && i != 0 && _generationMap.ContainsKey(i) && _generationMap[i].Value != key[i - 1]) { cleanCheck = false; _generationMap.RemoveBiggerOrEqualThenKey(i); } if (!_generationMap.ContainsKey(i)) { gn = new LTrieGenerationNode(this); gn.Value = key[i - 1]; gn.Pointer = _generationMap[i - 1].KidsInNode.GetPointerToTheKid(key[i - 1]); //FIND A SOLUTION FOR THIS NULL or EMPTY POINTER //if (gn.Pointer == null || this._IfPointerIsEmpty(gn.Pointer)) // return kv; if (gn.Pointer == null || gn.Pointer._IfPointerIsEmpty(this.DefaultPointerLen)) { return(kv); } _generationMap.Add(i, gn); gn.ReadSelf(useCache, _generationMap.GenerateMapNodesValuesUpToIndex(i)); //gn.ReadSelf(); } //Also if last element then supply 256 to get value not the link to value (if no value exit) //If kid is a link to next node we iterate further, if link on the value, we retrieve full key and value as link for TreeKVP stoping iteration //If link is empty (no kid) we return empty if (i >= key.Length) { p = i - 1; } else { p = i; } kidDef = _generationMap[i].GetKidAsValue((i >= (key.Length)), key[p]); if (kidDef.Exists) { if (kidDef.ValueKid) { kv.LinkToValue = kidDef.Ptr; return(kv); } if (!kidDef.LinkToNode) { //byte[] storedKey = _generationMap[i].ReadKidKeyFromValPtr(kidDef.Ptr); long valueStartPtr = 0; uint valueLength = 0; byte[] xValue = null; byte[] storedKey = null; if (!this.Tree.ValuesLazyLoadingIsOn) { this.Tree.Cache.ReadKeyValue(useCache, kidDef.Ptr, out valueStartPtr, out valueLength, out storedKey, out xValue); } else { storedKey = this.Tree.Cache.ReadKey(useCache, kidDef.Ptr); } // byte[] storedKey = this.Tree.Cache.ReadKey(useCache, kidDef.Ptr); if (key.Length != storedKey.Length || !key._ByteArrayEquals(storedKey)) { return(kv); } if (!this.Tree.ValuesLazyLoadingIsOn) { kv.ValueStartPointer = valueStartPtr; kv.ValueFullLength = valueLength; kv.Value = xValue; kv.ValueIsReadOut = true; } kv.LinkToValue = kidDef.Ptr; return(kv); } if (i == key.Length - 1) { len++; } //iterating further } else { return(kv); } } return(kv); }
//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> /// /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="WasUpdated">true means that value existed and was updated</param> /// <param name="dontUpdateIfExists">When true - if value exists, we dont update it. If WasUpdated = true then we value exists, if false - we have inserted new one</param> /// <returns></returns> public byte[] AddKey(ref byte[] key, ref byte[] value, out bool WasUpdated, bool dontUpdateIfExists) { //indicates that key we insert, already existed in the system and was updated WasUpdated = false; //if (key == null || key.Length == 0) // return; if (key == null) { return(null); } if (key.Length > UInt16.MaxValue) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.KEY_IS_TOO_LONG); } LTrieGenerationNode gn = null; if (_generationMap.Count() == 0) { //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this); gn.Pointer = this.LinkToZeroNode; //gn.Value=0; - default _generationMap.Add(0, gn); gn.ReadSelf(false, null); } LTrieSetupKidResult res = new LTrieSetupKidResult(); byte[] key1 = null; //we need it as null byte[] val1 = null; //len can be expanded inside of the algorithm maximum by one int len = key.Length; bool cleanCheck = true; /*Special case key is empty byte[0] */ if (key.Length == 0) { //Saving byte[0] key res = _generationMap[0].SetupKidWithValue((byte)0, true, ref key, ref value, false, out WasUpdated, dontUpdateIfExists); return(res.ValueLink); } /**/ for (int i = 0; i < len; i++) { //Getting kid from actual generation map if (cleanCheck && i != 0 && _generationMap.ContainsKey(i) && _generationMap[i].Value != key[i - 1]) { cleanCheck = false; //In case if i>0, it's not the first element and we have to compare if there are generation mapsstarting from this point. //If generationMap[i] exists and it's value not that what we want, we have to clean full in memory generation map as //Save_node... up to i Save_GM_nodes_Starting_From(i); //Remove Gen Map starting from... i _generationMap.RemoveBiggerOrEqualThenKey(i); } if (!_generationMap.ContainsKey(i)) { //All ok, for the first generation node //We read or create generation map //And add it to the _generationMap gn = new LTrieGenerationNode(this); gn.Value = key[i - 1]; gn.Pointer = _generationMap[i - 1].KidsInNode.GetPointerToTheKid(key[i - 1]); //gn.Pointer = _generationMap[i - 1].GetKidPointer(key[i - 1]); _generationMap.Add(i, gn); if (gn.Pointer != null) { gn.ReadSelf(false, null); } else { gn.Pointer = new byte[DefaultPointerLen]; //!!!!!!!!!!!!! Check if it'S really necessary or we can leave it as null } } //Generation Node in this trie can have link to kids [0-255] and link to the value. //If Kids>0 && Value Link is not Default Empty Pointer, then this value-link refers to the end of the sentence. //If Kids==0 && Value Link is not Default Empty Pointer, then this value-link refers to the sentence which can go after this last character, so also to the value. //Dual behaviour. if (res.KeyOldKid != null) { //It means that on this stage probably we have to setup both kids //We can check Length of both keys and their current condition //key1 = res.KeyOldKid; //we need it as null val1 = res.ValPtrOldKid; if ((res.KeyOldKid.Length - 1) < i) { _generationMap[i].SetupKidWithValue((byte)0, true, ref key1, ref val1, true, out WasUpdated, dontUpdateIfExists); } else { _generationMap[i].SetupKidWithValue(res.KeyOldKid[i], false, ref key1, ref val1, true, out WasUpdated, dontUpdateIfExists); } //Cleaning up KeyOldKid - probably not necessary, de bene esse (just in case) res.KeyOldKid = null; } //One more only then we setup value, otherwise we bind to the kid, Check Docs in fileDb LtrieSpreadExample1.jpg res = _generationMap[i].SetupKidWithValue(((i == key.Length) ? (byte)0 : key[i]), (i == key.Length), ref key, ref value, false, out WasUpdated, dontUpdateIfExists); if (!res.IterateFurther) { //After setting up value, we can just exit return(res.ValueLink); } else { //we don't need value on this phase, we can go on further //Expanding iteration cycle by one and, on the next iteration cycle we should go out from the loop. if (i == (key.Length - 1)) { len++; } } } //Should not happen as null, we have to return link to the full value return(null); } /// <summary> /// Returns link to the full value together with the key /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="startIndex"></param> /// <param name="WasUpdated">indicates that key we insert, already existed in the system and was updated</param> /// <returns></returns> public byte[] AddKeyPartially(ref byte[] key, ref byte[] value, uint startIndex, out long valueStartPtr, out bool WasUpdated) { WasUpdated = false; if (key == null) { valueStartPtr = -1; return(null); } if (key.Length > UInt16.MaxValue) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.KEY_IS_TOO_LONG); } if (value == null) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.PARTIAL_VALUE_CANT_BE_NULL); } LTrieGenerationNode gn = null; if (_generationMap.Count() == 0) { //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this); gn.Pointer = this.LinkToZeroNode; //gn.Value=0; - default _generationMap.Add(0, gn); gn.ReadSelf(false, null); } LTrieSetupKidResult res = new LTrieSetupKidResult(); byte[] key1 = null; //we need it as null byte[] val1 = null; //len can be expanded inside of the algorithm maximum by one int len = key.Length; bool cleanCheck = true; /*Special case key is empty byte[0] */ if (key.Length == 0) { //Saving byte[0] key res = _generationMap[0].SetupKidWithValuePartially((byte)0, true, ref key, ref value, false, startIndex, out valueStartPtr, out WasUpdated); return(res.ValueLink); } /**/ for (int i = 0; i < len; i++) { //Getting kid from actual generation map if (cleanCheck && i != 0 && _generationMap.ContainsKey(i) && _generationMap[i].Value != key[i - 1]) { cleanCheck = false; //In case if i>0, it's not the first element and we have to compare if there are generation mapsstarting from this point. //If generationMap[i] exists and it's value not that what we want, we have to clean full in memory generation map as //Save_node... up to i Save_GM_nodes_Starting_From(i); //Remove Gen Map starting from... i _generationMap.RemoveBiggerOrEqualThenKey(i); } if (!_generationMap.ContainsKey(i)) { //All ok, for the first generation node //We read or create generation map //And add it to the _generationMap gn = new LTrieGenerationNode(this); gn.Value = key[i - 1]; gn.Pointer = _generationMap[i - 1].KidsInNode.GetPointerToTheKid(key[i - 1]); //gn.Pointer = _generationMap[i - 1].GetKidPointer(key[i - 1]); _generationMap.Add(i, gn); if (gn.Pointer != null) { gn.ReadSelf(false, null); } else { gn.Pointer = new byte[DefaultPointerLen]; //!!!!!!!!!!!!! Check if it'S really necessary or we can leave it as null } } //Generation Node in this trie can have link to kids [0-255] and link to the value. //If Kids>0 && Value Link is not Default Empty Pointer, then this value-link refers to the end of the sentence. //If Kids==0 && Value Link is not Default Empty Pointer, then this value-link refers to the sentence which can go after this last character, so also to the value. //Dual behaviour. if (res.KeyOldKid != null) { //It means that on this stage probably we have to setup both kids //We can check Length of both keys and their current condition //key1 = res.KeyOldKid; //we need it as null val1 = res.ValPtrOldKid; if ((res.KeyOldKid.Length - 1) < i) { _generationMap[i].SetupKidWithValuePartially((byte)0, true, ref key1, ref val1, true, startIndex, out valueStartPtr, out WasUpdated); } else { _generationMap[i].SetupKidWithValuePartially(res.KeyOldKid[i], false, ref key1, ref val1, true, startIndex, out valueStartPtr, out WasUpdated); } //Cleaning up KeyOldKid - probably not necessary, de bene esse (just in case) res.KeyOldKid = null; } //One more only then we setup value, otherwise we bind to the kid, Check Docs in fileDb LtrieSpreadExample1.jpg res = _generationMap[i].SetupKidWithValuePartially(((i == key.Length) ? (byte)0 : key[i]), (i == key.Length), ref key, ref value, false, startIndex, out valueStartPtr, out WasUpdated); if (!res.IterateFurther) { //After setting up value, we can just exit return(res.ValueLink); } else { //we don't need value on this phase, we can go on further //Expanding iteration cycle by one and, on the next iteration cycle we should go out from the loop. if (i == (key.Length - 1)) { len++; } } } //Should not happen as null, we have to return link to the full value valueStartPtr = -1; return(null); } /// <summary> /// Check TransactionCommit in case of RemoveAll with file Recreation. /// Note if some other threads are reading parallel data, exception will be thrown in their transaction. /// It's correct. /// </summary> /// <param name="withFileRecreation"></param> public void RemoveAll(bool withFileRecreation) { if (!withFileRecreation) { LTrieGenerationNode gn = null; _generationMap.Clear(); if (_generationMap.Count() == 0) { //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this); gn.Pointer = this.LinkToZeroNode; //gn.Value=0; - default _generationMap.Add(0, gn); gn.ReadSelf(false, null); } _generationMap[0].RemoveAllKids(); } else { try { this.Tree.Cache.RecreateDB(); //Important, Better to re-read all generation nodes for safety reasons, de bene esse this._generationMap.Clear(); //And re-Read RootNode ReadRootNode(); } catch (Exception ex) { //////////////////// MADE THAT Table is not Opearable on the upper level, throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.RECREATE_TABLE_FAILED, this.Tree.TableName, ex); } } } /// <summary> /// Takes value fresh no committed value row.GetFullValue(false); /// </summary> /// <param name="oldKey"></param> /// <param name="newKey"></param> /// <returns></returns> public bool ChangeKey(ref byte[] oldKey, ref byte[] newKey) { byte[] refToInsertedValue = null; return(this.ChangeKey(ref oldKey, ref newKey, out refToInsertedValue)); } /// <summary> /// Takes value fresh no committed value row.GetFullValue(false); /// </summary> /// <param name="oldKey"></param> /// <param name="newKey"></param> /// <param name="refToInsertedValue">returns ptr in the file to the new key</param> /// <returns></returns> public bool ChangeKey(ref byte[] oldKey, ref byte[] newKey, out byte[] refToInsertedValue) { //The best way read old, remove, and create new, with holding of transactions, //just changing pointers to the value will give nothing, because in the value also the full key is written, so we will need //to make new value refToInsertedValue = null; var row = this.GetKey(oldKey, false); if (row.Exists) { byte[] oldKeyValue = row.GetFullValue(false); bool WasRemoved = false; byte[] deletedValue = null; this.RemoveKey(ref oldKey, out WasRemoved, false, out deletedValue); bool WasUpdated = false; refToInsertedValue = this.AddKey(ref newKey, ref oldKeyValue, out WasUpdated, false); refToInsertedValue = refToInsertedValue.EnlargeByteArray_BigEndian(8); return(true); } return(false); } /// <summary> /// Will return pointer to the value of the removing kid (if it existed). Otherwise NULL. /// </summary> /// <param name="key"></param> /// <param name="WasRemoved">indicates that value existed if true</param> /// <param name="retrieveDeletedValue">indicates if we should bind deleted value to the result</param> /// <param name="deletedValue">interesting only if WasRemoved = true and retrieveDeletedValue is true</param> /// <returns></returns> public void RemoveKey(ref byte[] key, out bool WasRemoved, bool retrieveDeletedValue, out byte[] deletedValue) { WasRemoved = false; deletedValue = null; //if (key == null || key.Length == 0) // return; if (key == null) { return; } if (key.Length > UInt16.MaxValue) { throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.KEY_IS_TOO_LONG); } LTrieGenerationNode gn = null; if (_generationMap.Count() == 0) { //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this); gn.Pointer = this.LinkToZeroNode; //gn.Value=0; - default _generationMap.Add(0, gn); gn.ReadSelf(false, null); } LTrieSetupKidResult res = new LTrieSetupKidResult(); //byte[] key1 = null; //we need it as null //byte[] val1 = null; //len can be expanded inside of the algorithm maximum by one int len = key.Length; bool cleanCheck = true; bool iterateFurther = false; /*SPECIAL CASE key=byte[0]*/ if (key.Length == 0) { _generationMap[0].RemoveKid((byte)0, true, ref key, out WasRemoved, retrieveDeletedValue, out deletedValue); return; } /***************************/ for (int i = 0; i < len; i++) { //Getting kid from actual generation map if (cleanCheck && i != 0 && _generationMap.ContainsKey(i) && _generationMap[i].Value != key[i - 1]) { cleanCheck = false; //In case if i>0, it's not the first element and we have to compare if there are generation mapsstarting from this point. //If generationMap[i] exists and it's value not that what we want, we have to clean full in memory generation map as //Save_node... up to i Save_GM_nodes_Starting_From(i); //Remove Gen Map starting from... i _generationMap.RemoveBiggerOrEqualThenKey(i); } if (!_generationMap.ContainsKey(i)) { //All ok, for the first generation node //We read or create generation map //And add it to the _generationMap gn = new LTrieGenerationNode(this); gn.Value = key[i - 1]; gn.Pointer = _generationMap[i - 1].KidsInNode.GetPointerToTheKid(key[i - 1]); //gn.Pointer = _generationMap[i - 1].GetKidPointer(key[i - 1]); _generationMap.Add(i, gn); if (gn.Pointer != null) { gn.ReadSelf(false, null); } else { gn.Pointer = new byte[DefaultPointerLen]; //!!!!!!!!!!!!! Check if it'S really necessary or we can leave it as null } } //Trying to remove as a result we receive information if we should iterate further iterateFurther = _generationMap[i].RemoveKid((i == key.Length) ? (byte)0 : key[i], (i == key.Length), ref key, out WasRemoved, retrieveDeletedValue, out deletedValue); if (!iterateFurther) { break; } else { if (i == (key.Length - 1)) { len++; } } } }
public void IterateForwardStartsWith_Prefix_Helper(byte[] initKey, bool useCache) { LTrieGenerationNode gn = null; initialKey = initKey; LTrieGenerationMap _generationMap = new LTrieGenerationMap(); //Loading it from Link TO ZERO Pointer gn = new LTrieGenerationNode(this._root); gn.Pointer = this._root.LinkToZeroNode; _generationMap.Add(0, gn); gn.ReadSelf(useCache, _generationMap.GenerateMapNodesValuesUpToIndex(0)); 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(System.Text.Encoding.ASCII.GetString(new byte[] {initKey[0]})); //Kid can be value link or node link //if value link we can count 1 up if (kd.ValueKid || !kd.LinkToNode) { PrefixDeep++; //key = this._root.Tree.Cache.ReadKey(useCache, kd.Ptr); //if (key[0] == initialKey[0]) // lstClosestPrefix.Add(initialKey[0]); } 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); PrefixDeep++; foreach (var xr in ItFrwStartsWith_Prefix_Helper(gn1, gml, 1, useCache)) { //we must iterate to fill lstClosestPrefix } } } }
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); }
private IEnumerable<LTrieRow> ItFrwStartsWith_Prefix_Helper(LTrieGenerationNode gn, byte[] generationMapLine, int deep, bool useCache) { byte[] key = null; LTrieRow row = null; byte[] gml = null; foreach (var kd in gn.KidsInNode.GetKidsForward()) { //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)) { //DOING NOTHING //////we are bigger then supplied key for search (initialKey) ////if (kd.ValueKid || !kd.LinkToNode) ////{ //// //visualize all possible //// 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 ////{ //// //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 ItFrwStartsWith_Prefix_Helper(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) { PrefixDeep++; ////visualize //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 { PrefixDeep++; ////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 ItFrwStartsWith_Prefix_Helper(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) { PrefixDeep++; ////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 { PrefixDeep++; //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 ItFrwStartsWith_Prefix_Helper(gn1, gml, deep + 1, useCache)) { yield return xr; } } } } else { //do nothing } } } }