/// <summary> /// Insert BsonDocument into new data pages /// </summary> public PageAddress Insert(BsonDocument doc) { var bytesLeft = doc.GetBytesCount(true); if (bytesLeft > MAX_DOCUMENT_SIZE) { throw new LiteException(0, "Document size exceed {0} limit", MAX_DOCUMENT_SIZE); } var firstBlock = PageAddress.Empty; IEnumerable <BufferSlice> source() { var blockIndex = 0; DataBlock lastBlock = null; while (bytesLeft > 0) { var bytesToCopy = Math.Min(bytesLeft, MAX_DATA_BYTES_PER_PAGE); var dataPage = _snapshot.GetFreePage <DataPage>(bytesToCopy + DataBlock.DATA_BLOCK_FIXED_SIZE); var dataBlock = dataPage.InsertBlock(bytesToCopy, blockIndex++ > 0); if (lastBlock != null) { lastBlock.SetNextBlock(dataBlock.Position); } if (firstBlock.IsEmpty) { firstBlock = dataBlock.Position; } yield return(dataBlock.Buffer); lastBlock = dataBlock; bytesLeft -= bytesToCopy; } } // consume all source bytes to write BsonDocument direct into PageBuffer // must be fastest as possible using (var w = new BufferWriter(source())) { // already bytes count calculate at method start w.WriteDocument(doc, false); w.Consume(); } return(firstBlock); }
/// <summary> /// Create a new index and returns head page address (skip list) /// </summary> public CollectionIndex CreateIndex(string name, string expr, bool unique) { // get how many butes needed fore each head/tail (both has same size) var bytesLength = IndexNode.GetNodeLength(MAX_LEVEL_LENGTH, BsonValue.MinValue, out var keyLength); // get a free index page for head note (x2 for head + tail) var indexPage = _snapshot.GetFreePage <IndexPage>(bytesLength * 2); // create index ref var index = _snapshot.CollectionPage.InsertCollectionIndex(name, expr, unique); // insert head/tail nodes var head = indexPage.InsertIndexNode(index.Slot, MAX_LEVEL_LENGTH, BsonValue.MinValue, PageAddress.Empty, bytesLength); var tail = indexPage.InsertIndexNode(index.Slot, MAX_LEVEL_LENGTH, BsonValue.MaxValue, PageAddress.Empty, bytesLength); // link head-to-tail with double link list in first level head.SetNext(0, tail.Position); tail.SetPrev(0, head.Position); index.Head = head.Position; index.Tail = tail.Position; return(index); }