예제 #1
0
        //#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);
        }
예제 #2
0
        //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;
            }
        }