public static void Execute(SecurityActivity activity) { if (!_enabled) { return; } SecurityActivityHistory.Start(activity.Id); try { using (var op = SnTrace.SecurityQueue.StartOperation("SAQ: EXECUTION START SA{0} .", activity.Id)) { activity.ExecuteInternal(); op.Successful = true; } } catch (Exception e) { SnTrace.Security.Write("SAQ: EXECUTION ERROR SA{0}: {1}", activity.Id, e.Message); SecurityActivityHistory.Error(activity.Id, e); } finally { DependencyManager.Finish(activity); } }
/// <summary> /// Ensures an exclusive (only one) object for the activity. Returns the new lock object or null. /// </summary> public SecurityActivityExecutionLock AcquireSecurityActivityExecutionLock( SecurityActivity securityActivity, int timeoutInSeconds) { var maxTime = timeoutInSeconds == int.MaxValue ? DateTime.MaxValue : DateTime.UtcNow.AddSeconds(timeoutInSeconds); while (DateTime.UtcNow < maxTime) { string result; using (var db = Db()) result = db.AcquireSecurityActivityExecutionLock( securityActivity.Id, securityActivity.Context.MessageProvider.ReceiverName, timeoutInSeconds); // ReSharper disable once SwitchStatementMissingSomeCases switch (result) { case ExecutionState.LockedForYou: // enable full executing return(new SecurityActivityExecutionLock(securityActivity, true)); case ExecutionState.Executing: case ExecutionState.Done: // enable partially executing return(new SecurityActivityExecutionLock(securityActivity, false)); } } throw new SecurityActivityTimeoutException( $"Waiting for a SecurityActivityExecutionLock timed out: #{securityActivity.Id}/{securityActivity.TypeName}"); }
internal static void ReleaseSecurityActivityExecutionLock(SecurityActivity securityActivity, bool fullExecutionEnabled) { if (fullExecutionEnabled) { securityActivity.Context.DataProvider.ReleaseSecurityActivityExecutionLock(securityActivity); } }
internal void SaveActivity(SecurityActivity activity) { var id = _dataProvider.SaveSecurityActivity(activity, out var bodySize); activity.BodySize = bodySize; activity.Id = id; }
internal static void Finish(SecurityActivity activity) { lock (_waitingSetLock) { // activity is done in the ActivityQueue _waitingSet.Remove(activity); // terminate and release waiting threads if there is any. activity.Finish(); // register activity termination in the log. SecurityActivityHistory.Finish(activity.Id); // register activity termination. TerminationHistory.FinishActivity(activity); // execute all activities that are completely freed. foreach (var dependentItem in activity.WaitingForMe.ToArray()) { dependentItem.FinishWaiting(activity); if (dependentItem.WaitingFor.Count == 0) { Task.Run(() => Executor.Execute(dependentItem)); } } } }
public static void EnqueueActivity(SecurityActivity activity) { SnTrace.SecurityQueue.Write("SAQ: SA{0} arrived{1}. {2}", activity.Id, activity.FromReceiver ? " from another computer" : "", activity.TypeName); SecurityActivityHistory.Arrive(activity); lock (_arrivalQueueLock) { if (activity.Id <= _lastQueued) { var sameActivity = _arrivalQueue.FirstOrDefault(a => a.Id == activity.Id); if (sameActivity != null) { sameActivity.Attach(activity); SnTrace.SecurityQueue.Write("SAQ: SA{0} attached to another one in the queue", activity.Id); return; } DependencyManager.AttachOrFinish(activity); return; } if (activity.Id > _lastQueued + 1) { //var loadedActivities = LoadActivities(_lastQueued + 1, activity.Id - 1); var from = _lastQueued + 1; var to = activity.Id - 1; var expectedCount = to - from + 1; var loadedActivities = Retrier.Retry( 3, 100, () => LoadActivities(from, to), (r, i, e) => { if (i < 3) { SnTrace.SecurityQueue.Write("SAQ: Loading attempt {0}", 4 - i); } if (e != null) { return(false); } return(r.Count() == expectedCount); }); foreach (var loadedActivity in loadedActivities) { SecurityActivityHistory.Arrive(loadedActivity); _arrivalQueue.Enqueue(loadedActivity); _lastQueued = loadedActivity.Id; SnTrace.SecurityQueue.Write("SAQ: SA{0} enqueued from db.", loadedActivity.Id); DependencyManager.ActivityEnqueued(); } } _arrivalQueue.Enqueue(activity); _lastQueued = activity.Id; SnTrace.SecurityQueue.Write("SAQ: SA{0} enqueued.", activity.Id); DependencyManager.ActivityEnqueued(); } }
internal static void SaveActivity(SecurityActivity activity) { int bodySize; var id = activity.Context.DataProvider.SaveSecurityActivity(activity, out bodySize); activity.BodySize = bodySize; activity.Id = id; }
public static void ExecuteActivity(SecurityActivity activity) { if (!activity.FromDatabase && !activity.FromReceiver) { DataHandler.SaveActivity(activity); } Serializer.EnqueueActivity(activity); }
public int SaveSecurityActivity(SecurityActivity activity, out int bodySize) { lock (_messageLock) { var id = Interlocked.Increment(ref _lastActivityId); var body = SecurityActivity.SerializeActivity(activity); bodySize = body.Length; _storage.Messages.Add(new Tuple <int, DateTime, byte[]>(id, DateTime.UtcNow, body)); return(id); } }
/// <summary> /// Initializes a new instance of the SecurityActivityExecutionLock /// </summary> /// <param name="activity">Activity that is locked.</param> /// <param name="fullExecutionEnabled">If true, all activity operation must be executed: /// storing, distributing, applying in the memory. Otherwise only the memor operations are allowed.</param> public SecurityActivityExecutionLock(SecurityActivity activity, bool fullExecutionEnabled) { _activity = activity; FullExecutionEnabled = fullExecutionEnabled; var interval = Configuration.SecurityActivityExecutionLockRefreshPeriodInSeconds * 1000.0; _timer = new Timer(interval) { Enabled = true }; _timer.Elapsed += Refresh; _timer.Disposed += Refresh; }
internal static void Wait(SecurityActivity activity) { lock (_lock) { foreach (var item in _history) { if (item != null && item.Id == activity.Id) { item.WaitedFor = activity.WaitingFor.Select(a => a.Id).ToArray(); break; } } } }
public virtual SecurityActivity LoadSecurityActivity(int id) { lock (_messageLock) { var item = _storage.Messages.Where(x => x.Item1 == id).FirstOrDefault(); if (item == null) { return(null); } var activity = SecurityActivity.DeserializeActivity(item.Item3); activity.Id = item.Item1; return(activity); } }
/// <summary> /// Returns a SecurityActivity. /// </summary> public SecurityActivity LoadSecurityActivity(int id) { using (var db = Db()) { var item = db.EFMessages.FirstOrDefault(x => x.Id == id); if (item == null) { return(null); } var activity = SecurityActivity.DeserializeActivity(item.Body); activity.Id = item.Id; return(activity); } }
internal static void AttachOrFinish(SecurityActivity activity) { lock (_waitingSetLock) { var sameActivity = _waitingSet.FirstOrDefault(a => a.Id == activity.Id); if (sameActivity != null) { sameActivity.Attach(activity); SnTrace.SecurityQueue.Write("SAQ: SA{0} attached to another in the waiting set.", activity.Id); return; } } activity.Finish(); // release blocked thread SecurityActivityHistory.Finish(activity.Id); SnTrace.SecurityQueue.Write("SAQ: SA{0} ignored: finished but not executed.", activity.Id); }
public byte[] SerializeActivity(SecurityActivity activity) { try { var ms = new MemoryStream(); var bf = new BinaryFormatter(); bf.Serialize(ms, activity); ms.Flush(); ms.Position = 0; return(ms.GetBuffer()); } catch (Exception e) // logged and rethrown { SnLog.WriteException(e, EventMessage.Error.Serialization, EventId.Serialization); throw; } }
public SecurityActivity DeserializeActivity(byte[] bytes) { Stream data = new MemoryStream(bytes); var bf = new BinaryFormatter(); SecurityActivity activity = null; try { activity = (SecurityActivity)bf.Deserialize(data); activity.Context = _securitySystem.GeneralSecurityContext; } catch (SerializationException e) // logged { SnLog.WriteException(e, EventMessage.Error.Deserialization, EventId.Serialization); } return(activity); }
/// <summary> /// Stores the full data of the passed activity. /// Returns with the generated activity id and the size of the activity's body. /// Activity ids in the database must be a consecutive list of numbers. /// </summary> /// <param name="activity">Activity to save.</param> /// <param name="bodySize">Activity size in bytes.</param> /// <returns>The generated activity id.</returns> public int SaveSecurityActivity(SecurityActivity activity, out int bodySize) { var body = SecurityActivity.SerializeActivity(activity); bodySize = body.Length; EntityEntry <EFMessage> result; using (var db = Db()) { result = db.EFMessages.Add(new EFMessage { ExecutionState = ExecutionState.Wait, SavedBy = activity.Context.MessageProvider.ReceiverName, SavedAt = DateTime.UtcNow, Body = body }); db.SaveChanges(); } return(result.Entity.Id); }
internal static void Arrive(SecurityActivity activity) { lock (_lock) { // avoiding duplication foreach (var item in _history) { if (item != null && item.Id == activity.Id) { return; } } var retired = _history[_position]; _history[_position] = new SecurityActivityHistoryItem { Id = activity.Id, TypeName = activity.TypeName, FromReceiver = activity.FromReceiver, FromDb = activity.FromDatabase, IsStartup = activity.IsUnprocessedActivity, ArrivedAt = DateTime.UtcNow, StartedAt = DateTime.MinValue, FinishedAt = DateTime.MinValue }; if (retired != null) { if (retired.FinishedAt == DateTime.MinValue) { _unfinished++; } } _position++; if (_position >= HistoryLength) { _position = 0; } } }
/// <summary> /// Loads a SecurityActivity fragment by the individual id array. /// Activities in the result array are sorted by id. /// Value of the IsUnprocessedActivity property of every loaded object /// vill be the value of the given "executingUnprocessedActivities" parameter. /// </summary> /// <param name="gaps">Individual id array</param> /// <param name="executingUnprocessedActivities"> /// Value of the IsUnprocessedActivity property of every loaded object.</param> public SecurityActivity[] LoadSecurityActivities(int[] gaps, bool executingUnprocessedActivities) { var result = new List <SecurityActivity>(); using (var db = Db()) { foreach (var item in db.EFMessages.Where(x => gaps.Contains(x.Id)).OrderBy(x => x.Id)) { var activity = SecurityActivity.DeserializeActivity(item.Body); if (activity == null) { continue; } activity.Id = item.Id; activity.FromDatabase = true; activity.IsUnprocessedActivity = executingUnprocessedActivities; result.Add(activity); } } return(result.ToArray()); }
internal static void FinishActivity(SecurityActivity activity) { var id = activity.Id; lock (_gapsLock) { if (id > _lastId) { if (id > _lastId + 1) { _gaps.AddRange(Enumerable.Range(_lastId + 1, id - _lastId - 1)); } _lastId = id; } else { _gaps.Remove(id); } SnTrace.SecurityQueue.Write("SAQ: State after finishing SA{0}: {1}", id, GetCurrentState()); } }
public SecurityActivity[] LoadSecurityActivities(int[] gaps, bool executingUnprocessedActivities) { lock (_messageLock) { var result = new List <SecurityActivity>(); foreach (var item in _storage.Messages.Where(x => gaps.Contains(x.Item1))) { var activity = SecurityActivity.DeserializeActivity(item.Item3); if (activity == null) { continue; } activity.Id = item.Item1; activity.FromDatabase = true; activity.IsUnprocessedActivity = executingUnprocessedActivities; result.Add(activity); } return(result.ToArray()); } }
public SecurityActivity[] LoadSecurityActivities(int from, int to, int count, bool executingUnprocessedActivities) { lock (_messageLock) { var result = new List <SecurityActivity>(); foreach (var item in _storage.Messages.Where(x => x.Item1 >= from && x.Item1 <= to).Take(count)) { var activity = SecurityActivity.DeserializeActivity(item.Item3); if (activity == null) { continue; } activity.Id = item.Item1; activity.FromDatabase = true; activity.IsUnprocessedActivity = executingUnprocessedActivities; result.Add(activity); } return(result.ToArray()); } }
private static void MessageProvider_MessageReceived(object sender, MessageReceivedEventArgs args) { var message = args.Message; // debug game if (message is PingMessage) { _messageProvider.SendMessage(new PongMessage()); return; } SecurityActivity activity = null; // load from database if it was too big to distribute var bigActivityMessage = message as BigActivityMessage; if (bigActivityMessage != null) { activity = DataHandler.LoadBigSecurityActivity(bigActivityMessage.DatabaseId); if (activity == null) { SnTrace.Security.WriteError("Cannot load body of a BigActivity. Id: {0}", bigActivityMessage.DatabaseId); } } // trying to interpret if (activity == null) { activity = message as SecurityActivity; } // Apply if everything is good if (activity != null) { activity.FromReceiver = true; SecurityActivity.Apply(activity); } }
private static void MakeDependencies(SecurityActivity newerActivity) { lock (_waitingSetLock) { foreach (var olderActivity in _waitingSet) { Debug.Assert(olderActivity.Id != newerActivity.Id); if (newerActivity.MustWaitFor(olderActivity)) { newerActivity.WaitFor(olderActivity); SnTrace.SecurityQueue.Write("SAQ: SA{0} depends from SA{1}", newerActivity.Id, olderActivity.Id); SecurityActivityHistory.Wait(newerActivity); } } _waitingSet.Add(newerActivity); if (newerActivity.WaitingFor.Count == 0) { Task.Run(() => Executor.Execute(newerActivity)); } } }
public void RefreshSecurityActivityExecutionLock(SecurityActivity securityActivity) { // do nothing }
internal static void RefreshSecurityActivityExecutionLock(SecurityActivity securityActivity) { securityActivity.Context.DataProvider.RefreshSecurityActivityExecutionLock(securityActivity); }
internal static Messaging.SecurityActivityExecutionLock AcquireSecurityActivityExecutionLock(SecurityActivity securityActivity) { var timeout = Debugger.IsAttached ? int.MaxValue : Configuration.SecurityActivityExecutionLockTimeoutInSeconds; return(securityActivity.Context.DataProvider .AcquireSecurityActivityExecutionLock(securityActivity, timeout)); }
internal override bool MustWaitFor(SecurityActivity olderActivity) { return(false); }
public void ReleaseSecurityActivityExecutionLock(SecurityActivity securityActivity) { // do nothing }
public Messaging.SecurityActivityExecutionLock AcquireSecurityActivityExecutionLock(SecurityActivity securityActivity, int timeoutInSeconds) { return(new Messaging.SecurityActivityExecutionLock(securityActivity, true)); }