コード例 #1
0
ファイル: LTrieGenerationMap.cs プロジェクト: hhblaze/DBreeze
        public void Add(int key, LTrieGenerationNode value)
        {
            if (key != size)
                throw new Exception("LTrieAsciiGenerationMap Generation Map error Add Index");

            ReGenerateMapUpToIndex = true;

            if((_d.Length-1) < key)
            {
                Array.Resize(ref _d, key*2);
            }

            _d[key] = value;

            //LTrieGenerationNode node = null;
            //_d.TryGetValue(key, out node);
            //if (node == null)
            //    _d.Add(key, value);
            //else
            //    _d[key] = value;

            //Place is ok!
            size++;
        }
コード例 #2
0
ファイル: LTrieRootNode.cs プロジェクト: NotYours180/DBreeze
        /// <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++;
                }
            }
        }
コード例 #3
0
ファイル: LTrieRootNode.cs プロジェクト: NotYours180/DBreeze
        /// <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>
        /// 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;
        }

        public void Commit()
        {
            try
            {

                this.Save_GM_nodes_Starting_From(0);

                byte[] oldRoot = me;

                me = this.SerializeRootNode();

                //Synchronized inside
                //DBreeze.Diagnostic.SpeedStatistic.StartCounter("Commit");
                //this.Tree.Cache.Commit(this.EmptyPointer, ref me, ref oldRoot);
                this.Tree.Cache.Commit(ref me, ref oldRoot);
                //DBreeze.Diagnostic.SpeedStatistic.StopCounter("Commit");

            }
            catch (Exception ex)
            {
                ////rollbak will be done on the level of the tree

                ////////////////////////////////////////
                throw DBreezeException.Throw(DBreezeException.eDBreezeExceptions.COMMIT_FAILED, this.Tree.TableName, ex);
            }
        }

        /// <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;
        }
コード例 #4
0
ファイル: LTrieRootNode.cs プロジェクト: NotYours180/DBreeze
        /// <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);
                }

            }
        }