/// <summary> /// Commits the transaction. /// </summary> /// <remarks> /// After a successful call to this method, this context instance should be disposed. /// </remarks> public void Commit() { try { if (_transactionCommitted) { throw new InvalidOperationException("Transaction already committed."); } _context.SubmitChanges(); if (_transaction != null) { _transaction.Commit(); } _transactionCommitted = true; } catch (ChangeConflictException) { foreach (ObjectChangeConflict occ in _context.ChangeConflicts) { MetaTable metatable = _context.Mapping.GetTable(occ.Object.GetType()); Platform.Log(LogLevel.Warn, "Change Conflict with update to table: {0}", metatable.TableName); } throw; } finally { if (_mutex != null) { _mutex.Unlock(); _mutex.Dispose(); _mutex = null; } } }
protected override void Execute() { var start = Environment.TickCount; var random = new Random(TesterId); do { // for simulating a broken lock to verify that this test does what is intended, use x as conditional on _lock calls // var x = _testerId != random.Next(0, 1000); var @lock = ExclusiveLock.CreateFileSystemLock(typeof(InstanceFileSystemLockTester).FullName); @lock.Lock(); Interlocked.Increment(ref _counter); try { Thread.Sleep(random.Next(1, 20)); // add some variability to iteration length so that threads aren't just running in lock step Assert.AreEqual(1, _counter, @"Tester {0} entered lock while another tester has lock", TesterId); FlagFailed(_counter != 1); } finally { Interlocked.Decrement(ref _counter); @lock.Unlock(); } } while (Environment.TickCount - start < TestLengthMs); }
/// <summary> /// Activate the options on the file appender. /// </summary> /// <remarks> /// <para> /// This is part of the <see cref="IOptionHandler"/> delayed object /// activation scheme. The <see cref="ActivateOptions"/> method must /// be called on this object after the configuration properties have /// been set. Until <see cref="ActivateOptions"/> is called this /// object is in an undefined state and must not be used. /// </para> /// <para> /// If any of the configuration properties are modified then /// <see cref="ActivateOptions"/> must be called again. /// </para> /// <para> /// This will cause the file to be opened. /// </para> /// </remarks> override public void ActivateOptions() { base.ActivateOptions(); if (m_securityContext == null) { m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); } if (m_lockingModel == null) { m_lockingModel = new ExclusiveLock(); } m_lockingModel.CurrentAppender = this; using (SecurityContext.Impersonate(this)) { m_fileName = ConvertToFullPath(m_fileName.Trim()); } if (m_fileName != null) { SafeOpenFile(m_fileName, m_appendToFile); } else { LogLog.Warn(declaringType, "FileAppender: File option not set for appender [" + Name + "]."); LogLog.Warn(declaringType, "FileAppender: Are you using FileAppender instead of ConsoleAppender?"); } }
public void Dispose() { if (_disposed) { throw new InvalidOperationException("Already disposed."); } _disposed = true; if (!_transactionCommitted && _transaction != null) { _transaction.Rollback(); } _context.Dispose(); _connection.Close(); _connection.Dispose(); if (_mutex != null) { _mutex.Unlock(); _mutex.Dispose(); _mutex = null; } }
/// <summary> /// 写日志以前的准备工作 /// </summary> override public void ActivateAppender() { if (m_lockingModel == null) { switch (LogConfig.Instance.LockType) { //独占锁 case LockingType.Exclusive: m_lockingModel = new ExclusiveLock(); break; //跨进程文件锁定 case LockingType.InterProcess: m_lockingModel = new InterProcessLock(); break; //最小时间锁 case LockingType.Minimal: m_lockingModel = new MinimalLock(); break; } } m_lockingModel.CurrentAppender = this; if (m_fileName != null) { PrepareWriter(); } }
public void Acquire_completes_sync_then_release_succeeds() { ExclusiveLock l = new ExclusiveLock(); ExclusiveLock.Token token = AssertTaskCompleted(l.AcquireAsync()); l.Release(token); }
private ExclusiveLock CreateLock(string baseName, bool useGlobalPrefix) { if (useGlobalPrefix) { return(new NamedMutexLock(@"Global\" + baseName)); } return(ExclusiveLock.CreateFileSystemLock(baseName)); }
static void RotateList(L2List list) { using (ExclusiveLock xl = new ExclusiveLock(list)) { L2Elem last = list.head.prev; last.unlink(); last.linkAfter(list.head); } }
public void Release_same_token_twice_throws_InvalidOperation() { ExclusiveLock l = new ExclusiveLock(); ExclusiveLock.Token token = AssertTaskCompleted(l.AcquireAsync()); l.Release(token); Assert.Throws <InvalidOperationException>(() => l.Release(token)); }
public void First_acquire_completes_sync_next_acquire_is_pending_until_first_release() { ExclusiveLock l = new ExclusiveLock(); ExclusiveLock.Token token = AssertTaskCompleted(l.AcquireAsync()); Task <ExclusiveLock.Token> nextAcquireTask = AssertTaskPending(l.AcquireAsync()); l.Release(token); AssertTaskCompleted(nextAcquireTask); }
public void Acquire_and_release_three_times_in_a_row_completes_sync_each_time() { ExclusiveLock l = new ExclusiveLock(); ExclusiveLock.Token token1 = AssertTaskCompleted(l.AcquireAsync()); l.Release(token1); ExclusiveLock.Token token2 = AssertTaskCompleted(l.AcquireAsync()); l.Release(token2); ExclusiveLock.Token token3 = AssertTaskCompleted(l.AcquireAsync()); l.Release(token3); }
/// <summary> /// 打开文件为写日志操作做准备 /// </summary> /// <param name="fileName">文件名</param> /// <param name="append">是否添加日志信息到文件尾</param> virtual protected void OpenFile(string fileName, bool append) { lock (this) { //先进行关闭之前打开的文件 Reset(); // 保存这些后, 允许重试如果打开文件失败 m_fileName = fileName; m_appendToFile = append; switch (LogConfig.Instance.LockType) { //独占 case LockingType.Exclusive: m_lockingModel = new ExclusiveLock(); break; //跨进程文件锁 case LockingType.InterProcess: m_lockingModel = new InterProcessLock(); break; //最小时间 case LockingType.Minimal: m_lockingModel = new MinimalLock(); break; } // LockingModel.CurrentAppender = this; //打开文件 LockingModel.OpenFile(fileName, append, m_encoding); m_stream = new LockingStream(LockingModel); if (m_stream != null) { m_stream.AcquireLock(); try { SetQWForFiles(new StreamWriter(m_stream, m_encoding)); } finally { m_stream.ReleaseLock(); } } } }
public void Three_acquires_first_completes_sync_next_acquires_are_pending_until_previous_owners_release() { ExclusiveLock l = new ExclusiveLock(); ExclusiveLock.Token token1 = AssertTaskCompleted(l.AcquireAsync()); Task <ExclusiveLock.Token> acquireTask1 = AssertTaskPending(l.AcquireAsync()); Task <ExclusiveLock.Token> acquireTask2 = AssertTaskPending(l.AcquireAsync()); l.Release(token1); ExclusiveLock.Token token2 = AssertTaskCompleted(acquireTask1); l.Release(token2); AssertTaskCompleted(acquireTask2); }
internal DataAccessContext(string mutexName, string databaseFilename) { if (!string.IsNullOrEmpty(mutexName)) { _mutex = ExclusiveLock.CreateFileSystemLock(SqlCeDatabaseHelper<DicomStoreDataContext>.GetDatabaseFilePath(mutexName + databaseFilename)); _mutex.Lock(); } try { // initialize a connection and transaction _databaseFilename = databaseFilename; _connection = CreateConnection(); _transaction = _connection.BeginTransaction(IsolationLevel.ReadCommitted); _context = new DicomStoreDataContext(_connection); //_context.Log = Console.Out; } catch { _mutex.Unlock(); _mutex.Dispose(); _mutex = null; throw; } lock (_syncLock) { if (_staticConnection == null) { // This is done for performance reasons. It forces a connection to remain open while the // the app domain is running, so that the database is kept in memory. try { _staticConnection = CreateConnection(); } catch (Exception ex) { Platform.Log(LogLevel.Debug, ex, "Failed to initialize static connection to data store database"); } } } }
internal DataAccessContext(string mutexName, string databaseFilename) { if (!string.IsNullOrEmpty(mutexName)) { _mutex = ExclusiveLock.CreateFileSystemLock(SqlCeDatabaseHelper <DicomStoreDataContext> .GetDatabaseFilePath(mutexName + databaseFilename)); _mutex.Lock(); } try { // initialize a connection and transaction _databaseFilename = databaseFilename; _connection = CreateConnection(); _transaction = _connection.BeginTransaction(IsolationLevel.ReadCommitted); _context = new DicomStoreDataContext(_connection); //_context.Log = Console.Out; } catch { _mutex.Unlock(); _mutex.Dispose(); _mutex = null; throw; } lock (_syncLock) { if (_staticConnection == null) { // This is done for performance reasons. It forces a connection to remain open while the // the app domain is running, so that the database is kept in memory. try { _staticConnection = CreateConnection(); } catch (Exception ex) { Platform.Log(LogLevel.Debug, ex, "Failed to initialize static connection to data store database"); } } } }
static void Main(string[] args) { var serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(); var serviceProvider = serviceCollection.BuildServiceProvider(); var loggerFactory = serviceProvider.GetService <ILoggerFactory>(); var cancellationTokenSource = new CancellationTokenSource(); using (var exclusiveLock = new ExclusiveLock("localhost:2181", "/dlock-example", 5000, cancellationTokenSource.Token, loggerFactory.CreateLogger("dlock.console"))) { var dlock = exclusiveLock.Wait().GetAwaiter().GetResult(); Console.WriteLine(dlock); if (dlock.result) { SpinWait.SpinUntil(() => dlock.cancellationToken.IsCancellationRequested); Console.WriteLine("Releasing lock, cancellation requested"); } } }
/// <summary> /// Activate the options on the file appender. /// </summary> /// <remarks> /// <para> /// This is part of the <see cref="IOptionHandler"/> delayed object /// activation scheme. The <see cref="ActivateOptions"/> method must /// be called on this object after the configuration properties have /// been set. Until <see cref="ActivateOptions"/> is called this /// object is in an undefined state and must not be used. /// </para> /// <para> /// If any of the configuration properties are modified then /// <see cref="ActivateOptions"/> must be called again. /// </para> /// <para> /// This will cause the file to be opened. /// </para> /// </remarks> public override void ActivateOptions() { base.ActivateOptions(); if (m_securityContext == null) m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); if (m_lockingModel == null) m_lockingModel = new ExclusiveLock(); m_lockingModel.CurrentAppender = this; using (SecurityContext.Impersonate(this)) { m_fileName = ConvertToFullPath(m_fileName.Trim()); } if (m_fileName != null) SafeOpenFile(m_fileName, m_appendToFile); else { LogLog.Warn("FileAppender: File option not set for appender [" + Name + "]."); LogLog.Warn("FileAppender: Are you using FileAppender instead of ConsoleAppender?"); } }
/// <summary> /// Commits the transaction. /// </summary> /// <remarks> /// After a successful call to this method, this context instance should be disposed. /// </remarks> public void Commit() { try { if (_transactionCommitted) throw new InvalidOperationException("Transaction already committed."); _context.SubmitChanges(); if (_transaction != null) _transaction.Commit(); _transactionCommitted = true; } catch (ChangeConflictException) { foreach (ObjectChangeConflict occ in _context.ChangeConflicts) { MetaTable metatable = _context.Mapping.GetTable(occ.Object.GetType()); Platform.Log(LogLevel.Warn, "Change Conflict with update to table: {0}", metatable.TableName); } throw; } finally { if (_mutex != null) { _mutex.Unlock(); _mutex.Dispose(); _mutex = null; } } }
public void Dispose() { if(_disposed) throw new InvalidOperationException("Already disposed."); _disposed = true; if(!_transactionCommitted && _transaction != null) { _transaction.Rollback(); } _context.Dispose(); _connection.Close(); _connection.Dispose(); if (_mutex != null) { _mutex.Unlock(); _mutex.Dispose(); _mutex = null; } }
public void Release_invalid_token_throws_InvalidOperation() { ExclusiveLock l = new ExclusiveLock(); Assert.Throws <InvalidOperationException>(() => l.Release(new MyToken())); }