Exemplo n.º 1
0
        public async Task <bool> Copy(string source, string newName, bool replace = true)
        {
            var _lock = NamedLock.Get(newName);

            using (var releaser = await _lock.LockAsync())
            {
                var sFile = _getPath(source);
                var tFile = _getPath(newName);

                var   r = Task.Run(() => File.Exists(sFile));
                await r;

                if (!r.Result)
                {
                    return(false);
                }

                var dir = Path.GetDirectoryName(tFile);

                if (dir != null && !Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }

                var r2 = Task.Run(() => File.Copy(sFile, tFile, replace));

                await r2;

                return(true);
            }
        }
 public void Lock_ThreadedCalls_ShouldOnlyAllowASingleThreadToAccessTheProcessAtOnce()
 {
     var counter = 0;
     var namedLock = new NamedLock<string>();
     const int threadCount = 50;
     var areEqual = true;
     var threads = new Thread[threadCount];
     for (var i = 0; i < threadCount; i++)
     {
         threads[i] = new Thread(() =>
                                     {
                                         using (namedLock.Lock("my lock"))
                                         {
                                             int currentCounter = ++counter;
                                             Thread.Sleep(25);
                                             if (currentCounter != counter)
                                                 areEqual = false;
                                         }
                                     });
         threads[i].Start();
     }
     for (var i = 0; i < threadCount; i++)
     {
         threads[i].Join();
     }
     Assert.IsTrue(areEqual, "Only a single thread should be able to modify the shared variable at any time");
 }
Exemplo n.º 3
0
        public async Task <ILock> ObtainLock(string name)
        {
            NamedLock lk = null;

            lock (_lock)
            {
                lk = _locks.GetOrAdd(name, key => new NamedLock(key));
            }

            await lk.Lock();

            var disposable = new DisposableLock(Disposable.Create(() =>
            {
                lk.Release();
                lock (_lock)
                {
                    if (lk.Waiters.Count == 0)
                    {
                        _locks.TryRemove(name, out _);
                    }
                }
            }));

            return(disposable);
        }
Exemplo n.º 4
0
        private void RemoveAwaiter(CorrelatedAwaiter awaitableNotification)
        {
            if (!awaitableNotification.Removed)
            {
                var start = DateTime.Now;
                using (NamedLock.CreateAndEnter($"{_cacheKeyPrefixNamedLocks}{awaitableNotification.Key}"))
                {
                    _traceWriter?.Write($"{nameof(CorrelatedAwaitManager<TMessage, TKey>)}: {nameof(RemoveAwaiter)}: Local_Lock_Acquired in {DateTime.Now.Subtract(start).TotalMilliseconds * 1000:#,##0.0}us");

                    if (!awaitableNotification.Removed)
                    {
                        if (_awaitedNotifications.TryGetValue(awaitableNotification.Key, out var hashSet))
                        {
                            hashSet.Remove(awaitableNotification);
                            if (hashSet.Count == 0)
                            {
                                _awaitedNotifications.TryRemove(awaitableNotification.Key, out var trash);
                            }
                        }

                        awaitableNotification.Removed = true;
                    }
                }
            }
        }
Exemplo n.º 5
0
        public IDisposable CreateLock(string lockKey, TimeSpan lockExpiryTime)
        {
            var lck = NamedLock.CreateAndEnter($"{nameof(LocalMemMockOfRedis)}:{nameof(CreateLock)}:{lockKey}", 0);

            if (lck.IsLocked)
            {
                return(lck);
            }

            lck.Dispose();
            return(null);
        }
Exemplo n.º 6
0
        public async Task Save(string fileName, byte[] data)
        {
            var _lock = NamedLock.Get(fileName);

            using (var releaser = await _lock.LockAsync())
            {
                var path = _getPath(fileName);
                _createDirForFile(path);

                var   r = Task.Run(() => File.WriteAllBytes(path, data));
                await r;
            }
        }
Exemplo n.º 7
0
        public async Task <bool> SaveString(string fileName, string data)
        {
            var _lock = NamedLock.Get(fileName);

            using (var releaser = await _lock.LockAsync())
            {
                var path = _getPath(fileName);
                _createDirForFile(path);

                var   r = Task.Run(() => File.WriteAllText(path, data));
                await r;
                return(true);
            }
        }
        public void Lock_ShouldRemoveTheLockWhenNoFurtherReferencesAreHeld()
        {
            var lockDictionary = (Dictionary<string, NamedLock<string>.RefCounter>)typeof(NamedLock<string>).GetField("_locks", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);

            //var lockDictionary =
            //    new ReflectionHelper().GetPrivateStaticField
            //        <Dictionary<string, NamedLock<string>.RefCounter>>(
            //        typeof(NamedLock<string>), "_locks");
            Assert.AreEqual(0, lockDictionary.Count, "Expect no locks to be present before the test is run");
            var namedLock = new NamedLock<string>();
            using (namedLock.Lock("lock name"))
            {
                Assert.AreEqual(1, lockDictionary.Count, "Expect the lock to be recorded in the dictionary");
            }
            Assert.AreEqual(0, lockDictionary.Count, "Expect the lock to be removed from the dictionary when no more threads hold the lock");
        }
Exemplo n.º 9
0
        public async Task SaveStream(string fileName, System.IO.Stream stream)
        {
            var _lock = NamedLock.Get(fileName);

            using (var releaser = await _lock.LockAsync())
            {
                var path = _getPath(fileName);

                _createDirForFile(path);

                using (var s = File.Create(path))
                {
                    await stream.CopyToAsync(s);
                }
            }
        }
Exemplo n.º 10
0
        public async Task <System.IO.Stream> LoadStream(string fileName)
        {
            var _lock = NamedLock.Get(fileName);

            using (var releaser = await _lock.LockAsync())
            {
                var path = _getPath(fileName);
                if (!File.Exists(path))
                {
                    return(null);
                }

                var   r = Task.Run(() => File.Open(path, FileMode.Open));
                await r;
                return(r.Result);
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Returns a value from local memory, failing that retrieves from external/network cache,
        /// stores a copy in local memory (as long as it is not near immediatey expiring) and returns it.
        /// </summary>
        /// <param name="key">Cache key (unique within external cache)</param>
        /// <returns></returns>
        public string Get(string key)
        {
            var cacheVal = _memoryCache.Get(key);

            _traceWriter?.Write($"From Local Cache 1: {key}, val length: {((string)cacheVal)?.Length ?? -1}");
            if (cacheVal != null)
            {
                return((string)cacheVal);
            }

            // not a perfect named lock but synchronises multiple incomming calls and prevents secondary / concurrent calls
            // to redis.get until the first, then after the redis retrieval is stored temporarily in memory (for 5 seconds)
            // subsoquent calls all get the result from memory (and ultimately fall back to redis if it expires)
            _traceWriter?.Write($"{nameof(MemoryFrontedExternalCache)}: {nameof(Get)}: Locking local: {_lockKeyPrefixExternalRetrieve}{key}");
            var start = DateTime.Now;

            using (NamedLock.CreateAndEnter($"{_lockKeyPrefixExternalRetrieve}{key}"))
            {
                _traceWriter?.Write($"{nameof(MemoryFrontedExternalCache)}: {nameof(Get)}: Locked: {_lockKeyPrefixExternalRetrieve}{key} in {DateTime.Now.Subtract(start).TotalMilliseconds * 1000:#,##0.0}us");
                cacheVal = _memoryCache.Get(key);
                _traceWriter?.Write($"From Local Cache 2: {key}, val length: {((string)cacheVal)?.Length ?? -1}");
                if (cacheVal != null)
                {
                    return((string)cacheVal);
                }

                var timePriorToRedisCall = DateTime.UtcNow;
                var value = _externalCache.StringGetWithExpiry($"{_cacheKeyPrefixItem}{key}", out var expiry);

                _traceWriter?.Write($"{nameof(MemoryFrontedExternalCache)}: {nameof(Get)}: {nameof(_externalCache)}.{nameof(_externalCache.StringGetWithExpiry)}(key: {key}, out expiry: {expiry}); => result present: {value != null}");

                if (value != null)
                {
                    var expiryTime = expiry.Subtract(DateTime.UtcNow.Subtract(timePriorToRedisCall));
                    if (expiryTime > TimeSpan.FromSeconds(0))
                    {
                        StoreLocalMemory(key, value, expiryTime);
                    }

                    return(value);
                }
            }

            return(null);
        }
Exemplo n.º 12
0
        public async Task <string> LoadString(string fileName)
        {
            var _lock = NamedLock.Get(fileName);

            using (var releaser = await _lock.LockAsync())
            {
                var path = _getPath(fileName);

                if (!File.Exists(path))
                {
                    return(null);
                }

                var   r = Task.Run(() => File.ReadAllText(path));
                await r;
                return(r.Result);
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Returns an awaitable task interface to await a requested result / message (based on a message id / key).
        /// </summary>
        public ICorrelatedAwaiter <TMessage> CreateAwaiter(TKey key)
        {
            var awaitableNotification = new CorrelatedAwaiter(key, this);

            var start = DateTime.Now;

            using (NamedLock.CreateAndEnter($"{_cacheKeyPrefixNamedLocks}{key}"))
            {
                _traceWriter?.Write($"{nameof(CorrelatedAwaitManager<TMessage, TKey>)}: {nameof(CreateAwaiter)}: Local_Lock_Acquired in {DateTime.Now.Subtract(start).TotalMilliseconds * 1000:#,##0.0}us");

                if (!_awaitedNotifications.TryGetValue(key, out var hashSet))
                {
                    _awaitedNotifications[key] = hashSet = new HashSet <CorrelatedAwaiter>();
                }

                hashSet.Add(awaitableNotification);
            }

            return(awaitableNotification);
        }
Exemplo n.º 14
0
        public async Task <bool> DeleteFile(string fileName)
        {
            var _lock = NamedLock.Get(fileName);

            using (var releaser = await _lock.LockAsync())
            {
                var path = _getPath(fileName);

                var   r = Task.Run(() => File.Exists(path));
                await r;

                if (r.Result)
                {
                    var   r2 = Task.Run(() => File.Delete(path));
                    await r2;
                }

                return(true);
            }
        }
Exemplo n.º 15
0
        public async Task <bool> IsZero(string fileName)
        {
            var _lock = NamedLock.Get(fileName);

            using (var releaser = await _lock.LockAsync())
            {
                var path = _getPath(fileName);

                var   r = Task.Run(() => File.Exists(path));
                await r;

                if (!r.Result)
                {
                    return(false);
                }

                var b = await Load(fileName);

                return(b.Length == 0);
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Notify all awaiters that have been created against this CorrelatedAwaitManager for the particular key
        /// and remove them from receiving future notifications.
        /// </summary>
        /// <param name="msg">Message to extract TKey from and to provide to awaiters.</param>
        public void NotifyAwaiters(TMessage msg)
        {
            // do critical lock synchonisation and manage dictionary of lists of awaiters inline before later
            // notifying waiting request/reply consumers (any new awaiters for same key will start queuing to new entry).
            List <CorrelatedAwaiter> tasksToComplete = null;

            var start = DateTime.Now;

            using (NamedLock.CreateAndEnter($"{_cacheKeyPrefixNamedLocks}{_getKeyFunc(msg)}"))
            {
                _traceWriter?.Write($"{nameof(CorrelatedAwaitManager<TMessage, TKey>)}: {nameof(NotifyAwaiters)}: Local_Lock_Acquired in {DateTime.Now.Subtract(start).TotalMilliseconds * 1000:#,##0.0}us");

                if (_awaitedNotifications.TryGetValue(_getKeyFunc(msg), out var hashSet))
                {
                    tasksToComplete = hashSet.ToList();
                    _awaitedNotifications.TryRemove(_getKeyFunc(msg), out var trash);
                    tasksToComplete.ForEach(tc => tc.Removed = true);
                }
            }

            // Simply sets results on task completion sources allowing scheduling of resumption of work in
            // awaiting threads/tasks.
            tasksToComplete?.ForEach(t => t.SetResult(msg));
        }
 public void NameLock_vs_NamedReaderWriterLockSlim_PerformanceTest_Balanced(int run)
 {
     const int threadCount = 50;
     const int lockSleepTime = 100;
     var threads = new Thread[threadCount];
     var startTime = DateTime.Now;
     for (var i = 0; i < threadCount; i++)
     {
         var j = i;
         threads[i] = new Thread(() =>
                                     {
                                         try
                                         {
                                             switch (j % 3)
                                             {
                                                 case 0:
                                                     using (_rwLock.LockRead("my lock" + run))
                                                         Thread.Sleep(lockSleepTime);
                                                     break;
                                                 case 1:
                                                     using (_rwLock.LockUpgradeableRead("my lock" + run, 10000))
                                                         Thread.Sleep(lockSleepTime);
                                                     break;
                                                 default:
                                                     using (_rwLock.LockWrite("my lock" + run))
                                                         Thread.Sleep(lockSleepTime);
                                                     break;
                                             }
                                         }
                                         catch (TimeoutException e)
                                         {
                                             Console.WriteLine(e.Message);
                                         }
                                     });
         threads[i].Start();
     }
     foreach (var thread in threads)
     {
         thread.Join();
     }
     Console.WriteLine("Run {0} - finished NamedRWLock run in {1}ms", run, new TimeSpan(DateTime.Now.Ticks - startTime.Ticks).TotalMilliseconds);
     //NamedLock
     var namedLock = new NamedLock<string>();
     startTime = DateTime.Now;
     for (var i = 0; i < threadCount; i++)
     {
         var j = i;
         threads[i] = new Thread(() =>
                                     {
                                         try
                                         {
                                             using (namedLock.Lock("my lock" + run, 10000))
                                                 Thread.Sleep(lockSleepTime);
                                         }
                                         catch (TimeoutException e)
                                         {
                                             Console.WriteLine(e.Message);
                                         }
                                     });
         threads[i].Start();
     }
     foreach (var thread in threads)
     {
         thread.Join();
     }
     Console.WriteLine("Run {0} - finished NamedLock run in {1}ms", run, new TimeSpan(DateTime.Now.Ticks - startTime.Ticks).TotalMilliseconds);
     //Monitor
     startTime = DateTime.Now;
     var myMonitorLock = new object();
     for (var i = 0; i < threadCount; i++)
     {
         var j = i;
         threads[i] = new Thread(() =>
                                     {
                                         if (!Monitor.TryEnter(myMonitorLock, 10000))
                                             Console.WriteLine("Failed to acquire monitor lock");
                                         Thread.Sleep(lockSleepTime);
                                         Monitor.Exit(myMonitorLock);
                                     });
         threads[i].Start();
     }
     foreach (var thread in threads)
     {
         thread.Join();
     }
     Console.WriteLine("Run {0} - finished Monitor run in {1}ms", run, new TimeSpan(DateTime.Now.Ticks - startTime.Ticks).TotalMilliseconds);
 }