internal MySqlDistributedLock Acquire() { Logger.TraceFormat("Acquire resource={0}, timeout={1}", _resource, _timeout); int insertedObjectCount; do { _cancellationToken.ThrowIfCancellationRequested(); var timeLeft = _start.Add(_timeout).Subtract(DateTime.UtcNow); using (ResourceLock.AcquireOne( _connection, _storageOptions.TablesPrefix, timeLeft, _cancellationToken, LockableResource.Lock)) { insertedObjectCount = AcquireLock(); } if (ContinueCondition(insertedObjectCount)) { _cancellationToken.WaitHandle.WaitOne(DelayBetweenPasses); _cancellationToken.ThrowIfCancellationRequested(); } } while (ContinueCondition(insertedObjectCount)); if (insertedObjectCount == 0) { throw new MySqlDistributedLockException("cannot acquire lock"); } return this; }
protected ResourceLockDelegator(ResourceLock resLock) : this(resLock, resLock.ResourceLockOptions) { Contract.Requires(resLock != null); Contract.Ensures(InnerLock != null); Contract.Assert(m_resLock != null); }
/// <summary> /// Constructs a RecursionResourceLockModifier object. /// </summary> /// <param name="resLock">A reference to a ResourceLock object that will not support recursion.</param> /// <param name="maxReaders">The maximum number of concurrent reader threads that this /// RecursionResourceLockModifier object should support.</param> public RecursionResourceLockModifier(ResourceLock resLock, Int32 maxReaders) : base(resLock, ResourceLockOptions.AcquiringThreadMustRelease | ResourceLockOptions.SupportsRecursion | (resLock.IsMutualExclusive ? ResourceLockOptions.IsMutualExclusive : 0)) { Contract.Requires(resLock != null); Contract.Requires(maxReaders >= 0); m_ReaderThreadIdsAndRecurseCounts = new ThreadIdAndRecurseCount[maxReaders]; }
public TextFileWriter(String fileName, Boolean append, Boolean forceDirectoryCreation) { Disposed = false; LogFilePath = RIUtils.DetermineParameterPath(fileName); Append = append; CreateDirectory = forceDirectoryCreation; FResourceLock = new ResourceLock(fileName); }
/// <summary> /// Constructs a RecursionResourceLockModifier object. /// </summary> /// <param name="resLock">A reference to a ResourceLock object that will not support recursion.</param> /// <param name="maxReaders">The maximum number of concurrent reader threads that this /// RecursionResourceLockModifier object should support.</param> public RecursionResourceLockModifier(ResourceLock resLock, Int32 maxReaders) : base(resLock, ResourceLockOptions.AcquiringThreadMustRelease | ResourceLockOptions.SupportsRecursion | (resLock.IsMutualExclusive ? ResourceLockOptions.IsMutualExclusive : 0)) { Contract.Requires(resLock != null); Contract.Requires(maxReaders >= 0); m_ReaderThreadIdsAndRecurseCounts = new ThreadIdAndRecurseCount[maxReaders]; }
public ResourceLock TryAcquireRead() { if (_lock.TryEnterReadLock(0)) { return(ResourceLock.Reader(this)); } return(null); }
internal MySqlConnection CreateAndOpenConnection() { var connection = new MySqlConnection(_connectionString); connection.Open(); ResourceLock.ReleaseAll(connection); return(connection); }
public ThreadBlockInfo(ResourceLock lockObject, Boolean acquiringExclusively) : this(lockObject, (lockObject.AcquiringThreadMustRelease ? ResourceLockOptions.AcquiringThreadMustRelease : 0) | (lockObject.SupportsRecursion ? ResourceLockOptions.SupportsRecursion : 0) | (acquiringExclusively ? ResourceLockOptions.IsMutualExclusive : 0)) { }
private int AggregateCounter(MySqlConnection connection) { using (ResourceLock.AcquireOne( connection, _options.TablesPrefix, LockableResource.Counter)) { return(connection.Execute( GetAggregationQuery(), new { now = DateTime.UtcNow, count = NumberOfRecordsInSinglePass })); } }
protected ResourceLockDelegator(ResourceLock resLock, ResourceLockOptions resourceLockOptions) : base(resourceLockOptions) { Contract.Requires(resLock != null); Contract.Ensures(InnerLock != null); m_resLock = resLock; #if DEADLOCK_DETECTION m_resLock.ImmuneFromDeadlockDetection = true; // The outerlock is used for deadlock detection; not the inner lock #endif Contract.Assert(m_resLock != null); }
protected ResourceLockDelegator(ResourceLock resLock, ResourceLockOptions resourceLockOptions) : base(resourceLockOptions) { Contract.Requires(resLock != null); Contract.Ensures(InnerLock != null); m_resLock = resLock; #if DEADLOCK_DETECTION m_resLock.ImmuneFromDeadlockDetection = true; // The outerlock is used for deadlock detection; not the inner lock #endif Contract.Assert(m_resLock != null); }
// Called by a thread when it is about to wait on a lock private IDisposable BlockForLockI(ResourceLock lockObject, Boolean acquiringExclusively) { // Some ResourceLock-derived types are ignored (like NullResourceLock) if (lockObject.ImmuneFromDeadlockDetection) { return(null); } // Create record indicating what the calling thread is waiting on and add to waiting threads list BlockThreadAndCheckDeadlock(new ThreadBlockInfo(lockObject, acquiringExclusively)); return(m_UnblockDueToLockAcquireDisposer); }
public IFetchedJob Dequeue(string[] queues, CancellationToken cancellationToken) { if (queues is null || !queues.Any()) { throw new ArgumentException("Queue array must be non-empty.", nameof(queues)); } var token = Guid.NewGuid().ToString(); // I'm not sure if this is used correctly... var expiration = _options.InvisibilityTimeout; // the connection variable is mutable, it job is claimed then this connection // is passed to job itself, and variable is set to null so it does not get // disposed here in such case var connection = _storage.CreateAndOpenConnection(); try { while (true) { cancellationToken.ThrowIfCancellationRequested(); using (ResourceLock.AcquireOne( connection, _options.TablesPrefix, LockableResource.Queue)) { var updated = ClaimJob(connection, queues, expiration, token); if (updated != 0) { var fetchedJob = FetchJobByToken(connection, token); return(new MySqlFetchedJob( _storage, _options, Interlocked.Exchange(ref connection, null), fetchedJob)); } } cancellationToken.WaitHandle.WaitOne(_options.QueuePollInterval); cancellationToken.ThrowIfCancellationRequested(); } } catch (MySqlException ex) { Logger.ErrorException(ex.Message, ex); throw; } finally { if (connection != null) { _storage.ReleaseConnection(connection); } } }
public void RemoveFromQueue() { Logger.TraceFormat("RemoveFromQueue JobId={0}", JobId); using (ResourceLock.AcquireOne( _connection, _options.TablesPrefix, LockableResource.Queue)) { _connection.Execute( $"delete from `{_options.TablesPrefix}JobQueue` where Id = @id", new { id = _id }); } _removed = true; }
public void Requeue() { Logger.TraceFormat("Requeue JobId={0}", JobId); using (ResourceLock.AcquireOne( _connection, _options.TablesPrefix, LockableResource.Queue)) { _connection.Execute( $"update `{_options.TablesPrefix}JobQueue` set FetchedAt = null where Id = @id", new { id = _id }); } _requeued = true; }
private async Task HandleCommandAsync(SocketMessage messageParam) { // Don't process the command if it was a system message var message = messageParam as SocketUserMessage; if (message == null) { return; } // Create a number to track where the prefix ends and the command begins int argPos = 0; // Determine if the message is a command based on the prefix and make sure no bots trigger commands if (!(message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos)) || message.Author.IsBot) { return; } // Create a WebSocket-based command context based on the message var context = new CustomCommandContext(_client, message); #if !DEBUG // We try to lock the channel so that only one Discord Client instance handles the message if (!await ResourceLock.AcquireLock(messageParam.Channel.Id.ToString())) { // If we didn't manage to acquire the lock, we don't do a thing, another client should already be working on it this._telemetryClient.TrackTrace($"Lock failed on channel {messageParam.Channel.Id} ({messageParam.Channel.Name})", SeverityLevel.Information); return; } #endif // Execute the command with the command context we just // created, along with the service provider for precondition checks. // Keep in mind that result does not indicate a return value // rather an object stating if the command executed successfully. var result = await _commands.ExecuteAsync( context : context, argPos : argPos, services : this._serviceProvider); // Optionally, we may inform the user if the command fails // to be executed; however, this may not always be desired, // as it may clog up the request queue should a user spam a // command. // if (!result.IsSuccess) // await context.Channel.SendMessageAsync(result.ErrorReason); }
internal void Release() { Logger.TraceFormat("Release resource={0}", _resource); using (ResourceLock.AcquireOne( _connection, _storageOptions.TablesPrefix, _timeout, CancellationToken.None, LockableResource.Lock)) { _connection.Execute( $"DELETE FROM `{_storageOptions.TablesPrefix}DistributedLock` " + "WHERE Resource = @resource", new { resource = _resource }); } }
public override void Commit() { _storage.UseTransaction(transaction => { using (ResourceLock.AcquireMany( transaction, _storageOptions.TablesPrefix, TimeSpan.FromSeconds(30), CancellationToken.None, _resources.ToArray())) { foreach (var command in _commandQueue) { command(transaction); } } }); }
private void Enqueue( IDbConnection connection, IDbTransaction transaction, string queue, string jobId) { Logger.TraceFormat("Enqueue JobId={0} Queue={1}", jobId, queue); using (ResourceLock.AcquireOne( connection, transaction, _options.TablesPrefix, LockableResource.Queue)) { connection.Execute( $@"/* MySqlJobQueue.Enqueue */ insert into `{_options.TablesPrefix}JobQueue` (JobId, Queue) values (@jobId, @queue)", new { jobId, queue }, transaction); } }
public void Dispose() { lock (this) { if (!Disposed) { Disposed = true; GC.SuppressFinalize(this); if (FResourceLock != null) { FResourceLock.Dispose(); FResourceLock = null; } } } }
public ExclusiveOwnerResourceLockHelper(ResourceLock resLock) { Contract.Requires(resLock != null); if (!resLock.IsMutualExclusive) throw new ArgumentException("resLock must identify a ResourceLock that is really a mutual-exclusive lock"); if (resLock.SupportsRecursion) throw new ArgumentException("resLock must identify a ResourceLock that does not support recursion"); m_owningThreadId = 0; // C# requires that all fields be assigned to before 'this' is used (when newing the Disposer objects) m_afterWaitDisposer = null; m_afterReleaseDisposer = null; m_afterWaitDisposer = new Disposer(AfterWait); m_afterReleaseDisposer = new Disposer(AfterRelease); }
private void ReleaseLockI(Object lockObject) { // Some ResourceLock-derived types are ignored (like NullResourceLock) ResourceLock rl = lockObject as ResourceLock; if ((rl != null) && rl.ImmuneFromDeadlockDetection) { return; } Int32 threadId = Thread.CurrentThread.ManagedThreadId; // The calling thread no longer owns this lock. lock (m_syncLock) { // Find the record representing the acquired lock being released Int32 index = m_AcquiredLocks.FindIndex(delegate(ThreadBlockInfo tli) { // If the lock doesn't have to be released by the owning thread, we have a match if (!tli.AcquiringThreadMustRelease) { return(true); } // Lock must be released by owning thread; we have a match if owning thread Id matches releasing thread Id return(tli.BlockedThreadId == threadId); }); // If not found, then we have an error if (index == -1) { throw new InvalidOperationException("This thread is trying to release a lock that is not owned"); } // Sanity check: Is the lock is a thread-owned lock, ensure that the thread releasing it is the owner if (m_AcquiredLocks[index].AcquiringThreadMustRelease && (m_AcquiredLocks[index].BlockedThreadId != Thread.CurrentThread.ManagedThreadId)) { throw new InvalidOperationException("This thread is trying to release a thread-owned lock that is owned by another thread"); } m_AcquiredLocks.RemoveAt(index); } }
public ExclusiveOwnerResourceLockHelper(ResourceLock resLock) { Contract.Requires(resLock != null); if (!resLock.IsMutualExclusive) { throw new ArgumentException("resLock must identify a ResourceLock that is really a mutual-exclusive lock"); } if (resLock.SupportsRecursion) { throw new ArgumentException("resLock must identify a ResourceLock that does not support recursion"); } m_owningThreadId = 0; // C# requires that all fields be assigned to before 'this' is used (when newing the Disposer objects) m_afterWaitDisposer = null; m_afterReleaseDisposer = null; m_afterWaitDisposer = new Disposer(AfterWait); m_afterReleaseDisposer = new Disposer(AfterRelease); }
/// <summary> /// Gets the specified name. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="name">The name.</param> /// <param name="bSlidingTimeWindow">if set to <c>true</c> [b sliding time window].</param> /// <param name="callback">The callback.</param> /// <param name="args">The arguments.</param> /// <returns></returns> /// <exception cref="System.ArgumentNullException">callback</exception> public T Get <T>(string name, bool bSlidingTimeWindow, Func <string, object[], CacheDataInfo <T> > callback = null, params object[] args) { var node = GetCachedNode(name, bSlidingTimeWindow); if (node == null) { if (callback == null) { return(default(T)); } using (var rLock = new ResourceLock(name)) { rLock.EnterWriteLock(); try { node = GetCachedNode(name, bSlidingTimeWindow); if (node == null) { var cData = callback(name, args); if (cData == null) { return(default(T)); } Set(name, cData.NewCacheData, cData.KeepAlive); return(cData.NewCacheData); } } finally { rLock.ExitWriteLock(); } } } return((T)node.Data); }
public static void Upgrade(MySqlConnection connection, string tablesPrefix = null) { if (connection == null) { throw new ArgumentNullException(nameof(connection)); } var prefix = tablesPrefix ?? string.Empty; using (ResourceLock.AcquireOne( connection, prefix, MigrationTimeout, CancellationToken.None, LockableResource.Migration)) { var resourceName = $"{typeof(MySqlObjectsInstaller).Namespace}.Migrations.xml"; var document = XElement.Parse(GetStringResource(resourceName)); EnsureMigrationsTable(connection, prefix); var migrations = document .Elements("migration") .Select(e => new { id = e.Attribute("id")?.Value, script = e.Value }) .ToArray(); foreach (var migration in migrations) { var alreadyApplied = IsMigrationApplied(connection, prefix, migration.id); if (alreadyApplied) { continue; } ApplyMigration(connection, migration.script, prefix, migration.id); } } }
public StatisticsGatheringResourceLockObserver(ResourceLock resLock) : base(resLock) { Contract.Requires(resLock != null); }
public StatisticsGatheringResourceLockObserver(ResourceLock resLock) : base(resLock) { Contract.Requires(resLock != null); }
/// <summary>Constructs a TimeoutNotifierResourceLockObserver object.</summary> /// <param name="resLock">Indicates the inner ResourceLock.</param> /// <param name="timeout">Indicates how long any thread should wait on the inner lock before throwing an exception. This value is in milliseconds.</param> public TimeoutNotifierResourceLockObserver(ResourceLock resLock, Int64 timeout) : base(resLock) { Contract.Requires(resLock != null); m_timeout = timeout; }
public ThreadSafeCheckerResourceLockObserver(ResourceLock resLock) : base(resLock) { Contract.Requires(resLock != null); }
/// <summary> /// Constructs a ResourceLockObserver. /// </summary> /// <param name="resLock"></param> protected ResourceLockObserver(ResourceLock resLock) : base(resLock) { Contract.Requires(resLock != null); }
public async void Updated(SocketGuildUser before, SocketGuildUser after) { if (before?.Activity?.Name == after?.Activity?.Name || string.IsNullOrWhiteSpace(after?.Activity?.Name)) { //We don't want to overload the bot by trying to do things when the activity name didn't change (ie: status change, match details change in the activity, ...) return; } // Try to lock the user if (!await ResourceLock.AcquireLock($"{after.Id}")) { // If we can't another client is already handling it this._telemetry.TrackEvent($"Lock failed on user {after.Id} ({after.Username}#{after.DiscriminatorValue})"); return; } this._telemetry.TrackEvent("Handling a user status update"); var guild = await SearchTable <Guild>(g => g.RowKey == after.Guild.Id.ToString()).GetOneAsync(); if (guild == null) { //On aurait pu prendre le guild id du before, pas comme si ça allait changer guild = new Guild(after.Guild); await guild.InsertAsync(); //On vient d'ajouter le serveur (guild) à la liste des serveurs connnus, on a plus rien a faire, puisque aucun binding n'existe return; } //On charge les consignes d'assignation await guild.LoadChildrens(g => g.RoleAssignations); if (!guild.RoleAssignations.Any()) { //Rien a faire, pas d'assignations return; } var orderedAssignations = guild.RoleAssignations.OrderBy(ra => ra.Order).ToList(); foreach (var orderedAssignation in orderedAssignations) { try { if (orderedAssignation.IsRegExp) { var regexp = new Regex(orderedAssignation.GameName, RegexOptions.IgnoreCase); if (regexp.IsMatch(after.Activity.Name)) { var role = after.Guild.GetRole(orderedAssignation.RoleId); await after.AddRoleAsync(role, RequestOptions.Default); return; } } else { if (after.Activity.Name.ToLowerInvariant().Contains(orderedAssignation.GameName.ToLowerInvariant())) { var role = after.Guild.GetRole(orderedAssignation.RoleId); await after.AddRoleAsync(role, RequestOptions.Default); return; } } } catch (Exception e) { this._telemetry.TrackException(e); continue; } } }
public ThreadSafeCheckerResourceLockObserver(ResourceLock resLock) : base(resLock) { Contract.Requires(resLock != null); }
// Called by a thread when it is about to wait on a lock private IDisposable BlockForLockI(ResourceLock lockObject, Boolean acquiringExclusively) { // Some ResourceLock-derived types are ignored (like NullResourceLock) if (lockObject.ImmuneFromDeadlockDetection) return null; // Create record indicating what the calling thread is waiting on and add to waiting threads list BlockThreadAndCheckDeadlock(new ThreadBlockInfo(lockObject, acquiringExclusively)); return m_UnblockDueToLockAcquireDisposer; }
/// <summary>Tells the DeadlockDetector that a thread is about to block waiting for a lock.</summary> /// <param name="lockObject">The lock that the thread is about to block on.</param> /// <param name="acquiringExclusively">true if the thread is acquiring the lock exclusively.</param> /// <returns>An object that tells the DeadlockDetector that the thread is no longer blocked.</returns> public static IDisposable BlockForLock(ResourceLock lockObject, Boolean acquiringExclusively) { return s_deadlockDetector.BlockForLockI(lockObject, acquiringExclusively); }
public ResourceLock AcquireUpgradableRead() { UnsafeEnterUpgradableRead(); return(ResourceLock.UpgradableReader(this)); }
protected ResourceLockDelegator(ResourceLock resLock) : this(resLock, resLock.ResourceLockOptions) { Contract.Requires(resLock != null); Contract.Ensures(InnerLock != null); Contract.Assert(m_resLock != null); }
/// <summary>Constructs a ResourceLockModifier object.</summary> /// <param name="resLock">Identifies the inner ResourceLock object.</param> /// <param name="resourceLockOptions">Identifies the flags associted with the innter ResourceLock object.</param> protected ResourceLockModifier(ResourceLock resLock, ResourceLockOptions resourceLockOptions) : base(resLock, resourceLockOptions) { Contract.Requires(resLock != null); }
public StatisticsGatheringResourceLock(ResourceLock resLock) : base(resLock, resLock.IsMutualExclusive) { }
/// <summary> /// Constructs an ExclusiveOwnerResourceLockModifier over the specified ResourceLock. /// </summary> /// <param name="resLock"></param> public ExclusiveOwnerResourceLockModifier(ResourceLock resLock) : base(resLock, ResourceLockOptions.AcquiringThreadMustRelease | ResourceLockOptions.IsMutualExclusive) { Contract.Requires(resLock != null); m_exclusiveOwner = new ExclusiveOwnerResourceLockHelper(resLock); }
public ThreadSafeCheckerResourceLock(ResourceLock resLock) : base(resLock, resLock.IsMutualExclusive) { }
/// <summary>Constructs a TimeoutNotifierResourceLockObserver object.</summary> /// <param name="resLock">Indicates the inner ResourceLock.</param> /// <param name="timeout">Indicates how long any thread should wait on the inner lock before throwing an exception.</param> public TimeoutNotifierResourceLockObserver(ResourceLock resLock, TimeSpan timeout) : this(resLock, (Int64)timeout.TotalMilliseconds) { Contract.Requires(resLock != null); }
public ThreadBlockInfo(ResourceLock lockObject, Boolean acquiringExclusively) : this(lockObject, (lockObject.AcquiringThreadMustRelease ? ResourceLockOptions.AcquiringThreadMustRelease : 0) | (lockObject.SupportsRecursion ? ResourceLockOptions.SupportsRecursion : 0) | (acquiringExclusively ? ResourceLockOptions.IsMutualExclusive : 0)) { }
protected DiagnosticResourceLock(ResourceLock resLock) : this(resLock, resLock.IsMutualExclusive) { }
public ResourceLock AcquireRead() { UnsafeEnterRead(); return(ResourceLock.Reader(this)); }
/// <summary>Constructs a TimeoutNotifierResourceLockObserver object.</summary> /// <param name="resLock">Indicates the inner ResourceLock.</param> /// <param name="timeout">Indicates how long any thread should wait on the inner lock before throwing an exception. This value is in milliseconds.</param> public TimeoutNotifierResourceLockObserver(ResourceLock resLock, Int64 timeout) : base(resLock) { Contract.Requires(resLock != null); m_timeout = timeout; }
public ResourceLock AcquireWrite() { UnsafeEnterWrite(); return(ResourceLock.Writer(this)); }
/// <summary>Constructs a TimeoutNotifierResourceLockObserver object.</summary> /// <param name="resLock">Indicates the inner ResourceLock.</param> /// <param name="timeout">Indicates how long any thread should wait on the inner lock before throwing an exception.</param> public TimeoutNotifierResourceLockObserver(ResourceLock resLock, TimeSpan timeout) : this(resLock, (Int64) timeout.TotalMilliseconds) { Contract.Requires(resLock != null); }