private IRecord GetRecord(long recordId) { var record = new Record(recordId); try { var currentBlockId = record.Id; do { var block = _blockStorage.Find(currentBlockId); if (block == null) { if (currentBlockId == RecordZero) { block = _blockStorage.Create(); return(RecordZero.WithBlocks(new[] { block })); } else { throw new Exception("Block not found by id: " + currentBlockId); } } if (block.IsDeleted) { throw new InvalidDataException("Block not found: " + currentBlockId); } record.Blocks.Add(block); currentBlockId = block.GetHeaderValue(BlockHeader.NextBlock); } while (currentBlockId != 0); } catch (Exception) { record.Dispose(); throw; } return(record); }
/// <summary> /// Deletes the record of specified id. /// </summary> public void Delete(uint recordId) { using (IBlock block = blockStorage.Find(recordId)) { IBlock curBlock = block; while (true) { IBlock nextBlock = null; using (curBlock) { // Instead of actually "deleting" the block, we simply flag it deleted for reuse. uint nextId = 0; MarkAsReusable(curBlock, out nextId); curBlock.SetHeader(BlockFields.IsDeleted, 1L); // If curBlock doesn't have a reference to the next block, just break out if (nextId == 0) { break; } // If there is a next block's id else { nextBlock = blockStorage.Find(nextId); if (nextBlock == null) { throw new InvalidDataException("Block not found with id: " + nextId); } } } // Move to next block if (nextBlock != null) { curBlock = nextBlock; } } } }
// // Public Methods // public virtual byte[] Find(uint recordId) { // First grab the block using (var block = storage.Find(recordId)) { if (block == null) { return(null); } // If this is a deleted block then ignore it if (1L == block.GetHeader(kIsDeleted)) { return(null); } // If this block is a child block then also ignore it if (0L != block.GetHeader(kPreviousBlockId)) { return(null); } // Grab total record size and allocate coressponded memory var totalRecordSize = block.GetHeader(kRecordLength); if (totalRecordSize > MaxRecordSize) { throw new NotSupportedException("Unexpected record length: " + totalRecordSize); } var data = new byte[totalRecordSize]; var bytesRead = 0; // Now start filling data IBlock currentBlock = block; while (true) { uint nextBlockId; using (currentBlock) { var thisBlockContentLength = currentBlock.GetHeader(kBlockContentLength); if (thisBlockContentLength > storage.BlockContentSize) { throw new InvalidDataException("Unexpected block content length: " + thisBlockContentLength); } // Read all available content of current block currentBlock.Read(dst: data, dstOffset: bytesRead, srcOffset: 0, count: (int)thisBlockContentLength); // Update number of bytes read bytesRead += (int)thisBlockContentLength; // Move to the next block if there is any nextBlockId = (uint)currentBlock.GetHeader(kNextBlockId); if (nextBlockId == 0) { return(data); } } // Using currentBlock currentBlock = this.storage.Find(nextBlockId); if (currentBlock == null) { throw new InvalidDataException("Block not found by id: " + nextBlockId); } } } }