예제 #1
0
        /// <summary>
        /// Implements insert documents in a collection - use a buffer to commit transaction in each buffer count
        /// </summary>
        public int Insert(string colName, IEnumerable <BsonDocument> docs)
        {
            return(this.Transaction <int>(colName, true, (col) =>
            {
                var count = 0;

                foreach (var doc in docs)
                {
                    BsonValue id;

                    // if no _id, add one as ObjectId
                    if (!doc.RawValue.TryGetValue("_id", out id))
                    {
                        doc["_id"] = id = ObjectId.NewObjectId();
                    }

                    // test if _id is a valid type
                    if (id.IsNull || id.IsMinValue || id.IsMaxValue)
                    {
                        throw LiteException.InvalidDataType("_id", id);
                    }

                    _log.Write(Logger.COMMAND, "insert document on '{0}' :: _id = {1}", col.CollectionName, id);

                    // serialize object
                    var bytes = BsonSerializer.Serialize(doc);

                    // storage in data pages - returns dataBlock address
                    var dataBlock = _data.Insert(col, bytes);

                    // store id in a PK index [0 array]
                    var pk = _indexer.AddNode(col.PK, id);

                    // do links between index <-> data block
                    pk.DataBlock = dataBlock.Position;
                    dataBlock.IndexRef[0] = pk.Position;

                    // for each index, insert new IndexNode
                    foreach (var index in col.GetIndexes(false))
                    {
                        var key = doc.Get(index.Field);

                        var node = _indexer.AddNode(index, key);

                        // point my index to data object
                        node.DataBlock = dataBlock.Position;

                        // point my dataBlock
                        dataBlock.IndexRef[index.Slot] = node.Position;
                    }

                    _cache.CheckPoint();

                    count++;
                }

                return count;
            }));
        }
예제 #2
0
        /// <summary>
        /// Implement update command to a document inside a collection
        /// </summary>
        public int Update(string colName, IEnumerable <BsonDocument> docs)
        {
            return(this.Transaction <int>(colName, false, (col) =>
            {
                // no collection, no updates
                if (col == null)
                {
                    return 0;
                }

                var count = 0;

                foreach (var doc in docs)
                {
                    // normalize id before find
                    var id = doc["_id"].Normalize(col.PK.Options);

                    // validate id for null, min/max values
                    if (id.IsNull || id.IsMinValue || id.IsMaxValue)
                    {
                        throw LiteException.InvalidDataType("_id", id);
                    }

                    _log.Write(Logger.COMMAND, "update document on '{0}' :: _id = ", colName, id);

                    // find indexNode from pk index
                    var indexNode = _indexer.Find(col.PK, id, false, Query.Ascending);

                    // if not found document, no updates
                    if (indexNode == null)
                    {
                        continue;
                    }

                    // serialize document in bytes
                    var bytes = BsonSerializer.Serialize(doc);

                    // update data storage
                    var dataBlock = _data.Update(col, indexNode.DataBlock, bytes);

                    // delete/insert indexes - do not touch on PK
                    foreach (var index in col.GetIndexes(false))
                    {
                        var key = doc.Get(index.Field);

                        var node = _indexer.GetNode(dataBlock.IndexRef[index.Slot]);

                        // check if my index node was changed
                        if (node.Key.CompareTo(key) != 0)
                        {
                            // remove old index node
                            _indexer.Delete(index, node.Position);

                            // and add a new one
                            var newNode = _indexer.AddNode(index, key);

                            // point my index to data object
                            newNode.DataBlock = dataBlock.Position;

                            // set my block page as dirty before change
                            _pager.SetDirty(dataBlock.Page);

                            // point my dataBlock
                            dataBlock.IndexRef[index.Slot] = newNode.Position;
                        }
                    }

                    _cache.CheckPoint();

                    count++;
                }

                return count;
            }));
        }