Пример #1
0
        private void FlushTrimmedTransactionLog()
        {
            byte[] transactionBuffer;
            using (var ms = new MemoryStream())
            {
                ms.Write(Constants.StartTransactionSeparator, 0, Constants.StartTransactionSeparator.Length);

                var count = BitConverter.GetBytes(EstimatedCountOfItemsInQueue);
                ms.Write(count, 0, count.Length);

                var checkedOut = checkedOutEntries.ToArray();
                foreach (var entry in checkedOut)
                {
                    WriteEntryToTransactionLog(ms, entry, OperationType.Enqueue);
                }

                var listedEntries = entries.ToArray();
                foreach (var entry in listedEntries)
                {
                    WriteEntryToTransactionLog(ms, entry, OperationType.Enqueue);
                }
                ms.Write(Constants.EndTransactionSeparator, 0, Constants.EndTransactionSeparator.Length);
                ms.Flush();
                transactionBuffer = ms.ToArray();
            }
            Atomic.Write(TransactionLog, stream =>
            {
                stream.SetLength(transactionBuffer.Length);
                stream.Write(transactionBuffer, 0, transactionBuffer.Length);
            });
        }
Пример #2
0
        private void ReadTransactionLog()
        {
            var requireTxLogTrimming = false;

            Atomic.Read(TransactionLog, stream =>
            {
                using (var binaryReader = new BinaryReader(stream))
                {
                    bool readingTransaction = false;
                    try
                    {
                        int txCount = 0;
                        while (true)
                        {
                            txCount += 1;
                            // this code ensures that we read the full transaction
                            // before we start to apply it. The last truncated transaction will be
                            // ignored automatically.
                            AssertTransactionSeperator(binaryReader, txCount, Constants.StartTransactionSeparatorGuid,
                                                       () => readingTransaction = true);
                            var opsCount = binaryReader.ReadInt32();
                            var txOps    = new List <Operation>(opsCount);
                            for (var i = 0; i < opsCount; i++)
                            {
                                AssertOperationSeparator(binaryReader);
                                var operation = new Operation(
                                    ( OperationType )binaryReader.ReadByte(),
                                    binaryReader.ReadInt32(),
                                    binaryReader.ReadInt32(),
                                    binaryReader.ReadInt32()
                                    );
                                txOps.Add(operation);
                                //if we have non enqueue entries, this means
                                // that we have not closed properly, so we need
                                // to trim the log
                                if (operation.Type != OperationType.Enqueue)
                                {
                                    requireTxLogTrimming = true;
                                }
                            }
                            AssertTransactionSeperator(binaryReader, txCount, Constants.EndTransactionSeparatorGuid, () => { });
                            readingTransaction = false;
                            ApplyTransactionOperations(txOps);
                        }
                    }
                    catch (EndOfStreamException)
                    {
                        // we have a truncated transaction, need to clear that
                        if (readingTransaction)
                        {
                            requireTxLogTrimming = true;
                        }
                    }
                }
            });
            if (requireTxLogTrimming)
            {
                FlushTrimmedTransactionLog();
            }
        }
Пример #3
0
 private void ReadMetaState()
 {
     Atomic.Read(Meta, stream =>
     {
         using (var binaryReader = new BinaryReader(stream))
         {
             try
             {
                 CurrentFileNumber   = binaryReader.ReadInt32();
                 CurrentFilePosition = binaryReader.ReadInt64();
             }
             catch (EndOfStreamException)
             {
             }
         }
     });
 }
Пример #4
0
        public void CommitTransaction(ICollection <Operation> operations)
        {
            if (operations.Count == 0)
            {
                return;
            }

            byte[] transactionBuffer = GenerateTransactionBuffer(operations);

            lock (transactionLogLock)
            {
                long txLogSize;
                using (var stream = WaitForTransactionLog(transactionBuffer))
                {
                    stream.Write(transactionBuffer, 0, transactionBuffer.Length);
                    txLogSize = stream.Position;
                    stream.Flush();
                }

                ApplyTransactionOperations(operations);
                TrimTransactionLogIfNeeded(txLogSize);

                Atomic.Write(Meta, stream =>
                {
                    var bytes = BitConverter.GetBytes(CurrentFileNumber);
                    stream.Write(bytes, 0, bytes.Length);
                    bytes = BitConverter.GetBytes(CurrentFilePosition);
                    stream.Write(bytes, 0, bytes.Length);
                });

                if (ParanoidFlushing)
                {
                    FlushTrimmedTransactionLog();
                }
            }
        }