/// <summary> /// Cancel the last transaction. Works only if it was a delayed transaction /// </summary> public void CancelTransaction() { lock (_syncRoot) { Dbg.Trace("canceling transaction from transaction log"); if (_disposed) { throw new ObjectDisposedException("The object was disposed"); } Dbg.Trace("begin canceling transaction"); var data = _transactionQueue.Dequeue(); Dbg.Trace("removed from queue"); // reset the event so the next call is blocking if (_transactionQueue.Count == 0) { _queueNotEmpty.Reset(); } if (data.DelayInMilliseconds == 0) { throw new NotSupportedException( "Trying to cancel a transaction which is not delayed"); } data.TransactionStatus = TransactionStaus.Canceled; UpdateTransactionStatus(data); Dbg.Trace("end canceling transaction"); } }
public static bool CloseNonListForms(bool needSave) { var openedFoms = new IApplicationForm[m_FormList.Count]; m_FormList.CopyTo(openedFoms); try { foreach (IApplicationForm frm in openedFoms) { //if (!(frm is IBaseListPanel || frm is IListFormsContainer)) if (((Control)frm).FindForm() != MainForm) { if (!Close(frm, DialogResult.Cancel, needSave ? FormClosingMode.SaveWithConfirmation : FormClosingMode.NoSave)) { return(false); } } } } catch (Exception ex) { Dbg.Trace(); Dbg.Debug(ex.ToString()); } m_CurrentForm = null; return(true); }
//private static string m_DefaultLayout; //public static string DefaultLayout //{ // get // { // return m_DefaultLayout; // } // set // { // m_DefaultLayout = value; // } //} public static void ResetLanguage() { LayoutCorrector.Init(); var openedFoms = new IApplicationForm[m_FormList.Count]; m_FormList.CopyTo(openedFoms); try { foreach (IApplicationForm frm in openedFoms) { //if (!(frm is IBaseListPanel || frm is IListFormsContainer)) if (((Control)frm).FindForm() != MainForm) { Close(frm); } else { ResetLanguage(frm); } } } catch (Exception ex) { Dbg.Trace(); Dbg.Debug(ex.ToString()); } }
public void RemoveMany(IList <PackedObject> items) { Dbg.Trace($"remove many called for {items.Count} items"); foreach (var item in items) { foreach (var metadata in CollectionSchema.ServerSide) { if (metadata.IndexType == IndexType.Unique) { _dataByUniqueKey[metadata.Name].Remove(item[metadata.Order]); } } // if present remove it from the full-text index _fullTextIndex?.DeleteDocument(item.PrimaryKey); EvictionPolicy.TryRemove(item); } foreach (var index in _dataByIndexKey) { index.Value.RemoveMany(items); } foreach (var o in items) { DataByPrimaryKey.Remove(o.PrimaryKey); } }
public void EndProcessing(IPersistentTransaction transaction) { Dbg.Trace("end processing transaction from transaction log"); lock (_syncRoot) { if (_disposed) { throw new ObjectDisposedException("The object was disposed"); } var data = _transactionQueue.Dequeue(); // reset the event so the next call is blocking if (_transactionQueue.Count == 0) { _queueNotEmpty.Reset(); } if (data.Id != transaction.Id || data.TransactionStatus != TransactionStaus.Processing) { throw new NotSupportedException( "EndProcessing() can be called only on the one transaction currently in Processing status "); } data.TransactionStatus = TransactionStaus.Processed; UpdateTransactionStatus(data); } }
/// <summary> /// Remove the object from all indexes /// </summary> /// <param name="primary"></param> private PackedObject InternalRemoveByPrimaryKey(KeyValue primary) { Dbg.Trace($"remove by primary key {primary}"); var toRemove = DataByPrimaryKey[primary]; DataByPrimaryKey.Remove(primary); foreach (var metadata in CollectionSchema.ServerSide) { if (metadata.IndexType == IndexType.Unique) { _dataByUniqueKey[metadata.Name].Remove(toRemove[metadata.Order]); } if (metadata.IndexType == IndexType.Ordered || metadata.IndexType == IndexType.Dictionary) { _dataByIndexKey[metadata.Name].RemoveOne(toRemove); } } _fullTextIndex?.DeleteDocument(primary); return(toRemove); }
private void ProcessDataRequest(DataRequest dataRequest, IClient client) { DataStore dataStore; lock (DataStores) { var fullTypeName = dataRequest.FullTypeName; if (!DataStores.ContainsKey(fullTypeName)) { throw new NotSupportedException("Not registered type : " + fullTypeName); } dataStore = DataStores[fullTypeName]; } Dbg.Trace($"begin processing {dataRequest.AccessType} request on server {ShardIndex}"); if (dataRequest.AccessType == DataAccessType.Write) { if (dataStore.Lock.TryEnterWriteLock(-1)) { try { dataStore.ProcessRequest(dataRequest, client, PersistTransaction); } finally { dataStore.Lock.ExitWriteLock(); } } else { Dbg.Trace( $"failed to acquire read-only lock on server {ShardIndex} for type {dataRequest.FullTypeName}"); } } else { if (dataStore.Lock.TryEnterReadLock(-1)) { try { dataStore.ProcessRequest(dataRequest, client, PersistTransaction); } finally { dataStore.Lock.ExitReadLock(); } } else { Dbg.Trace( $"failed to acquire write lock on server {ShardIndex} for type {dataRequest.FullTypeName}"); } } Dbg.Trace($"end processing {dataRequest.AccessType} request on server {ShardIndex}"); }
public void WaitForPendingTransactions() { Dbg.Trace($"{TransactionLog.PendingTransactionsCount} pending transactions"); while (TransactionLog.PendingTransactionsCount > 0) { Thread.Sleep(10); } }
// Start is called before the first frame update public void Start() { bp = gameObject.name; Debug.Log(Application.persistentDataPath); //queue = GetComponent<MyLog>(); seshNum = " A "; Dbg.Trace("ID__" + uname); script2 = source.GetComponent <VARdist>(); script = GetComponent <TWOsidesTRI>(); }
/// <summary> /// </summary> /// <param name="items"></param> /// <param name="excludeFromEviction">used only for non persistent case</param> internal void InternalPutMany(IList <PackedObject> items, bool excludeFromEviction) { var isBulkOperation = items.Count > Constants.BulkThreshold; var toUpdate = new List <PackedObject>(); try { Dbg.Trace($"begin InternalPutMany with {items.Count} object"); InternalBeginBulkInsert(isBulkOperation); foreach (var item in items) { if (DataByPrimaryKey.ContainsKey(item.PrimaryKey)) { toUpdate.Add(item); } else { InternalAddNew(item, excludeFromEviction); } } } finally { InternalEndBulkInsert(isBulkOperation); // update items outside the bulk insert if (toUpdate.Count > Constants.BulkThreshold) // bulk optimization for updates { RemoveMany(toUpdate); InternalPutMany(toUpdate, true); } else { foreach (var cachedObject in toUpdate) { InternalUpdate(cachedObject); } } foreach (var cachedObject in toUpdate) { EvictionPolicy.Touch(cachedObject); } Dbg.Trace($"end InternalPutMany with {items.Count} object"); } }
public void EndProcess() { foreach (var pair in _temporaryStorage) { _dataContainer.DataStores[pair.Key].InternalPutMany(pair.Value, true, null); } _temporaryStorage.Clear(); Dbg.Trace("done loading persistent objects into memory"); }
public void ExecuteTransaction(IList <CachedObject> itemsToPut, IList <OrQuery> conditions, IList <CachedObject> itemsToDelete = null) { var locksOk = false; var iteration = 0; while (!locksOk) { var delay = ThreadLocalRandom.Instance.Next(10 * iteration); TransactionStatistics.Retries(iteration + 1); Dbg.Trace( $"C: delay = {delay} for iteration {iteration} single stage transaction connector {GetHashCode()}"); if (delay > 0) { Thread.Sleep(delay); } if (itemsToPut == null) { throw new ArgumentNullException(nameof(itemsToPut)); } var request = new TransactionRequest(itemsToPut, conditions, itemsToDelete) { IsSingleStage = true }; TransactionStatistics.ExecutedAsSingleStage(); var response = Channel.SendRequest(request); if (response is NullResponse) { locksOk = true; } else if (response is ExceptionResponse exResponse) { if (exResponse.ExceptionType != ExceptionType.FailedToAcquireLock) { throw new CacheException(exResponse.Message, exResponse.ExceptionType); } } } TransactionStatistics.NewTransactionCompleted(); }
void Start() { propellersController = GetComponent <PropellersController> (); rb = GetComponent <Rigidbody>(); m_PhotonView = GetComponent <PhotonView>(); rb.inertiaTensor = new Vector3(12e-4f, 15e-4f, 10e-4f); LoadPlayerPrefs(); resetYawRef(); Dbg.Trace("phi, theta, psi, phi_ref, theta_ref, psi_ref, p, q, r, p_ref, q_ref, r_ref, torque_x, torque_y, torque_z, vz, vz_ref, thrust_Z"); }
public void NewTransaction(byte[] data, int delayInMilliseconds = 0) { lock (_syncRoot) { if (_disposed) { throw new ObjectDisposedException("The object was disposed"); } // the file pointer is always at the end var transaction = new TransactionData { TimeStamp = DateTime.Now, TransactionStatus = TransactionStaus.ToProcess, Offset = _lastOffset, Data = data, DelayInMilliseconds = delayInMilliseconds }; var writer = new BinaryWriter(_transactionLog); writer.Write((int)transaction.TransactionStatus); writer.Write(transaction.TimeStamp.Ticks); writer.Write(transaction.Data.Length); writer.Write(transaction.Data); writer.Write(transaction.Offset); writer.Write(transaction.Id); writer.Write(transaction.DelayInMilliseconds); writer.Write(EndMarker); var newPosition = _transactionLog.Position; writer.Seek(0, SeekOrigin.Begin); writer.Write(newPosition); _lastOffset = newPosition; writer.Flush(); _transactionLog.Seek(_lastOffset, SeekOrigin.Begin); _transactionQueue.Enqueue(transaction); _queueNotEmpty.Set(); Dbg.Trace("new durable transaction in transaction log"); } }
private void StopServers() { foreach (var serverInfo in _servers) { Dbg.Trace("begin channel stop "); serverInfo.Channel.Stop(); Dbg.Trace("end channel stop "); Dbg.Trace("begin server stop "); serverInfo.Server.Stop(); Dbg.Trace("end server stop "); } }
// Executes a query with a collection result. public IEnumerable <T> ExecuteCollection <T>(QueryModel queryModel) { var visitor = new QueryVisitor(_collectionName, _collectionSchema); visitor.VisitQueryModel(queryModel); var expression = visitor.RootExpression; _customAction?.Invoke(expression); Dbg.Trace($"linq provider produced expression {expression}"); return(_client.GetMany(visitor.RootExpression, _sessionId).Select(ri => FromJObject <T>(ri.Item))); }
// Executes a query with a collection result. public IEnumerable <T> ExecuteCollection <T>(QueryModel queryModel) { var visitor = new QueryVisitor(_typeDescription); visitor.VisitQueryModel(queryModel); var expression = visitor.RootExpression; _customAction?.Invoke(expression); Dbg.Trace($"linq provider produced expression {expression}"); return(_client.GetMany <T>(visitor.RootExpression)); }
void FixedUpdate() { if (!m_PhotonView.isMine) { return; } float heightCommandCompensated = 0; float heightFeedforwardCompensated = 0; Vector3 anglesCommand = Vector3.zero; switch (heightControl) { case ControlMode.Stabilized: heightFeedforwardCompensated = applyAngleCompensation(heightFeedforward); heightCommandCompensated = applyAngleCompensation(controlVerticalSpeed()); break; case ControlMode.Manual: heightFeedforwardCompensated = heightFeedforward + controlThrottle(); heightCommandCompensated = 0; break; } switch (anglesControl) { case ControlMode.Stabilized: anglesCommand = controlAngles(); break; case ControlMode.Manual: anglesCommand = controlRates(); break; } propellersController.MixRPM(heightFeedforwardCompensated, heightCommandCompensated, anglesCommand.x, anglesCommand.y, anglesCommand.z); // Dbg.Trace (rb.angularVelocity.ToString()); Vector3 f = propellersController.getTotalForce(); Vector3 t = propellersController.getTotalTorque(); rb.AddRelativeForce(f); rb.AddRelativeTorque(t); Dbg.Trace(string.Format("{0:0.0000000}, {1:0.0000000}, {2:0.0000000}, {3:0.0000000}, {4:0.0000000}, {5:0.0000000}, " + "{6:0.0000000}, {7:0.0000000}, {8:0.0000000}, {9:0.0000000}, {10:0.0000000}, {11:0.0000000}, " + "{12:0.0000000}, {13:0.0000000}, {14:0.0000000}, {15:0.0000000}, {16:0.0000000}, {17:0.0000000}", transform.eulerAngles.z, transform.eulerAngles.x, transform.eulerAngles.y, rollRef, pitchRef, yawRef, -rb.angularVelocity.z, -rb.angularVelocity.x, rb.angularVelocity.y, angularRatesRef.x, angularRatesRef.y, angularRatesRef.z, -t.z, -t.x, t.y, rb.velocity.y, verticalSpeedRef, f.y)); acceleration = transform.rotation * f / rb.mass - 9.81f * Vector3.up; }
private bool AcquireWriteLock(IClient client, List <string> types, string transactionId) { var result = true; foreach (var type in types) { if (!DataStores[type].Lock.TryEnterWriteLock(Constants.DelayForLock)) { result = false; break; } } if (result) { Dbg.Trace($"S: Locks acquired on server {ShardIndex} transaction {transactionId}"); //client.SendResponse(new ReadyResponse()); var answer = client.ShouldContinue(); if (answer.HasValue && answer.Value) { Dbg.Trace( $"S: all clients acquired locks. Continue on server {ShardIndex} transaction {transactionId}"); return(true); } } Dbg.Trace($"S: Not all clients acquired locks on server {ShardIndex} transaction {transactionId}."); // first unlock everything to avoid deadlocks foreach (var type in types) { if (DataStores[type].Lock.IsWriteLockHeld) { DataStores[type].Lock.ExitWriteLock(); } } Dbg.Trace($"S: Release all locks on server {ShardIndex} transaction {transactionId}."); client.SendResponse(new ExceptionResponse( new CacheException( $"can not acquire write lock on server {ShardIndex} for transaction {transactionId}"), ExceptionType.FailedToAcquireLock)); return(false); }
private void SaveDurableTransaction(TransactionRequest transactionRequest, SafeDictionary <string, DataStore> dataStores) { // get the items to delete from the DeleteManyRequests var itemsToDelete = new HashSet <PackedObject>(); var deleteManyRequests = transactionRequest.ChildRequests.Where(r => r is RemoveManyRequest) .Cast <RemoveManyRequest>().ToList(); foreach (var deleteManyRequest in deleteManyRequests) { var ds = dataStores[deleteManyRequest.CollectionName]; var items = new QueryManager(ds).ProcessQuery(deleteManyRequest.Query); foreach (var item in items) { itemsToDelete.Add(item); } } // add items to delete explicitly foreach (var remove in transactionRequest.ChildRequests.Where(r => r is RemoveRequest) .Cast <RemoveRequest>()) { var collectionName = remove.CollectionName; if (dataStores[collectionName].DataByPrimaryKey.TryGetValue(remove.PrimaryKey, out var item)) { itemsToDelete.Add(item); } } // get items to put (conditions have already been checked) var itemsToPut = transactionRequest.ChildRequests.Where(r => r is PutRequest).Cast <PutRequest>() .SelectMany(r => r.Items).ToList(); Dbg.Trace($"S: begin writing delayed transaction {transactionRequest.TransactionId}"); _transactionLog?.NewTransaction(new MixedDurableTransaction { ItemsToDelete = itemsToDelete.ToList(), ItemsToPut = itemsToPut }, true ); }
// Executes a query with a scalar result, i.e. a query that ends with a result operator such as Count, Sum, or Average. public T ExecuteScalar <T>(QueryModel queryModel) { var visitor = new QueryVisitor(_typeDescription); visitor.VisitQueryModel(queryModel); var expression = visitor.RootExpression; _customAction?.Invoke(expression); Dbg.Trace($"linq provider produced expression {expression}"); if (expression.CountOnly) { return((T)(object)_client.EvalQuery(expression).Value); } throw new NotSupportedException("Only Count scalar method is implemented"); }
public void Process(byte[] data) { var item = SerializationHelper.ObjectFromBytes <CachedObject>(data, SerializationMode.ProtocolBuffers, false); Dbg.Trace($"processing persistent object {data.Length} bytes {item}"); if (!_temporaryStorage.TryGetValue(item.FullTypeName, out var list)) { list = new List <CachedObject>(); _temporaryStorage[item.FullTypeName] = list; } list.Add(item); if (!_dataContainer.DataStores.ContainsKey(item.FullTypeName)) { throw new NotSupportedException($"The type {item.FullTypeName} is not present in the database schema"); } }
public int LogIn(string ticketId, bool repeatAfterDeadlock = true) { using (DbManagerProxy manager = DbManagerFactory.Factory.Create(ModelUserContext.Instance)) { try { DataTable dt = manager.SetSpCommand("dbo.spLoginByTicket", manager.Parameter("@strTicket", ticketId), manager.Parameter("@intExpirationInterval", BaseSettings.TicketExpiration), manager.Parameter(ParameterDirection.Output, "@Result", 0) ).ExecuteDataTable(); int res = Convert.ToInt32(manager.Parameter("@Result").Value); if (res == 0) { PerformLogin(dt); } m_LoginTry = 0; return(res); } catch (Exception e) { Dbg.Debug("login by ticket failed, error: {0}", e); Dbg.Trace(); m_LoginTry++; if (DbModelException.IsDeadlockException(e) && m_LoginTry < DedalockRepeatCount) { Debug.WriteLine("user login deadlock found"); return(LogIn(ticketId, m_LoginTry < DedalockRepeatCount - 1)); } var dataException = e as DataException; if (dataException != null) { m_LoginTry = 0; throw DbModelException.Create(null, dataException); } m_LoginTry = 0; throw; } } }
public void Process(byte[] data) { var item = SerializationHelper.ObjectFromBytes <PackedObject>(data, SerializationMode.ProtocolBuffers, false); // the json itself may be compressed, but the persisted object is never compressed Dbg.Trace($"processing persistent object {data.Length} bytes {item}"); if (!_temporaryStorage.TryGetValue(item.CollectionName, out var list)) { list = new List <PackedObject>(); _temporaryStorage[item.CollectionName] = list; } list.Add(item); var store = _dataContainer.TryGetByName(item.CollectionName); if (store == null) { throw new NotSupportedException($"The type {item.CollectionName} is not present in the database schema"); } }
public void EndProcess(string dataPath = null) { HashSet <string> frequentTokens = new HashSet <string>(); foreach (var pair in _temporaryStorage) { var store = _dataContainer.DataStores[pair.Key]; store.InternalPutMany(pair.Value, true, null); frequentTokens.UnionWith(store.GetMostFrequentTokens(100)); } // generate a helper file containing most frequent tokens if (dataPath != null && frequentTokens.Count > 0) { File.WriteAllLines(Path.Combine(dataPath, "Most_frequent_tokens.txt"), frequentTokens); } _temporaryStorage.Clear(); Dbg.Trace("done loading persistent objects into memory"); }
public void Stop() { try { Dbg.Trace("before _listener.Server.Disconnect();"); _listener.Server.Disconnect(false); Dbg.Trace("after _listener.Server.Disconnect();"); //_listener.Stop(); } catch (Exception) { // ignore } finally { Dbg.Trace("before _listener.Server.Close();"); _listener.Server.Close(); Dbg.Trace("after _listener.Server.Close();"); } }
private void ProcessSingleStageTransactionRequest(TransactionRequest transactionRequest, IClient client, SafeDictionary <string, DataStore> dataStores) { var types = transactionRequest.AllCollections; _lockManager.DoWithWriteLock(() => { try { Dbg.Trace($"S: fallback to single stage for transaction {transactionRequest.TransactionId}"); // check the conditions (in case of conditional update) CheckConditions(transactionRequest, dataStores); SaveDurableTransaction(transactionRequest, dataStores); // update the data in memory ExecuteInMemory(transactionRequest, dataStores); client.SendResponse(new NullResponse()); Dbg.Trace($"S: end writing delayed transaction {transactionRequest.TransactionId}"); } catch (CacheException e) { client.SendResponse(new ExceptionResponse(e, e.ExceptionType)); } catch (Exception e) { Dbg.Trace($"error writing delayed transaction:{e.Message}"); client.SendResponse(new ExceptionResponse(e)); // failed to write a durable transaction so stop here } }, types); }
private void ProcessSingleStageTransactionRequest(TransactionRequest transactionRequest, IClient client) { var typesToPut = transactionRequest.ItemsToPut.Select(i => i.FullTypeName).Distinct().ToList(); var typesToDelete = transactionRequest.ItemsToDelete.Select(i => i.FullTypeName).Distinct().ToList(); var types = typesToPut.Union(typesToDelete).Distinct(); try { foreach (var type in types) { if (!DataStores[type].Lock.TryEnterWriteLock(Constants.DelayForLock)) { throw new CacheException("Failed to acquire write locks for single-stage transaction", ExceptionType.FailedToAcquireLock); } } Dbg.Trace($"S: fallback to single stage for transaction {transactionRequest.TransactionId}"); // check the conditions (in case of conditional update) int index = 0; foreach (var condition in transactionRequest.Conditions) { if (!condition.IsEmpty()) { var ds = DataStores[condition.TypeName]; ds.CheckCondition(transactionRequest.ItemsToPut[index].PrimaryKey, condition); } index++; } PersistenceEngine?.NewTransaction(new MixedTransaction { ItemsToDelete = transactionRequest.ItemsToDelete, ItemsToPut = transactionRequest.ItemsToPut } ); // update the data in memory var dataRequests = transactionRequest.SplitByType(); foreach (var dataRequest in dataRequests) { if (!DataStores.ContainsKey(dataRequest.FullTypeName)) { throw new NotSupportedException($"The type {dataRequest.FullTypeName} is not registered"); } DataStores[dataRequest.FullTypeName].ProcessRequest(dataRequest, client, null); } client.SendResponse(new NullResponse()); Dbg.Trace($"S: end writing delayed transaction {transactionRequest.TransactionId}"); } catch (CacheException e) { client.SendResponse(new ExceptionResponse(e, e.ExceptionType)); } catch (Exception e) { Dbg.Trace($"error writing delayed transaction:{e.Message}"); client.SendResponse(new ExceptionResponse(e)); // failed to write a durable transaction so stop here } finally { // release acquired locks foreach (var type in types) { if (DataStores[type].Lock.IsWriteLockHeld) { DataStores[type].Lock.ExitWriteLock(); } } } }
public void FeedMany(string collectionName, IEnumerable <PackedObject> items, bool excludeFromEviction, int packetSize = 50000) { if (items == null) { throw new ArgumentNullException(nameof(items)); } var sessionId = Guid.NewGuid(); // initialize one request per node var requests = new PutRequest[CacheClients.Count]; // Parallelize both nodes and requests (multiple requests for the same node are executed in parallel if multiple connections are available in the pool) var tasks = new List <Task>(); foreach (var item in items) { var node = WhichNode(item); if (requests[node] == null) { requests[node] = new PutRequest(collectionName) { ExcludeFromEviction = excludeFromEviction, SessionId = sessionId } } ; var request = requests[node]; request.Items.Add(item); if (request.Items.Count == packetSize) { var task = Task.Factory.StartNew(re => { var put = (PutRequest)re; var split = put.SplitWithMaxSize(); foreach (var putRequest in split) { var response = CacheClients[node].Channel.SendRequest(putRequest); if (response is ExceptionResponse exResponse) { throw new CacheException( "Error while writing an object to the cache", exResponse.Message, exResponse.CallStack); } } }, request); tasks.Add(task); requests[node] = new PutRequest(collectionName) { ExcludeFromEviction = excludeFromEviction, SessionId = sessionId }; } } //send the last packet left for each node for (var node = 0; node < CacheClients.Count; node++) { var request = requests[node]; if (request != null) { request.EndOfSession = true; var n = node; var task = Task.Factory.StartNew(re => { var response = CacheClients[n].Channel.SendRequest((PutRequest)re); if (response is ExceptionResponse exResponse) { throw new CacheException( "Error while writing an object to the cache", exResponse.Message, exResponse.CallStack); } }, request); tasks.Add(task); } } try { Task.WaitAll(tasks.ToArray()); Dbg.Trace($"{tasks.Count} tasks finished"); } catch (AggregateException e) { if (e.InnerException != null) { throw e.InnerException; } } }
public IPersistentTransaction StartProcessing() { _queueNotEmpty.WaitOne(); if (_disposed) { return(null); // to avoid a race condition between the disposal of consumer and the log } Dbg.Trace("start processing transaction from transaction log"); // the event was set during dispose to unlock the consumer if (_transactionQueue.Count == 0) { return(null); } TransactionData data; lock (_syncRoot) { if (_transactionQueue.Count == 0) { return(null); } data = _transactionQueue.Peek(); } // if it is a delayed transaction wait until it is valid if (data.DelayInMilliseconds != 0) { Dbg.Trace("processing delayed transaction"); var millisecondsToWait = data.DelayInMilliseconds - (int)(DateTime.Now - data.TimeStamp).TotalMilliseconds; if (millisecondsToWait > 0 && data.TransactionStatus != TransactionStaus.Canceled) { Dbg.Trace($"waiting {millisecondsToWait} ms for delayed transaction to become active"); SmartSleep(millisecondsToWait); } } // if canceled do not process if (data.TransactionStatus == TransactionStaus.Canceled) { Dbg.Trace("delayed transaction was canceled"); return(null); } if (data.TransactionStatus != TransactionStaus.ToProcess) { Dbg.Trace("Incomplete transaction found. Reprocessing"); } lock (_syncRoot) { data.TransactionStatus = TransactionStaus.Processing; UpdateTransactionStatus(data); } Dbg.Trace("processing delayed transaction after delay has passed"); return(data); }