internal FluentNHibernateDistributedLock Acquire()
        {
            var finish = DateTime.UtcNow.Add(_timeout);

            while (!_cancellationToken.IsCancellationRequested && finish > DateTime.UtcNow)
            {
                if (SqlUtil.WrapForTransaction(() => SqlUtil.WrapForDeadlock(_cancellationToken, () =>
                {
                    _cancellationToken.WaitHandle.WaitOne(new TimeSpan(0, 0, 1));

                    var done = TryLock(() =>
                    {
                        using (var session = _storage.GetStatelessSession())
                        {
                            using (var transaction = session.BeginTransaction(IsolationLevel.Serializable))
                            {
                                var count = session.Query <_DistributedLock>()
                                            .Count(i => i.Resource == _resource);
                                if (count == 0)
                                {
                                    var distributedLock = new _DistributedLock
                                    {
                                        CreatedAt = session.Storage.UtcNow, Resource = _resource,
                                        ExpireAtAsLong = session.Storage.UtcNow.Add(_timeout).ToEpochDate()
                                    };
                                    session.Insert(distributedLock);

                                    _lockId = distributedLock.Id;
                                    transaction.Commit();
                                    if (Logger.IsDebugEnabled())
                                    {
                                        Logger.DebugFormat("Created distributed lock for {0}",
                                                           JsonConvert.SerializeObject(distributedLock));
                                    }
                                    return(true);
                                }
                            }

                            return(false);
                        }
                    }, () => false);
                    return(done);
                }, _options)))
                {
                    Logger.DebugFormat("Granted distributed lock for {0}", _resource);
                    return(this);
                }

                _cancellationToken.WaitHandle.WaitOne(_options.DistributedLockPollInterval);
            }

            return(null);
        }
Exemplo n.º 2
0
 internal void Release()
 {
     SqlUtil.WrapForTransaction(() =>
     {
         SqlUtil.WrapForDeadlock(() =>
         {
             lock (Mutex)
             {
                 using (var session = _storage.GetSession())
                 {
                     session.CreateQuery(SqlUtil.DeleteDistributedLockSql)
                     .SetParameter(SqlUtil.IdParameterName, _resource)
                     .ExecuteUpdate();
                     session.Flush();
                     Logger.DebugFormat("Released distributed lock for {0}", _resource);
                 }
             }
         }, _options);
     });
 }
        internal void Release()
        {
            SqlUtil.WrapForTransaction(() =>
            {
                SqlUtil.WrapForDeadlock(_cancellationToken, () =>
                {
                    lock (Mutex)
                    {
                        if (_lockId.HasValue)
                        {
                            using (var session = _storage.GetStatelessSession())
                            {
                                session.Query <_DistributedLock>().Where(i => i.Id == _lockId).Delete();

                                Logger.DebugFormat("Released distributed lock for {0}", _resource);
                                _lockId = null;
                            }
                        }
                    }
                }, _options);
            });
        }
Exemplo n.º 4
0
        private bool CreateLockRow()
        {
            return(SqlUtil.WrapForDeadlock(() =>
            {
                lock (Mutex)
                {
                    using (var session = _storage.GetSession())
                    {
                        using (var transaction = session.BeginTransaction(IsolationLevel.Serializable))
                        {
                            var lockResourceParams = new LockResourceParams(session, _resource, _timeout);

                            var query = session.CreateQuery(SqlUtil.GetCreateDistributedLockStatement())
                                        .SetParameter(SqlUtil.ResourceParameterName, lockResourceParams.Resource)
                                        .SetParameter(SqlUtil.ExpireAtAsLongParameterName,
                                                      lockResourceParams.ExpireAtAsLong)
                                        .SetParameter(SqlUtil.CreatedAtParameterName, lockResourceParams.CreatedAt)
                                        .SetParameter(SqlUtil.UtcNowAsLongParameterName, lockResourceParams.CreatedAtAsLong);


                            var count = query.ExecuteUpdate();
                            if (count == 1)
                            {
                                transaction.Commit();
                                if (Logger.IsDebugEnabled())
                                {
                                    Logger.DebugFormat("Created distributed lock for {0}",
                                                       JsonConvert.SerializeObject(lockResourceParams));
                                }
                                return true;
                            }
                        }
                    }

                    return false;
                }
            }, _options));
        }
        internal void Initialize()
        {
            var started = Stopwatch.StartNew();

            do
            {
                if (SqlUtil.WrapForTransaction(() => SqlUtil.WrapForDeadlock(_cancellationToken, () =>
                {
                    var done = TryLock(() =>
                    {
                        var result = false;
                        _storage.UseStatelessSessionInTransaction(session =>
                        {
                            var distributedLock = session.Query <_DistributedLock>()
                                                  .FirstOrDefault(i => i.Resource == _resource);

                            var utcNow = session.Storage.UtcNow;
                            var expireAtAsLong = utcNow.Add(_timeout).ToEpochDate();
                            if (distributedLock == null)
                            {
                                distributedLock = new _DistributedLock
                                {
                                    CreatedAt = utcNow,
                                    Resource = _resource,
                                    ExpireAtAsLong = expireAtAsLong
                                };
                                session.Insert(distributedLock);

                                _lockId = distributedLock.Id;
                                result = true;
                                if (Logger.IsDebugEnabled())
                                {
                                    Logger.Debug($"Inserted row for distributed lock '{_resource}'");
                                }
                            }
                            else if (distributedLock.ExpireAtAsLong < utcNow.ToEpochDate())
                            {
                                distributedLock.CreatedAt = utcNow;
                                distributedLock.ExpireAtAsLong = expireAtAsLong;
                                session.Update(distributedLock);
                                if (Logger.IsDebugEnabled())
                                {
                                    Logger.Debug($"Re-used row for distributed lock '{_resource}'");
                                }
                                _lockId = distributedLock.Id;
                                result = true;
                            }
                        });
                        return(result);
                    }, () => false);
                    return(done);
                }, _options)))
                {
                    if (Logger.IsDebugEnabled())
                    {
                        Logger.DebugFormat("Granted distributed lock '{0}'", _resource);
                    }
                    return;
                }

                if (started.Elapsed > _timeout)
                {
                    break;
                }
                if (Logger.IsDebugEnabled())
                {
                    Logger.Debug(
                        $"Will poll for distributed lock '{_resource}' in {_options.DistributedLockPollInterval}.");
                }
                _cancellationToken.Wait(_options.DistributedLockPollInterval);
            } while (true);

            //dont change this.  Hangfire looks for resource name in exception properties
            throw new DistributedLockTimeoutException(_resource);
        }