예제 #1
0
        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);
        }
예제 #2
0
        /// <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;
                    }
                }
            }
        }
예제 #3
0
파일: RecordStorage.cs 프로젝트: gmich/Gem
        //
        // 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);
                    }
                }
            }
        }