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); }
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); }
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); }