public void CommitDropIndex(int indexNum)
        {
            lock (this) {
                // The IndexBlock we are dropping
                var curIndexBlock = indexBlocks[indexNum];
                int blockSize     = curIndexBlock.BlockSize;

                try {
                    Store.Lock();

                    // Add all the elements to the deleted areas in the block
                    var allBlockPointers = curIndexBlock.GetBlockPointers();

                    foreach (long area in allBlockPointers)
                    {
                        curIndexBlock.AddDeletedArea(area);
                    }

                    // Mark the current block as deleted
                    curIndexBlock.MarkAsDeleted();

                    // Make up a new blank block list for this index set.
                    long blockP = CreateNewBlock();

                    // Now create a new IndexBlock object
                    var newIndexBlock = new IndexBlock(this, indexNum, blockSize, blockP);

                    // Add reference to the new one
                    newIndexBlock.AddReference();

                    // Remove reference to the old
                    curIndexBlock.RemoveReference();

                    // Update the index_blocks list
                    indexBlocks[indexNum] = newIndexBlock;

                    // Commit the new index header (index_blocks)
                    CommitIndexHeader();
                } finally {
                    Store.Unlock();
                }
            }
        }
        public void CommitIndexSet(IRowIndexSet indexSet)
        {
            var removedBlocks = new List <IndexBlock>();

            lock (this) {
                var sIndexSet = (SnapshotIndexSet)indexSet;

                try {
                    try {
                        Store.Lock();

                        // For each Index in the index set,
                        foreach (Index index in sIndexSet)
                        {
                            int indexNum = index.IndexNumber;

                            // The IndexBlock we are changing
                            var curIndexBlock = indexBlocks[indexNum];

                            // Get all the blocks in the list
                            var blocks = index.AllBlocks.ToList();

                            // Make up a new block list for this index set.
                            long blockP;

                            using (var area = Store.CreateArea(16 + (blocks.Count * 28))) {
                                blockP = area.Id;
                                area.Write(1);                                 // version
                                area.Write(0);                                 // reserved
                                area.Write((long)blocks.Count);                // block count

                                foreach (var block in blocks)
                                {
                                    var mappedBlock = (IMappedBlock)block;

                                    long bottomInt = 0;
                                    long topInt    = 0;
                                    var  blockSize = mappedBlock.Count;

                                    if (blockSize > 0)
                                    {
                                        bottomInt = mappedBlock.Bottom;
                                        topInt    = mappedBlock.Top;
                                    }

                                    long blockPointer = mappedBlock.BlockPointer;

                                    // Is the block new or was it changed?
                                    if (blockPointer == -1 || mappedBlock.HasChanged)
                                    {
                                        // If this isn't -1 then write this sector on the list of
                                        // sectors to delete during GC.
                                        if (blockPointer != -1)
                                        {
                                            curIndexBlock.AddDeletedArea(blockPointer);
                                        }

                                        // This is a new block or a block that's been changed
                                        // Write the block to the file system
                                        blockPointer = mappedBlock.Flush();
                                    }

                                    area.Write(bottomInt);
                                    area.Write(topInt);
                                    area.Write(blockPointer);
                                    area.Write((int)(blockSize | ((mappedBlock.CompactType) << 24)));
                                }

                                // Finish initializing the area
                                area.Flush();
                            }

                            // Add the deleted blocks
                            var deletedBlocks = index.DeletedBlocks.ToArray();

                            for (int i = 0; i < deletedBlocks.Length; ++i)
                            {
                                long delBlockP = deletedBlocks[i].BlockPointer;
                                if (delBlockP != -1)
                                {
                                    curIndexBlock.AddDeletedArea(delBlockP);
                                }
                            }

                            // Mark the current block as deleted
                            curIndexBlock.MarkAsDeleted();

                            // Now create a new IndexBlock object
                            var newIndexBlock = new IndexBlock(this, indexNum, curIndexBlock.BlockSize, blockP);
                            newIndexBlock.Parent = curIndexBlock;

                            // Add reference to the new one
                            newIndexBlock.AddReference();

                            // Update the index_blocks list
                            indexBlocks[indexNum] = newIndexBlock;

                            // We remove this later.
                            removedBlocks.Add(curIndexBlock);
                        }

                        // Commit the new index header (index_blocks)
                        CommitIndexHeader();
                    } finally {
                        Store.Unlock();
                    }

                    // Commit finished.
                } catch (IOException e) {
                    throw new InvalidOperationException("Error while committing index changed", e);
                }
            }

            // Remove all the references for the changed blocks,
            foreach (var block in removedBlocks)
            {
                block.RemoveReference();
            }
        }
        internal void PrepareIndexes(int count, int type, int blockSize)
        {
            lock (this) {
                try {
                    Store.Lock();

                    // Allocate a new area for the list
                    int newSize = 16 + ((indexBlocks.Length + count) * 16);

                    using (var newIndexArea = Store.CreateArea(newSize)) {
                        long newIndexPointer = newIndexArea.Id;
                        var  newIndexBlocks  = new IndexBlock[(indexBlocks.Length + count)];

                        // Copy the existing area
                        indexHeaderArea.Position = 0;
                        int  version  = indexHeaderArea.ReadInt32();
                        int  reserved = indexHeaderArea.ReadInt32();
                        long icount   = indexHeaderArea.ReadInt64();
                        newIndexArea.Write(version);
                        newIndexArea.Write(reserved);
                        newIndexArea.Write(icount + count);

                        for (int i = 0; i < indexBlocks.Length; ++i)
                        {
                            int  itype       = indexHeaderArea.ReadInt32();
                            int  iblockSize  = indexHeaderArea.ReadInt32();
                            long indexBlockP = indexHeaderArea.ReadInt64();

                            newIndexArea.Write(itype);
                            newIndexArea.Write(iblockSize);
                            newIndexArea.Write(indexBlockP);

                            newIndexBlocks[i] = indexBlocks[i];
                        }

                        // Add the new entries
                        for (int i = 0; i < count; ++i)
                        {
                            long newBlankBlockP = CreateNewBlock();

                            newIndexArea.Write(type);
                            newIndexArea.Write(blockSize);
                            newIndexArea.Write(newBlankBlockP);

                            var newBlock = new IndexBlock(this, indexBlocks.Length + i, blockSize, newBlankBlockP);
                            newBlock.AddReference();
                            newIndexBlocks[indexBlocks.Length + i] = newBlock;
                        }

                        // Finished initializing the index.
                        newIndexArea.Flush();

                        // The old index header pointer
                        long oldIndexHeaderP = indexHeaderPointer;

                        // Update the state of this object,
                        indexHeaderPointer = newIndexPointer;
                        indexHeaderArea    = Store.GetArea(newIndexPointer);
                        indexBlocks        = newIndexBlocks;

                        // Update the start pointer
                        startArea.Position = 8;
                        startArea.Write(newIndexPointer);
                        startArea.Flush();

                        // Free the old header
                        Store.DeleteArea(oldIndexHeaderP);
                    }
                } finally {
                    Store.Unlock();
                }
            }
        }