示例#1
0
        public bool Add(T record, out int index)
        {
            _workingBlock = new Block <T>(MaxRecords);
            if (_partiallyFullBlocks.Count > 0)
            {
                index = _partiallyFullBlocks.Min(i => i);
                _workingBlock.FromByteArray((_file.ReadData(index)));
                if (_workingBlock.AddRecord(record))
                {
                    if (_workingBlock.ValidCount == MaxRecords)
                    {
                        _partiallyFullBlocks.Remove(index);
                    }
                    _file.WriteData(index, _workingBlock.ToByteArray());
                    return(true);
                }
            }
            else if (_freeBlocks.Count > 0)
            {
                index = _freeBlocks.Min(i => i);
                _workingBlock.FromByteArray((_file.ReadData(index)));
                if (_workingBlock.AddRecord(record))
                {
                    _freeBlocks.Remove(index);
                    _partiallyFullBlocks.Add(index);
                    _file.WriteData(index, _workingBlock.ToByteArray());
                    return(true);
                }
            }
            else
            {
                if (_workingBlock.AddRecord(record))
                {
                    index = _file.WriteData(_workingBlock.ToByteArray());
                    if (_workingBlock.ValidCount < MaxRecords)
                    {
                        _partiallyFullBlocks.Add(index);
                    }
                    return(true);
                }
            }

            index = -1;
            return(false);
        }
示例#2
0
        private bool AddOverflow(ExternalTrieNode node, T record, Block <T> workingBlock = null)
        {
            if (workingBlock == null)
            {
                if (node.IndexOfBlock == -1)
                {
                    throw new Exception($"This should not happened, index of block: {node.IndexOfBlock} and should not be");
                }
                if (node.RecordCount < MaxRecords)
                {
                    throw new Exception($"This should not happened nodeRecords vs maxRecords {node.RecordCount} < {MaxRecords}");
                }

                //nacitaj podla indexu blok,
                //skus vlozit do bloku
                //ak nie
                //kym ma blok adresu na dalsieho, nacitavaj do listu
                //postupne nacitavaj blok kym sa nenajde taky kde sa zaznam zmesti
                //ak sa nikde nezmesti, vytvor novy pozri free bloky inak na koniec
                //record count ++
                _workingBlock1 = new Block <T>(MaxRecords);
                _workingBlock1.FromByteArray(_blockFile.ReadData(node.IndexOfBlock));
                if (_workingBlock1.TryFindRecord(record, out var data)) //ak tam uz existuje
                {
                    return(false);
                }

                if (_workingBlock1.NextOverflowBlockIndex == -1) //ak zatial nebol preplneny
                {
                    if (_workingBlock1.AddRecord(record))        //ak ho pridame do povodneho tak len zapiseme a koniec, netreba kontrolu lebo nema preplnovacie, i ked myslim ze to ani nenastane
                    {
                        node.RecordCount++;
                        _blockFile.WriteData(node.IndexOfBlock, _workingBlock1.ToByteArray());
                        return(true);
                    }

                    _overflowBlock = new Block <T>(MaxRecordsInOverflow);
                    _overflowBlock.AddRecord(record);
                    node.RecordCount++;

                    if (_freeBlocksOverflow.Count == 0)
                    {
                        var index = _freeBlocksOverflow.Min(i => i);
                        _freeBlocksOverflow.Remove(index);
                        _overflowFile.WriteData(index, _overflowBlock.ToByteArray()); //zapisem preplneny a nastavim index
                        _workingBlock1.NextOverflowBlockIndex = index;
                    }
                    else
                    {
                        _workingBlock1.NextOverflowBlockIndex = _overflowFile.WriteData(_overflowBlock.ToByteArray());
                    }
                }
                else //ak uz bol preplneny
                {
                    var listOverflowBlocks = new List <Block <T> >();
                    var index = _workingBlock1.NextOverflowBlockIndex;
                    while (index != -1)
                    {
                        listOverflowBlocks.Add(new Block <T>(MaxRecordsInOverflow));
                        listOverflowBlocks[listOverflowBlocks.Count - 1].FromByteArray(_overflowFile.ReadData(index));
                        index = listOverflowBlocks[listOverflowBlocks.Count - 1].NextOverflowBlockIndex;
                    }

                    //to ci uz existuje v normalnom bloku sa overilo hore
                    foreach (var ofBlock in listOverflowBlocks) //overit ci niekde uz nie je v preplnovacke
                    {
                        if (ofBlock.TryFindRecord(record, out var dataRec))
                        {
                            return(false); //v nejakom z nich uz existuje
                        }
                    }

                    if (node.RecordCount - MaxRecords < listOverflowBlocks.Count * MaxRecordsInOverflow) //niekde sa zmestia
                    {
                        if (!_workingBlock1.AddRecord(record))                                           //ak sa nezmesti do normalneho skus do ostatnych
                        {
                            foreach (var ofBlock in listOverflowBlocks)                                  //prechadzat a naplnat
                            {
                                if (ofBlock.AddRecord(record))
                                {
                                    break;
                                }
                            }
                        }
                    }
                    else //nikde sa nezmestia - vytvorit novy
                    {
                        _overflowBlock = new Block <T>(MaxRecordsInOverflow);
                        _overflowBlock.AddRecord(record);
                        if (_freeBlocksOverflow.Count > 0)
                        {
                            index = _freeBlocksOverflow.Min(i => i);
                            _freeBlocksOverflow.Remove(index);
                            _overflowFile.WriteData(index, _overflowBlock.ToByteArray());
                        }
                        else
                        {
                            index = _overflowFile.WriteData(_overflowBlock.ToByteArray());
                        }
                        if (listOverflowBlocks[listOverflowBlocks.Count - 1].NextOverflowBlockIndex != -1)
                        {
                            throw new Exception($"This should not happened, index of block: {node.IndexOfBlock} and should be -1");
                        }
                        listOverflowBlocks[listOverflowBlocks.Count - 1].NextOverflowBlockIndex = index;
                    }
                    node.RecordCount++;

                    for (int i = listOverflowBlocks.Count - 1; i > 0; i--)
                    {
                        _overflowFile.WriteData(listOverflowBlocks[i - 1].NextOverflowBlockIndex,
                                                listOverflowBlocks[i].ToByteArray()); //kazdeho zapisem podla indexu predchadzajuceho (az na prveho)
                    }

                    _overflowFile.WriteData(_workingBlock1.NextOverflowBlockIndex, listOverflowBlocks[0].ToByteArray());
                }
                _blockFile.WriteData(node.IndexOfBlock, _workingBlock1.ToByteArray()); //zapisem povodny blok
            }
            else
            {
                if (node.IndexOfBlock != -1)
                {
                    throw new Exception($"This should not happened, index of block: {node.IndexOfBlock} and should be -1");
                }
                //zapis nodu novy working blok a daj mu adresu na prvy preplnovak kde pojde record
                //record count ++;

                if (workingBlock.TryFindRecord(record, out var dataRec))
                {
                    throw new Exception($"This should not happened, block already contains record");
                }

                _overflowBlock = new Block <T>(MaxRecordsInOverflow);
                _overflowBlock.AddRecord(record);
                var index = -1;
                if (_freeBlocksOverflow.Count > 0)
                {
                    index = _freeBlocksOverflow.Min(i => i);
                    _freeBlocksOverflow.Remove(index);
                    _overflowFile.WriteData(index, _overflowBlock.ToByteArray());
                }
                else
                {
                    index = _overflowFile.WriteData(_overflowBlock.ToByteArray());
                }
                if (index == -1)
                {
                    throw new Exception($"This should not happened, index of block: {node.IndexOfBlock} and should NOT be -1");
                }
                workingBlock.NextOverflowBlockIndex = index;
                node.IndexOfBlock = WriteNewBlockAndGetIndex(workingBlock);
                node.RecordCount++;
            }

            return(true);
        }
示例#3
0
        public bool Add(T record)
        {
            _currentDepth = 0;
            bool result = false;
            var  node   = FindExternalNode(record.GetHashCode());

            if (node.IndexOfBlock == -1)
            {
                _workingBlock1 = new Block <T>(MaxRecords);
                result         = _workingBlock1.AddRecord(record);
                if (result)
                {
                    node.RecordCount++;
                    node.IndexOfBlock = WriteNewBlockAndGetIndex(_workingBlock1);
                }
            }
            else if (node.RecordCount < MaxRecords)
            {
                _workingBlock1 = new Block <T>(MaxRecords);
                _workingBlock1.FromByteArray(_blockFile.ReadData(node.IndexOfBlock));

                result = _workingBlock1.AddRecord(record);
                if (result)
                {
                    node.RecordCount++;
                    _blockFile.WriteData(node.IndexOfBlock, _workingBlock1.ToByteArray());
                }
            }
            else if (node.RecordCount > MaxRecords)
            {
                return(AddOverflow(node, record));
            }
            else if (node.RecordCount == MaxRecords)
            {
                if (_currentDepth == HashBitSize) //ak sme na konci
                {
                    return(AddOverflow(node, record));
                }
                else
                {
                    var replaceNode = node;
                    _workingBlock1 = new Block <T>(MaxRecords);
                    _workingBlock1.FromByteArray(_blockFile.ReadData(replaceNode.IndexOfBlock));
                    _freeBlocks.Add(replaceNode.IndexOfBlock); //blok sa rozdeli, ale ulozim jeho index
                    var workingRecord = record;
                    while (replaceNode?.RecordCount == MaxRecords)
                    {
                        if (_currentDepth == HashBitSize) //ak uz dalej nemozme delit
                        {
                            return(AddOverflow(replaceNode, workingRecord, _workingBlock1));
                        }

                        var newInternal = TransformExternal(replaceNode);
                        _leftWorkingBlock  = new Block <T>(MaxRecords);
                        _rightWorkingBlock = new Block <T>(MaxRecords);
                        var leftExternal  = newInternal.LeftChild as ExternalTrieNode;
                        var rightExternal = newInternal.RightChild as ExternalTrieNode;

                        result = PutRecordInCorrectBlock(leftExternal, rightExternal, workingRecord); //najskor pridat

                        foreach (var rec in _workingBlock1.GetAllRecords())                           //najskor prerozdelit
                        {
                            workingRecord = rec;
                            PutRecordInCorrectBlock(leftExternal, rightExternal, rec); //uz raz boli pridane, netreba overovat
                        }

                        if (leftExternal?.RecordCount == 0)
                        {
                            replaceNode    = rightExternal;
                            _workingBlock1 = _rightWorkingBlock;
                        }
                        else if (rightExternal?.RecordCount == 0)
                        {
                            replaceNode    = leftExternal;
                            _workingBlock1 = _leftWorkingBlock;
                        }
                        else
                        {
                            if (leftExternal != null)
                            {
                                leftExternal.IndexOfBlock = WriteNewBlockAndGetIndex(_leftWorkingBlock);
                            }
                            if (rightExternal != null)
                            {
                                rightExternal.IndexOfBlock = WriteNewBlockAndGetIndex(_rightWorkingBlock);
                            }
                            break;
                        }
                        _currentDepth++;
                    }
                    AdjustFile();
                }
            }

            return(result);
        }