Exemplo n.º 1
0
        public void Set(string name, string key, RavenJObject data, UuidType uuidType)
        {
            Api.JetSetCurrentIndex(session, Lists, "by_name_and_key");
            Api.MakeKey(session, Lists, name, Encoding.Unicode, MakeKeyGrbit.NewKey);
            Api.MakeKey(session, Lists, key, Encoding.Unicode, MakeKeyGrbit.None);

            var exists = Api.TrySeek(session, Lists, SeekGrbit.SeekEQ);


            using (var update = new Update(session, Lists, exists ? JET_prep.Replace : JET_prep.Insert))
            {
                Api.SetColumn(session, Lists, tableColumnsCache.ListsColumns["name"], name, Encoding.Unicode);
                Api.SetColumn(session, Lists, tableColumnsCache.ListsColumns["key"], key, Encoding.Unicode);
                Api.SetColumn(session, Lists, tableColumnsCache.ListsColumns["etag"], uuidGenerator.CreateSequentialUuid(uuidType).TransformToValueForEsentSorting());
                using (var columnStream = new ColumnStream(session, Lists, tableColumnsCache.ListsColumns["data"]))
                {
                    if (exists)
                    {
                        columnStream.SetLength(0);
                    }
                    using (Stream stream = new BufferedStream(columnStream))
                    {
                        data.WriteTo(stream);
                        stream.Flush();
                    }
                }
                update.Save();
            }
        }
Exemplo n.º 2
0
		public Etag AddAttachment(string key, Etag etag, Stream data, RavenJObject headers)
		{
			Api.JetSetCurrentIndex(session, Files, "by_name");
			Api.MakeKey(session, Files, key, Encoding.Unicode, MakeKeyGrbit.NewKey);
			var isUpdate = Api.TrySeek(session, Files, SeekGrbit.SeekEQ);
			if (isUpdate)
			{
				var existingEtag = Etag.Parse(Api.RetrieveColumn(session, Files, tableColumnsCache.FilesColumns["etag"]));
				if (existingEtag != etag && etag != null)
				{
					throw new ConcurrencyException("PUT attempted on attachment '" + key +
						"' using a non current etag")
					{
						ActualETag = existingEtag,
						ExpectedETag = etag
					};
				}
			}
			else
			{
				if (data == null)
					throw new InvalidOperationException("When adding new attachment, the attachment data must be specified");

				if (Api.TryMoveFirst(session, Details))
					Api.EscrowUpdate(session, Details, tableColumnsCache.DetailsColumns["attachment_count"], 1);
			}

			Etag newETag = uuidGenerator.CreateSequentialUuid(UuidType.Attachments);
			using (var update = new Update(session, Files, isUpdate ? JET_prep.Replace : JET_prep.Insert))
			{
				Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["name"], key, Encoding.Unicode);
				if (data != null)
				{
					long written;
					using (var columnStream = new ColumnStream(session, Files, tableColumnsCache.FilesColumns["data"]))
					{
						if (isUpdate)
							columnStream.SetLength(0);
						using (var stream = new BufferedStream(columnStream))
						{
							data.CopyTo(stream);
							written = stream.Position;
							stream.Flush();
						}
					}
					if (written == 0) // empty attachment
					{
						Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["data"], new byte[0]);
					}
				}

				Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["etag"], newETag.TransformToValueForEsentSorting());
				Api.SetColumn(session, Files, tableColumnsCache.FilesColumns["metadata"], headers.ToString(Formatting.None), Encoding.Unicode);

				update.Save();
			}
			logger.Debug("Adding attachment {0}", key);

			return newETag;
		}
Exemplo n.º 3
0
        public void ShrinkColumnStream()
        {
            var bookmark = new byte[SystemParameters.BookmarkMost];
            int bookmarkSize;

            const int Length = 1345;
            var       data   = Any.BytesOfLength(Length);

            using (var transaction = new Transaction(this.sesid))
                using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert))
                    using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText))
                    {
                        stream.Write(data, 0, data.Length);
                        stream.Write(data, 0, data.Length);
                        Assert.AreEqual(Length * 2, stream.Length);

                        stream.SetLength(Length);
                        Assert.AreEqual(Length, stream.Length);

                        update.Save(bookmark, bookmark.Length, out bookmarkSize);
                        transaction.Commit(CommitTransactionGrbit.LazyFlush);
                    }

            Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize);
            using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText))
            {
                Assert.AreEqual(Length, stream.Length);
                var buffer = new byte[Length];
                stream.Read(buffer, 0, buffer.Length);
                CollectionAssert.AreEqual(data, buffer);
            }
        }
Exemplo n.º 4
0
        public AddDocumentResult InsertDocument(string key, RavenJObject data, RavenJObject metadata, bool checkForUpdates)
        {
            var  prep     = JET_prep.Insert;
            bool isUpdate = false;

            if (checkForUpdates)
            {
                Api.JetSetCurrentIndex(session, Documents, "by_key");
                Api.MakeKey(session, Documents, key, Encoding.Unicode, MakeKeyGrbit.NewKey);
                isUpdate = Api.TrySeek(session, Documents, SeekGrbit.SeekEQ);
                if (isUpdate)
                {
                    prep = JET_prep.Replace;
                }
            }
            using (var update = new Update(session, Documents, prep))
            {
                Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["key"], key, Encoding.Unicode);
                using (var columnStream = new ColumnStream(session, Documents, tableColumnsCache.DocumentsColumns["data"]))
                {
                    if (isUpdate)
                    {
                        columnStream.SetLength(0);
                    }
                    using (Stream stream = new BufferedStream(columnStream))
                        using (var finalStream = documentCodecs.Aggregate(stream, (current, codec) => codec.Encode(key, data, metadata, current)))
                        {
                            data.WriteTo(finalStream);
                            finalStream.Flush();
                        }
                }
                Guid newEtag = uuidGenerator.CreateSequentialUuid(UuidType.Documents);
                Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["etag"], newEtag.TransformToValueForEsentSorting());
                DateTime savedAt = SystemTime.UtcNow;
                Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["last_modified"], savedAt.ToBinary());

                using (var columnStream = new ColumnStream(session, Documents, tableColumnsCache.DocumentsColumns["metadata"]))
                {
                    if (isUpdate)
                    {
                        columnStream.SetLength(0);
                    }
                    using (Stream stream = new BufferedStream(columnStream))
                    {
                        metadata.WriteTo(stream);
                        stream.Flush();
                    }
                }

                update.Save();

                return(new AddDocumentResult
                {
                    Etag = newEtag,
                    SavedAt = savedAt,
                    Updated = isUpdate
                });
            }
        }
Exemplo n.º 5
0
 public void ColumnStreamSetLengthThrowsExceptionWhenLengthIsNegative()
 {
     using (var t = new Transaction(this.sesid))
         using (var u = new Update(this.sesid, this.tableid, JET_prep.Insert))
             using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText))
             {
                 stream.SetLength(-1);
             }
 }
Exemplo n.º 6
0
        /// <summary>Store the column value in the database.</summary>
        public override void Serialize(EseCursorBase cur, JET_COLUMNID idColumn, object value, bool bNewRecord)
        {
            using (var stm = new ColumnStream(cur.idSession, cur.idTable, idColumn))
            {
                using (XmlDictionaryWriter bw = XmlDictionaryWriter.CreateBinaryWriter(stm, this.dict))
                {
                    this.m_serializer.WriteObject(bw, value);
                    bw.Flush();
                }

                // TODO [low]: if the ( current size - new size < 4kb ), then append spaces/zeros instead of resizing the column. The comments inside the SetLength method suggest that shrinking the column is very inefficient for large values.
                if (stm.Position < stm.Length)
                {
                    stm.SetLength(stm.Position);
                }
            }
        }
Exemplo n.º 7
0
        public AddDocumentResult PutDocumentMetadata(string key, RavenJObject metadata)
        {
            Api.JetSetCurrentIndex(session, Documents, "by_key");
            Api.MakeKey(session, Documents, key, Encoding.Unicode, MakeKeyGrbit.NewKey);
            var isUpdate = Api.TrySeek(session, Documents, SeekGrbit.SeekEQ);

            if (isUpdate == false)
            {
                throw new InvalidOperationException("Updating document metadata is only valid for existing documents, but " + key +
                                                    " does not exists");
            }

            Etag     newEtag = uuidGenerator.CreateSequentialUuid(UuidType.Documents);
            DateTime savedAt = SystemTime.UtcNow;

            using (var update = new Update(session, Documents, JET_prep.Replace))
            {
                Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["etag"], newEtag.TransformToValueForEsentSorting());
                Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["last_modified"], savedAt.ToBinary());

                using (var columnStream = new ColumnStream(session, Documents, tableColumnsCache.DocumentsColumns["metadata"]))
                {
                    columnStream.SetLength(0);                     // always updating here
                    using (Stream stream = new BufferedStream(columnStream))
                    {
                        metadata.WriteTo(stream);
                        stream.Flush();
                    }
                }

                update.Save();
            }
            return(new AddDocumentResult
            {
                Etag = newEtag,
                SavedAt = savedAt,
                Updated = true
            });
        }
Exemplo n.º 8
0
        public void SetColumnStreamToZeroLength()
        {
            var bookmark = new byte[SystemParameters.BookmarkMost];
            int bookmarkSize;

            using (var transaction = new Transaction(this.sesid))
                using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert))
                    using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText))
                    {
                        byte[] data = Any.Bytes;
                        stream.Write(data, 0, data.Length);

                        stream.SetLength(0);
                        Assert.AreEqual(0, stream.Length);

                        update.Save(bookmark, bookmark.Length, out bookmarkSize);
                        transaction.Commit(CommitTransactionGrbit.LazyFlush);
                    }

            Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize);
            CollectionAssert.AreEqual(new byte[0], Api.RetrieveColumn(this.sesid, this.tableid, this.columnidLongText));
        }
Exemplo n.º 9
0
        public void SetColumnStreamLength()
        {
            var bookmark = new byte[SystemParameters.BookmarkMost];
            int bookmarkSize;

            const long Length = 1345;

            using (var transaction = new Transaction(this.sesid))
                using (var update = new Update(this.sesid, this.tableid, JET_prep.Insert))
                    using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText))
                    {
                        stream.SetLength(Length);
                        Assert.AreEqual(Length, stream.Length);

                        update.Save(bookmark, bookmark.Length, out bookmarkSize);
                        transaction.Commit(CommitTransactionGrbit.LazyFlush);
                    }

            Api.JetGotoBookmark(this.sesid, this.tableid, bookmark, bookmarkSize);
            using (var stream = new ColumnStream(this.sesid, this.tableid, this.columnidLongText))
            {
                Assert.AreEqual(Length, stream.Length);
            }
        }
Exemplo n.º 10
0
        public AddDocumentResult AddDocument(string key, Etag etag, RavenJObject data, RavenJObject metadata)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            var byteCount = Encoding.Unicode.GetByteCount(key);

            if (byteCount >= 2048)
            {
                throw new ArgumentException(string.Format("The key must be a maximum of 2,048 bytes in Unicode, 1,024 characters, key is: '{0}'", key), "key");
            }

            try
            {
                Api.JetSetCurrentIndex(session, Documents, "by_key");
                Api.MakeKey(session, Documents, key, Encoding.Unicode, MakeKeyGrbit.NewKey);
                var isUpdate = Api.TrySeek(session, Documents, SeekGrbit.SeekEQ);

                Etag existingEtag = null;
                if (isUpdate)
                {
                    existingEtag = EnsureDocumentEtagMatch(key, etag, "PUT");
                }
                else
                {
                    if (etag != null && etag != Etag.Empty)                     // expected something to be there.
                    {
                        throw new ConcurrencyException("PUT attempted on document '" + key +
                                                       "' using a non current etag (document deleted)")
                              {
                                  ExpectedETag = etag
                              }
                    }
                    ;
                    if (Api.TryMoveFirst(session, Details))
                    {
                        Api.EscrowUpdate(session, Details, tableColumnsCache.DetailsColumns["document_count"], 1);
                    }
                }
                Etag newEtag = uuidGenerator.CreateSequentialUuid(UuidType.Documents);

                DateTime savedAt;
                try
                {
                    using (var update = new Update(session, Documents, isUpdate ? JET_prep.Replace : JET_prep.Insert))
                    {
                        Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["key"], key, Encoding.Unicode);
                        using (var columnStream = new ColumnStream(session, Documents, tableColumnsCache.DocumentsColumns["data"]))
                        {
                            if (isUpdate)
                            {
                                columnStream.SetLength(0);                                 // empty the existing value, since we are going to overwrite the entire thing
                            }
                            using (Stream stream = new BufferedStream(columnStream))
                                using (
                                    var finalStream = documentCodecs.Aggregate(stream, (current, codec) => codec.Encode(key, data, metadata, current))
                                    )
                                {
                                    data.WriteTo(finalStream);
                                    finalStream.Flush();
                                }
                        }
                        Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["etag"],
                                      newEtag.TransformToValueForEsentSorting());

                        savedAt = SystemTime.UtcNow;
                        Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["last_modified"], savedAt.ToBinary());

                        using (var columnStream = new ColumnStream(session, Documents, tableColumnsCache.DocumentsColumns["metadata"]))
                        {
                            if (isUpdate)
                            {
                                columnStream.SetLength(0);
                            }
                            using (Stream stream = new BufferedStream(columnStream))
                            {
                                metadata.WriteTo(stream);
                                stream.Flush();
                            }
                        }


                        update.Save();
                    }
                }
                catch (EsentErrorException e)
                {
                    if (e.Error == JET_err.KeyDuplicate || e.Error == JET_err.WriteConflict)
                    {
                        throw new ConcurrencyException("PUT attempted on document '" + key + "' concurrently", e);
                    }
                    throw;
                }


                logger.Debug("Inserted a new document with key '{0}', update: {1}, ",
                             key, isUpdate);

                cacher.RemoveCachedDocument(key, newEtag);
                return(new AddDocumentResult
                {
                    Etag = newEtag,
                    PrevEtag = existingEtag,
                    SavedAt = savedAt,
                    Updated = isUpdate
                });
            }
            catch (EsentKeyDuplicateException e)
            {
                throw new ConcurrencyException("Illegal duplicate key " + key, e);
            }
        }
Exemplo n.º 11
0
        public AddDocumentResult InsertDocument(string key, RavenJObject data, RavenJObject metadata, bool overwriteExisting)
        {
            var  prep     = JET_prep.Insert;
            bool isUpdate = false;

            Etag existingETag = null;

            if (overwriteExisting)
            {
                Api.JetSetCurrentIndex(session, Documents, "by_key");
                Api.MakeKey(session, Documents, key, Encoding.Unicode, MakeKeyGrbit.NewKey);
                isUpdate = Api.TrySeek(session, Documents, SeekGrbit.SeekEQ);
                if (isUpdate)
                {
                    existingETag = Etag.Parse(Api.RetrieveColumn(session, Documents, tableColumnsCache.DocumentsColumns["etag"]));
                    prep         = JET_prep.Replace;
                }
            }

            try
            {
                using (var update = new Update(session, Documents, prep))
                {
                    Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["key"], key, Encoding.Unicode);
                    using (var columnStream = new ColumnStream(session, Documents, tableColumnsCache.DocumentsColumns["data"]))
                    {
                        if (isUpdate)
                        {
                            columnStream.SetLength(0);
                        }
                        using (Stream stream = new BufferedStream(columnStream))
                            using (var finalStream = documentCodecs.Aggregate(stream, (current, codec) => codec.Encode(key, data, metadata, current)))
                            {
                                data.WriteTo(finalStream);
                                finalStream.Flush();
                            }
                    }
                    Etag newEtag = uuidGenerator.CreateSequentialUuid(UuidType.Documents);
                    Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["etag"], newEtag.TransformToValueForEsentSorting());
                    DateTime savedAt = SystemTime.UtcNow;
                    Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["last_modified"], savedAt.ToBinary());

                    using (var columnStream = new ColumnStream(session, Documents, tableColumnsCache.DocumentsColumns["metadata"]))
                    {
                        if (isUpdate)
                        {
                            columnStream.SetLength(0);
                        }
                        using (Stream stream = new BufferedStream(columnStream))
                        {
                            metadata.WriteTo(stream);
                            stream.Flush();
                        }
                    }

                    update.Save();

                    if (existingETag != null)
                    {
                        cacher.RemoveCachedDocument(key, existingETag);
                    }

                    return(new AddDocumentResult
                    {
                        Etag = newEtag,
                        PrevEtag = existingETag,
                        SavedAt = savedAt,
                        Updated = isUpdate
                    });
                }
            }
            catch (EsentKeyDuplicateException e)
            {
                throw new ConcurrencyException("Illegal duplicate key " + key, e);
            }
        }
Exemplo n.º 12
0
        public Guid AddDocumentInTransaction(string key, Guid?etag, RavenJObject data, RavenJObject metadata, TransactionInformation transactionInformation)
        {
            Api.JetSetCurrentIndex(session, Documents, "by_key");
            Api.MakeKey(session, Documents, key, Encoding.Unicode, MakeKeyGrbit.NewKey);
            var isUpdate = Api.TrySeek(session, Documents, SeekGrbit.SeekEQ);

            if (isUpdate)
            {
                EnsureNotLockedByTransaction(key, transactionInformation.Id);
                EnsureDocumentEtagMatchInTransaction(key, etag);
                using (var update = new Update(session, Documents, JET_prep.Replace))
                {
                    Api.SetColumn(session, Documents, tableColumnsCache.DocumentsColumns["locked_by_transaction"], transactionInformation.Id.ToByteArray());
                    update.Save();
                }
            }
            else
            {
                EnsureDocumentIsNotCreatedInAnotherTransaction(key, transactionInformation.Id);
            }
            EnsureTransactionExists(transactionInformation);
            Guid newEtag = uuidGenerator.CreateSequentialUuid(UuidType.DocumentTransactions);

            Api.JetSetCurrentIndex(session, DocumentsModifiedByTransactions, "by_key");
            Api.MakeKey(session, DocumentsModifiedByTransactions, key, Encoding.Unicode, MakeKeyGrbit.NewKey);
            var isUpdateInTransaction = Api.TrySeek(session, DocumentsModifiedByTransactions, SeekGrbit.SeekEQ);

            using (var update = new Update(session, DocumentsModifiedByTransactions, isUpdateInTransaction ? JET_prep.Replace : JET_prep.Insert))
            {
                Api.SetColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["key"], key, Encoding.Unicode);

                using (var columnStream = new ColumnStream(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["data"]))
                {
                    if (isUpdate)
                    {
                        columnStream.SetLength(0);
                    }
                    using (Stream stream = new BufferedStream(columnStream))
                        using (var finalStream = documentCodecs.Aggregate(stream, (current, codec) => codec.Encode(key, data, metadata, current)))
                        {
                            data.WriteTo(finalStream);
                            finalStream.Flush();
                        }
                }
                Api.SetColumn(session, DocumentsModifiedByTransactions,
                              tableColumnsCache.DocumentsModifiedByTransactionsColumns["etag"],
                              newEtag.TransformToValueForEsentSorting());

                using (var columnStream = new ColumnStream(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["metadata"]))
                {
                    if (isUpdate)
                    {
                        columnStream.SetLength(0);
                    }
                    using (Stream stream = new BufferedStream(columnStream))
                    {
                        metadata.WriteTo(stream);
                        stream.Flush();
                    }
                }

                Api.SetColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["last_modified"], SystemTime.UtcNow.ToBinary());
                Api.SetColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["delete_document"], false);
                Api.SetColumn(session, DocumentsModifiedByTransactions, tableColumnsCache.DocumentsModifiedByTransactionsColumns["locked_by_transaction"], transactionInformation.Id.ToByteArray());

                update.Save();
            }
            logger.Debug("Inserted a new document with key '{0}', update: {1}, in transaction: {2}",
                         key, isUpdate, transactionInformation.Id);

            return(newEtag);
        }