public long WriteDocument(DocumentId documentId, byte[] blob) { // calculate the size of the document including meta data int size = 2 + documentId.Length + 4 + blob.Length; int position = 0; Buffer.BlockCopy(BitConverter.GetBytes((UInt16)documentId.Length), 0, m_writeDocumentBuffer, position, 2); position += 2; Buffer.BlockCopy(documentId.Bytes, 0, m_writeDocumentBuffer, position, documentId.Length); position += documentId.Length; Buffer.BlockCopy(BitConverter.GetBytes(blob.Length), 0, m_writeDocumentBuffer, position, 4); position += 4; if (blob.Length > 0) { Buffer.BlockCopy(blob, 0, m_writeDocumentBuffer, position, blob.Length); } m_writerStream.Write(m_writeDocumentBuffer, 0, size); return m_writerStream.Position - blob.Length; }
public Document GetDocument(DocumentId documentId) { Document document; m_documents.TryGetValue(documentId, out document); return document; }
protected bool Equals(DocumentId other) { if (other.Bytes.Length != Bytes.Length) { return false; } return Bytes.SequenceEqual(other.Bytes); }
public void ThenDocumentIsInTheDatabaseWithKeyAndValue(int key, string value) { DocumentId documentId = new DocumentId(key); byte[] valueBytes = m_databaseContext.Database.Get(documentId); string dbValue = Encoding.ASCII.GetString(valueBytes); Assert.AreEqual(dbValue, value); }
public Document GetDocumentForUpdate(DocumentId documentId, int transactionId) { Document document; if (m_documents.TryGetValue(documentId, out document) && document.IsLocked && transactionId != document.TransactionId) { throw new DocumentLockedException(); } else if (document != null && document.TransactionId == 0 && transactionId != -1) { document.TransactionLock(transactionId); } return document; }
public void ReadDocumentUpdatedByTransaction() { DocumentId id1 = new DocumentId("1"); m_db.Update(id1, new byte[1] { 0 }); int transactionId = m_db.StartTransaction(); m_db.TransactionUpdate(transactionId, id1, new byte[1] { 1 }); byte[] blob = m_db.TransactionGet(transactionId, id1); Assert.AreEqual(1, blob[0]); // reading without transaction should return uncommitted document blob = m_db.Get(id1); Assert.AreEqual(0, blob[0]); m_db.CommitTransaction(transactionId); // reading the object agian after the transaction committed making sure we are reading the new committed document blob = m_db.Get(id1); Assert.AreEqual(1, blob[0]); }
public void ReadOldRevisionDuringTransaction() { DocumentId id1 = new DocumentId("1"); m_db.Update(id1, new byte[1] { 0 }); int transactionId = m_db.StartTransaction(); m_db.Update(id1, new byte[1] { 1 }); byte[] blob = m_db.TransactionGet(transactionId, id1); Assert.AreEqual(0, blob[0]); m_db.CommitTransaction(transactionId); transactionId = m_db.StartTransaction(); blob = m_db.TransactionGet(transactionId, id1); Assert.AreEqual(1, blob[0]); m_db.CommitTransaction(transactionId); }
public byte[] TransactionGet(int transactionId, DocumentId documentId) { Transaction transaction; if (!m_pendingTransaction.TryGetValue(transactionId, out transaction)) { throw new TransactionNotExistException(); } Document document = m_documentStore.GetDocument(documentId); if (document == null) { return ZeroBlob; } // if updated by current transaction we just return the current blob if (document.TransactionId == transactionId) { return transaction.GetBlob(documentId); } // we need to find the current revision DocumentRevision revision = document.GetDocumentRevisionByTimestamp(transaction.DBTimestamp); // if there is no revision the object is not exist for this timestamp if (revision == null) { return ZeroBlob; } return ReadInternal(revision.BlobFileLocation, revision.BlobSize); }
public Dictionary<DocumentId, Document> GetDocuments(out ulong dbTimestamp) { dbTimestamp = 0; Dictionary<DocumentId, Document> documents = new Dictionary<DocumentId, Document>(); // initialize the buffers byte[] timestampBuffer = new byte[12]; byte[] documentIdLengthBuffer = new byte[2]; byte[] documentIdBuffer = new byte[UInt16.MaxValue]; byte[] blobLengthBuffer = new byte[4]; int numberOfDocuments = 0; int documentsCounter = 0; // now we read all the objects meta data (not loading any data yet) while (m_readStream.Position < m_readStream.Length) { if (numberOfDocuments == documentsCounter) { // now we are reading the object timestamp m_readStream.Read(timestampBuffer, 0, 12); dbTimestamp = BitConverter.ToUInt64(timestampBuffer, 0); numberOfDocuments = BitConverter.ToInt32(timestampBuffer, 8); documentsCounter = 0; } // first is the object id lenth m_readStream.Read(documentIdLengthBuffer, 0, 2); UInt16 objectIdLength = BitConverter.ToUInt16(documentIdLengthBuffer, 0); // read the objectId m_readStream.Read(documentIdBuffer, 0, objectIdLength); byte[] documentIdBytes = new byte[objectIdLength]; Buffer.BlockCopy(documentIdBuffer, 0, documentIdBytes, 0, objectIdLength); DocumentId documentId = new DocumentId(documentIdBytes); // read the blob length m_readStream.Read(blobLengthBuffer, 0, 4); int blobLength = BitConverter.ToInt32(blobLengthBuffer, 0); long blobLocation = m_readStream.Position; // take the position of the file to the next document m_readStream.Position += blobLength; // check if the document not exist and not deleted (zero length is deleted if (!documents.ContainsKey(documentId) && blobLength > 0) { documents.Add(documentId, new Document(documentId, dbTimestamp, blobLocation, blobLength)); } else { // if the document is deleted we just remove the document from the store if (blobLength == 0) { documents.Remove(documentId); } else { Document document = documents[documentId]; document.Update(dbTimestamp, blobLocation, blobLength, false); } } documentsCounter++; } if (documentsCounter != numberOfDocuments) { // database is corrupted, need to recover throw new Exception("Database is corrupted"); } return documents; }
private void TransactionUpdate() { byte[] transactionIdBytes = m_serverSocket.Receive(); int transactionId = BitConverter.ToInt32(transactionIdBytes, 0); byte[] documentIdBytes = m_serverSocket.Receive(); DocumentId documentId = new DocumentId(documentIdBytes); byte[] blob = m_serverSocket.Receive(); try { m_db.TransactionUpdate(transactionId, documentId, blob); // sending success m_serverSocket.Send(Protocol.Success); } catch (TransactionNotExistException ex) { m_serverSocket.SendMore(Protocol.Failed).Send("Transaction doesn't exist"); } catch (DocumentLockedException) { m_serverSocket.SendMore(Protocol.Failed).Send("Document locked by another transaction"); } }
public byte[] GetBlob(DocumentId documentId) { return m_updates[documentId]; }
public void AddUpdate(DocumentId documentId, byte[] blob) { m_updates.Add(documentId, blob); }
private void TransactionGet() { byte[] transactionIdBytes = m_serverSocket.Receive(); int transactionId = BitConverter.ToInt32(transactionIdBytes, 0); byte[] documentIdBytes = m_serverSocket.Receive(); DocumentId documentId = new DocumentId(documentIdBytes); try { byte [] blob = m_db.TransactionGet(transactionId, documentId); if (blob == null) { blob = new byte[0]; } m_serverSocket.SendMore(Protocol.Success).Send(blob); } catch (TransactionNotExistException ex) { m_serverSocket.SendMore(Protocol.Failed).Send("Transaction doesn't exist"); } }
private void Delete() { byte[] documentIdBytes = m_serverSocket.Receive(); DocumentId documentId = new DocumentId(documentIdBytes); try { m_db.Delete(documentId); // sending success m_serverSocket.Send(Protocol.Success); } catch (DocumentLockedException) { m_serverSocket.SendMore(Protocol.Failed).Send("Document locked by another transaction"); } }
public void Delete(DocumentId documentId) { Update(documentId, ZeroBlob); }
public void TransactionDelete(int transactionId, DocumentId documentId) { TransactionUpdate(transactionId, documentId, ZeroBlob); }
public byte[] Get(DocumentId key) { Document document = m_documentStore.GetDocument(key); if (document != null) { return ReadInternal(document.CurrentRevision.BlobFileLocation, document.CurrentRevision.BlobSize); } else { return ZeroBlob; } }
public void TryReadFutureDocument() { int transactionId = m_db.StartTransaction(); DocumentId id1 = new DocumentId("1"); // this object is stored out of transaction therefore should be visible for the transaction m_db.Update(id1, new byte[1] { 0 }); byte[] blob = m_db.TransactionGet(transactionId, id1); Assert.IsNull(blob); m_db.CommitTransaction(transactionId); }
public void TransactionUpdate(int transactionId, DocumentId documentId, byte[] blob) { Transaction transaction; if (!m_pendingTransaction.TryGetValue(transactionId, out transaction)) { throw new TransactionNotExistException(); } try { // mark the document is updated by transaction m_documentStore.GetDocumentForUpdate(documentId, transactionId); } catch (DocumentLockedException) { m_log.InfoFormat("Tranasction {1} update failed because document is locked by another transaction, documentId(bytes):{0}", documentId.GetBytesReprestnation(), transactionId); throw; } transaction.AddUpdate(documentId, blob); }
public void AddNewDocument(DocumentId documentId, ulong documentTimeStamp, long blobFileLocation, int blobSize) { m_documents.Add(documentId, new Document(documentId, documentTimeStamp, blobFileLocation, blobSize)); }
public void Update(DocumentId documentId, byte[] blob) { Document document; try { document = m_documentStore.GetDocumentForUpdate(documentId, -1); } catch (DocumentLockedException) { m_log.InfoFormat("Update failed because document is locked by another transaction, documentId(bytes):{0}", documentId.GetBytesReprestnation()); throw; } DBTimeStamp++; m_databaseFileWriter.BeginTimestamp(DBTimeStamp, 1); long documentLocation = m_databaseFileWriter.WriteDocument(documentId, blob); if (blob.Length > 0) { m_cacheProvider.Set(documentLocation, blob); } m_databaseFileWriter.Flush(); if (document != null) { document.Update(DBTimeStamp, documentLocation, blob.Length, true); } else { m_documentStore.AddNewDocument(documentId, DBTimeStamp, documentLocation, blob.Length); } }
public Document(DocumentId documentId, ulong documentTimeStamp, long blobFileLocation, int blobSize) { DocumentId = documentId; CurrentRevision = new DocumentRevision(documentId,documentTimeStamp, blobFileLocation, blobSize); }
private void Get() { byte[] documentIdBytes = m_serverSocket.Receive(); DocumentId documentId = new DocumentId(documentIdBytes); byte[] blob = m_db.Get(documentId); if (blob == null) { blob = new byte[0]; } m_serverSocket.SendMore(Protocol.Success).Send(blob); }