public void CancelDelayedTransaction() { TransactionLog.CancelTransaction(); }
public void Start() { _storage = Container != null ? new ReliableStorage(new ObjectProcessor(Container), WorkingDirectory) : new ReliableStorage(new NullObjectProcessor(), WorkingDirectory); ServerLog.LogInfo("start processing schema"); // Stage 1 load the schema and // register types (this will create an in-memory data store for each type) lock (_schemaSync) { Container?.LoadSchema(SchemaFilePath); Container?.LoadSequence(SequenceFilePath); } ServerLog.LogInfo("end processing schema"); ServerLog.LogInfo("start loading transaction log"); TransactionLog = new TransactionLog(WorkingDirectory); ServerLog.LogInfo("end loading transaction log"); // if there are pending transactions data needs to be loaded twice // first without processing the persistent objects; simply initializing offset tables // second after processing pending transactions reload and store objects in memory if (TransactionLog.PendingTransactionsCount > 0) { ServerLog.LogInfo("start loading data before transaction processing"); // load once without processing the objects _storage.LoadPersistentData(false); ServerLog.LogInfo("end loading data before transaction processing"); } // start the thread that will process pending transactions StartProcessingTransactions(); ServerLog.LogInfo("start waiting for pending transactions to be processed"); // Stage 2 wait for the persistence engine to commit all the pending transactions in the log // in the storage WaitForPendingTransactions(); ServerLog.LogInfo("end waiting for pending transactions"); // Stage 3 house keeping ServerLog.LogInfo("start compacting the transaction log"); TransactionLog.ClearLog(); ServerLog.LogInfo("end compacting the transaction log"); ServerLog.LogInfo("start compacting the persistence storage"); _storage.CleanStorage(); ServerLog.LogInfo("end compacting the persistence storage"); ServerLog.LogInfo("begin load data"); // Stage 4 load data from persisent storage to memory _storage.LoadPersistentData(); ServerLog.LogInfo("end load data"); }
private void StartProcessingTransactions() { _shouldContinue = true; _singleConsumer = new Thread(() => { while (_shouldContinue) { try { // this call is blocking if nothing to process var persistentTransaction = TransactionLog.StartProcessing(); if (persistentTransaction != null && persistentTransaction.TransactionStatus != TransactionStaus.Canceled) { var data = persistentTransaction.Data; var transaction = SerializationHelper.ObjectFromBytes <Transaction>(data, SerializationMode.ProtocolBuffers, false); if (transaction is MixedTransaction mixedTransaction) { foreach (var item in mixedTransaction.ItemsToPut) { var itemData = SerializationHelper.ObjectToBytes(item, SerializationMode.ProtocolBuffers, null); Dbg.Trace( $"storing persistent block for object {item} transaction={persistentTransaction.Id}"); _storage.StoreBlock(itemData, item.GlobalKey, unchecked ((int)persistentTransaction.Id)); } foreach (var item in mixedTransaction.ItemsToDelete) { Dbg.Trace($"deleting persistent block {persistentTransaction.Id}"); _storage.DeleteBlock(item.GlobalKey, unchecked ((int)persistentTransaction.Id)); } } if (transaction is PutTransaction putTransaction) { foreach (var item in putTransaction.Items) { var itemData = SerializationHelper.ObjectToBytes(item, SerializationMode.ProtocolBuffers, null); Dbg.Trace( $"storing persistent block for object {item} transaction={persistentTransaction.Id}"); _storage.StoreBlock(itemData, item.GlobalKey, unchecked ((int)persistentTransaction.Id)); } } if (transaction is DeleteTransaction deleteTransaction) { foreach (var item in deleteTransaction.ItemsToDelete) { Dbg.Trace($"deleting persistent block {persistentTransaction.Id}"); _storage.DeleteBlock(item.GlobalKey, unchecked ((int)persistentTransaction.Id)); } } TransactionLog.EndProcessing(persistentTransaction); } else { return; } } catch (Exception e) { Dbg.Trace(e.Message); //TODO add proper logging } } }); _singleConsumer.Start(); }