//#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); }
//object lock_nestedTblAccess = new object(); /// <summary> /// /// </summary> /// <param name="row"></param> /// <param name="tableIndex"></param> /// <param name="masterTrie"></param> /// <param name="insertTable">Regulates if InsertTable or SelectTable was called (ability to create table if it doesn't exist)</param> /// <param name="useCache">Regulates READ table thread or WRITE table thread - visibilityscope</param> /// <returns></returns> public NestedTable GetTable(LTrieRow row, ref byte[] btKey, uint tableIndex, LTrie masterTrie, bool insertTable, bool useCache) { //Console.WriteLine(useCache.ToString() + " " + System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()); try { if (!insertTable && !row.Exists) { //For Readers, which couldn't allocate table, we return empty DbInTable return new NestedTable(null, false, false); } if (insertTable) { //settign up modification thread this.NestedTablesCoordinator.ModificationThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId; } if (masterTrie == null) masterTrie = this; NestedTableInternal dit = null; //this one we will return byte[] fullValuePointer = null; if (insertTable) TableIsModified = true; //flag will permit commit and rollback byte[] val = null; long Id_RootStart = 0; if (row.Exists) { val = row.GetPartialValue(tableIndex * this.Storage.TrieSettings.ROOT_SIZE, this.Storage.TrieSettings.ROOT_SIZE, useCache); if (val == null || val.Length < this.Storage.TrieSettings.ROOT_SIZE) { //For Readers, which couldn't allocate table, we return empty DbInTable if (!insertTable) { return new NestedTable(null, false, false); } //Here can appear only WRITERS, which couldn't allocate table byte[] btValue = new byte[this.Storage.TrieSettings.ROOT_SIZE]; long valueStartPointer = 0; fullValuePointer = this.AddPartially(ref btKey, ref btValue, tableIndex * this.Storage.TrieSettings.ROOT_SIZE, out valueStartPointer); Id_RootStart = valueStartPointer + (tableIndex * this.Storage.TrieSettings.ROOT_SIZE); lock (this.NestedTablesCoordinator.lock_nestedTblAccess) { dit = new DataTypes.NestedTableInternal(true, masterTrie, Id_RootStart, (tableIndex * this.Storage.TrieSettings.ROOT_SIZE), false,this,ref btKey); this.NestedTablesCoordinator.AddNestedTable(ref btKey, fullValuePointer.DynamicLength_To_UInt64_BigEndian(), Id_RootStart, dit); //if (!insertTable) //{ //If we open the table for read, we increase read value dit.quantityOpenReads++; //} } } else { //then we must open/create DbInTable Id_RootStart = row.ValueStartPointer + (tableIndex * this.Storage.TrieSettings.ROOT_SIZE); fullValuePointer = row.LinkToValue; lock (this.NestedTablesCoordinator.lock_nestedTblAccess) { dit = this.NestedTablesCoordinator.GetTable(ref btKey, Id_RootStart); if (dit == null) { dit = new DataTypes.NestedTableInternal(true, masterTrie, Id_RootStart, (tableIndex * this.Storage.TrieSettings.ROOT_SIZE), useCache, this, ref btKey); this.NestedTablesCoordinator.AddNestedTable(ref btKey, fullValuePointer.DynamicLength_To_UInt64_BigEndian(), Id_RootStart, dit); } //if (!insertTable) //{ //If we open the table for read, we increase read value dit.quantityOpenReads++; //} } } } else { //Every new row with DbInTable starts from here //Here can appear only WRITERS, which couldn't allocate table //creating space for the root byte[] btValue = new byte[this.Storage.TrieSettings.ROOT_SIZE]; //adding empty root to the place long valueStartPointer = 0; fullValuePointer = this.AddPartially(ref btKey, ref btValue, tableIndex * this.Storage.TrieSettings.ROOT_SIZE, out valueStartPointer); Id_RootStart = valueStartPointer + (tableIndex * this.Storage.TrieSettings.ROOT_SIZE); lock (this.NestedTablesCoordinator.lock_nestedTblAccess) { dit = new DataTypes.NestedTableInternal(true, masterTrie, Id_RootStart, (tableIndex * this.Storage.TrieSettings.ROOT_SIZE), false, this, ref btKey); this.NestedTablesCoordinator.AddNestedTable(ref btKey, fullValuePointer.DynamicLength_To_UInt64_BigEndian(), Id_RootStart, dit); //if (!insertTable) //{ //If we open the table for read, we increase read value dit.quantityOpenReads++; //} } } //Console.WriteLine("Creating NestedTable " + btKey.ToBytesString("")); //this.NestedTablesCoordinator.AddNestedTable(ref btKey, fullValuePointer.DynamicLength_To_UInt64_BigEndian(), Id_RootStart, dit); return new NestedTable(dit, insertTable, true); } catch (Exception ex) { this.RollBack(); //Cascade throw ex; } }