Exemple #1
0
        /// <summary>
        ///     Enqueues an upload.
        /// </summary>
        /// <param name="username">The username of the remote user.</param>
        /// <param name="filename">The filename to enqueue.</param>
        public void Enqueue(string username, string filename)
        {
            SyncRoot.Wait();

            try
            {
                var upload = new Upload()
                {
                    Username = username, Filename = filename
                };

                Uploads.AddOrUpdate(
                    key: username,
                    addValue: new List <Upload>(new[] { upload }),
                    updateValueFactory: (key, list) =>
                {
                    list.Add(upload);
                    return(list);
                });

                Log.Debug("Enqueued: {File} for {User} at {Time}", Path.GetFileName(upload.Filename), upload.Username, upload.Enqueued);
            }
            finally
            {
                SyncRoot.Release();
                Process();
            }
        }
Exemple #2
0
        /// <summary>
        ///     Awaits the start of an upload.
        /// </summary>
        /// <param name="username">The username of the remote user.</param>
        /// <param name="filename">The filename for which to await the start.</param>
        /// <returns>The operation context.</returns>
        public Task AwaitStartAsync(string username, string filename)
        {
            SyncRoot.Wait();

            try
            {
                if (!Uploads.TryGetValue(username, out var list))
                {
                    throw new SlskdException($"No enqueued uploads for user {username}");
                }

                var upload = list.FirstOrDefault(e => e.Filename == filename);

                if (upload == default)
                {
                    throw new SlskdException($"File {filename} is not enqueued for user {username}");
                }

                upload.Ready = DateTime.UtcNow;
                Log.Debug("Ready: {File} for {User} at {Time}", Path.GetFileName(upload.Filename), upload.Username, upload.Enqueued);

                return(upload.TaskCompletionSource.Task);
            }
            finally
            {
                SyncRoot.Release();
                Process();
            }
        }
Exemple #3
0
        /// <summary>
        ///     Scans the configured <see cref="Directory"/> and fills the cache.
        /// </summary>
        public void Fill()
        {
            var sw = new Stopwatch();

            sw.Start();

            Console.WriteLine($"[SHARED FILE CACHE]: Refreshing...");

            SyncRoot.EnterWriteLock();

            try
            {
                CreateTable();

                Files = System.IO.Directory.GetFiles(Directory, "*", SearchOption.AllDirectories)
                        .Select(f => new Soulseek.File(1, f, new FileInfo(f).Length, Path.GetExtension(f), 0))
                        .ToDictionary(f => f.Filename, f => f);

                // potentially optimize with multi-valued insert
                // https://stackoverflow.com/questions/16055566/insert-multiple-rows-in-sqlite
                foreach (var file in Files)
                {
                    InsertFilename(file.Key);
                }
            }
            finally
            {
                SyncRoot.ExitWriteLock();
            }

            sw.Stop();

            Console.WriteLine($"[SHARED FILE CACHE]: Refreshed in {sw.ElapsedMilliseconds}ms.  Found {Files.Count()} files.");
            LastFill = DateTime.UtcNow;
        }
        void IDisposable.Dispose()
        {
            using (SyncRoot.Enter())
            {
                if (IsDisposed || IsDisposing)
                {
                    return;
                }

                IsDisposing = true;
            }

            try
            {
                Dispose(true);
            }
            catch (Exception)
            {
                // Disposing so not much we can do with this exception
            }
            finally
            {
                IsDisposed = true;
            }
        }
Exemple #5
0
        public override void OnInspectorGUI()
        {
            DrawDefaultInspector();

            if (Application.isPlaying)
            {
                SharingStage networkManager = (SharingStage)target;

                SyncRoot root = networkManager.Root;

                if (root != null)
                {
                    EditorGUILayout.Separator();
                    EditorGUILayout.BeginVertical();
                    {
                        EditorGUILayout.LabelField("Object Hierarchy");
                        DrawDataModelGUI(root, string.Empty);
                    }
                    EditorGUILayout.EndVertical();
                }

                // Force this inspector to repaint every frame so that it reflects changes to the undo stack
                // immediately rather than showing stale data until the user clicks on the inspector window
                Repaint();
            }
        }
        public bool TryEnqueue(T item, int timeoutMilliseconds = 0)
        {
            if (item == null)
            {
                return(false);
            }

            //The method only throws exception on thread lock timeout
            using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable)
            {
                if (IsDisposing || IsDisposed)
                {
                    return(false);
                }

                if (m_count == m_size)
                {
                    return(false);
                }

                m_items[m_tail++] = item;   // Place the new item immediately after tail, then increment tail pos
                m_tail           %= m_size; // Modulus new tail pos with size so queue items will wrap around
                m_count++;                  // Count will never be more than size after incrementing here

                //Signal that an item has been enqueued to unblock waiting
                //dequeue threads
                syncLock.PulseAll();

                return(true);
            }
        }
        public bool TryDequeue(out T item, int timeoutMilliseconds = 0)
        {
            //This method only throws exception on thread lock timeout
            using (IWaitable syncRoot = SyncRoot.Enter(timeoutMilliseconds) as IWaitable)
            {
                if (IsDisposing || IsDisposed)
                {
                    item = null;
                    return(false);
                }

                if (m_count == 0)
                {
                    item = null;
                    return(false);
                }

                item = m_items[m_head];     // Get item at head of queue
                m_items[m_head++] = null;   // Clear item at head of queue then increment head pos
                m_head           %= m_size; // Modulus new head pos with size so queue items will wrap around
                m_count--;                  // Count will never be less than zero after decrementing here

                //Signal that an item has been dequeued to unblock waiting
                //enqueue threads
                syncRoot.PulseAll();

                return(true);
            }
        }
        }   // OperatingParameters constructor


		private void InitializeOnFirstUse (
			SyncRoot ps_srCriticalSection ,
			AppSettingsForEntryAssembly pappSettingsForEntryAssembly ,
			SettingsPropertyCollection psettingsPropertyValueCollection )
		{
            lock ( ps_srCriticalSection )
                _settingsPropertyValueCollection = psettingsPropertyValueCollection;
		}   // private void InitializeOnFirstUse
		}   // GetTheSingleInstance Method


		private void InitializeOnFirstUse (
			SyncRoot ps_srCriticalSection ,
			OperatingParametersCollection<T, U> operatingParametersCollection )
		{
			lock ( ps_srCriticalSection )
			{
			}   // lock ( ps_srCriticalSection )
		}   // private void InitializeOnFirstUse
Exemple #10
0
 public void Set(T token)
 {
     using (SyncRoot.Enter())
     {
         var signal = GetSignal(token);
         signal.Set();
     }
 }
        protected override void Dispose(bool disposing)
        {
            using (SyncRoot.Enter())
            {
                Clear();

                m_items = null;
            }
        }
Exemple #12
0
        private AutoResetEvent GetSignal(T token)
        {
            using (SyncRoot.Enter())
            {
                if (!m_signals.ContainsKey(token))
                {
                    m_signals[token] = new AutoResetEvent(false);
                }

                return(m_signals[token]);
            }
        }
        public void Clear()
        {
            using (IWaitable syncLock = SyncRoot.Enter() as IWaitable)
            {
                //Unblock waiting threads
                syncLock.PulseAll();

                m_count = 0;
                m_head  = 0;
                m_tail  = 0;
                m_items = new T[m_size];
            }
        }
Exemple #14
0
        /// <summary>
        /// <c>Release</c> an object and add it back into the pool - increases pool size if the pool is full
        /// </summary>
        /// <param name="item">the object released back into the pool</param>
        /// <exception cref="ObjectDisposedException">throws when accessed during or after disposal</exception>
        public override void Release(T item)
        {
            if (!TryRelease(item)) //Tf the pool is full
            {
                using (SyncRoot.Enter())
                {
                    if (IsDisposing || IsDisposed)
                    {
                        throw new ObjectDisposedException(nameof(PrimitiveObjectPool <T>));
                    }

                    m_internalStorage.Add(item); //This will increment storage bag count
                    Size++;
                }
            }
        }
Exemple #15
0
        public override void AcceptVisitor(StatementVisitor visitor)
        {
            visitor.VisitLockStatement(this);

            if (SyncRoot != null)
            {
                SyncRoot.AcceptVisitor(visitor);
            }

            if (EnterTimeout != null)
            {
                EnterTimeout.AcceptVisitor(visitor);
            }

            if (Body != null)
            {
                Body.AcceptVisitor(visitor);
            }
        }
        protected T ExecStoredProcedure <T>(params object[] arguments)
        {
            using (_logger.BeginScope(nameof(ExecStoredProcedure)))
            {
                try
                {
                    _logger.LogDebug("Searching for calling method");
                    var stackFrames = new StackTrace().GetFrames();

                    var caller = stackFrames.Select(x => (MethodInfo)x.GetMethod())
                                 .Skip(1)
                                 .FirstOrDefault(x => typeof(DbContext).IsAssignableFrom(x.DeclaringType));

                    if (caller == null)
                    {
                        throw new MissingMethodException("Caller procedure could not be found, probably it was removed by optimizer. Check if caller method is marked by [MethodImpl(MethodImplOptions.NoInlining)]");
                    }

                    var fullName = $"{caller.DeclaringType.FullName}.{caller.Name}";
                    lock (SyncRoot.Get(fullName))
                    {
                        _logger.LogDebug($"Found: {fullName}");

                        if (arguments.Length != caller.GetParameters().Length)
                        {
                            throw new InvalidOperationException("ExecStoredProcedure is executed with invalid number of arguments");
                        }

                        var logger            = _parameters.LoggerFactory.CreateLogger($"{nameof(DbContextProxyHelper)}.{nameof(DbContextProxyHelper.CreateProxy)}");
                        var callerProxyMethod = _dbContextHelper.CreateProxy(caller, logger);

                        _logger.LogTrace("Calling proxy method");
                        var result = (T)callerProxyMethod.Invoke(null, arguments.Prepend(this).ToArray());
                        return(result);
                    }
                }
                catch (Exception e)
                {
                    _logger.LogError(e, e.Message);
                    throw;
                }
            }
        }
        public void Enqueue(T item, int timeoutMilliseconds = -1)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item", "item cannot be null");
            }

            if (IsDisposing || IsDisposed)
            {
                throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>));
            }

            using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable)
            {
                //While the queue is full, wait for an empty space
                //Timeout won't be exact if multiple enqueues are blocked on a full queue
                //So a dequeue could be followed by a different enqueue so this will wait
                //for another loop
                while (m_count == m_size)
                {
                    //Wait for a pulse from a dequeue
                    if (!syncLock.Wait(timeoutMilliseconds))
                    {
                        throw new TimeoutException("Enqueue timed out while waiting for available queue space");
                    }

                    //Double check not disposed since waiting for available space
                    if (IsDisposing || IsDisposed)
                    {
                        throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>));
                    }
                }

                m_items[m_tail++] = item;   // Place the new item immediately after tail, then increment tail pos
                m_tail           %= m_size; // Modulus new tail pos with size so queue items will wrap around
                m_count++;                  // Count will never be more than size after incrementing here

                //Signal that an item has been enqueued to unblock waiting
                //dequeue threads
                syncLock.PulseAll();
            }
        }
Exemple #18
0
        /// <summary>
        ///     Signals the completion of an upload.
        /// </summary>
        /// <param name="username">The username of the remote user.</param>
        /// <param name="filename">The completed filename.</param>
        public void Complete(string username, string filename)
        {
            SyncRoot.Wait();

            try
            {
                if (!Uploads.TryGetValue(username, out var list))
                {
                    throw new SlskdException($"No enqueued uploads for user {username}");
                }

                var upload = list.FirstOrDefault(e => e.Filename == filename);

                if (upload == default)
                {
                    throw new SlskdException($"File {filename} is not enqueued for user {username}");
                }

                list.Remove(upload);
                Log.Debug("Complete: {File} for {User} at {Time}", Path.GetFileName(upload.Filename), upload.Username, upload.Enqueued);

                // ensure the slot is returned to the group from which it was acquired the group may have been removed during the
                // transfer. if so, do nothing.
                if (Groups.ContainsKey(upload.Group ?? string.Empty))
                {
                    var group = Groups[upload.Group];

                    group.UsedSlots = Math.Max(0, group.UsedSlots - 1);
                    Log.Debug("Group {Group} slots: {Used}/{Available}", group.Name, group.UsedSlots, group.Slots);
                }

                if (!list.Any() && Uploads.TryRemove(username, out _))
                {
                    Log.Debug("Cleaned up tracking list for {User}; no more queued uploads to track", username);
                }
            }
            finally
            {
                SyncRoot.Release();
                Process();
            }
        }
Exemple #19
0
        /// <summary>
        /// Adds a new arena team member
        /// Calls ArenaTeamMgr.OnJoinTeam
        /// </summary>
        /// <param name="chr">character to add</param>
        /// <returns>ArenaTeamMember of new member</returns>
        public ArenaTeamMember AddMember(CharacterRecord chr)
        {
            ArenaTeamMember newMember;

            if (Members.Count >= Type * 2)
            {
                return(null);
            }

            SyncRoot.Enter();
            try
            {
                if (Members.TryGetValue(chr.EntityLowId, out newMember))
                {
                    return(newMember);
                }
                newMember = new ArenaTeamMember(chr, this, false);
                newMember.Character.SetArenaTeamInfoField(Slot, ArenaTeamInfoType.ARENA_TEAM_ID, Id);
                newMember.Character.SetArenaTeamInfoField(Slot, ArenaTeamInfoType.ARENA_TEAM_MEMBER, 1);

                Members.Add(newMember.Id, newMember);

                newMember.Create();
                Update();
            }
            catch (Exception e)
            {
                LogUtil.ErrorException(e, string.Format("Could not add member {0} to arena team {1}", chr, this));
                return(null);
            }
            finally
            {
                SyncRoot.Exit();
            }

            ArenaMgr.RegisterArenaTeamMember(newMember);

            //ArenaTeamHandler.SendEventToTeam(this, ArenaTeamEvents.JOINED_SS, newMember);

            return(newMember);
        }
Exemple #20
0
        private async Task AttemptReconnect()
        {
            if (await SyncRoot.WaitAsync(0))
            {
                try
                {
                    if (State.CurrentValue.Server.IsConnected)
                    {
                        return;
                    }

                    var attempts = 1;

                    while (true)
                    {
                        var(delay, jitter) = Compute.ExponentialBackoffDelay(
                            iteration: attempts,
                            maxDelayInMilliseconds: ReconnectMaxDelayMilliseconds);

                        var approximateDelay = (int)Math.Ceiling((double)(delay + jitter) / 1000);
                        Log.Information($"Waiting about {(approximateDelay == 1 ? "a second" : $"{approximateDelay} seconds")} before reconnecting");
                        await Task.Delay(delay + jitter);

                        Log.Information("Attempting to reconnect (#{Attempts})...", attempts);

                        try
                        {
                            // reconnect with the latest configuration values we have for username and password, instead of the
                            // options that were captured at startup. if a user has updated these values prior to the disconnect,
                            // the changes will take effect now.
                            await Client.ConnectAsync(Options.CurrentValue.Soulseek.Username, Options.CurrentValue.Soulseek.Password);

                            break;
                        }
                        catch (Exception ex)
                        {
                            attempts++;
                            Log.Error("Failed to reconnect: {Message}", ex.Message);
                        }
                    }
                }
Exemple #21
0
        /// <summary>
        /// <c>TryObtain</c> an object and remove it from the pool - does not throw an exception if pool is empty
        /// </summary>
        /// <param name="item">the object obtained from the pool, if successful - null if unsuccessful</param>
        /// <returns>returns true if successful, false if unsuccessful i.e. pool is empty</returns>
        /// <exception cref="ObjectDisposedException">throws when accessed during or after disposal</exception>
        public bool TryObtain(out T item)
        {
            using (SyncRoot.Enter())
            {
                //This is called from Obtain so only need to check dispose state here
                if (IsDisposing || IsDisposed)
                {
                    throw new ObjectDisposedException(nameof(PrimitiveObjectPool <T>));
                }

                if (m_internalStorage.TryTake(out item)) //This will decrement count
                {
                    InUse++;
                    return(true);
                }
                else //if bag is empty
                {
                    return(false);
                }
            }
        }
Exemple #22
0
        /// <summary>
        /// <c>Obtain</c> and remove an object from the pool - increases pool size if the pool is empty
        /// </summary>
        /// <returns>returns an object of type <typeparamref name="T"/> from the pool</returns>
        /// <exception cref="ObjectDisposedException">throws when accessed during or after disposal</exception>
        public override T Obtain()
        {
            if (TryObtain(out T item))
            {
                return(item);
            }
            else //If the pool is empty
            {
                using (SyncRoot.Enter())
                {
                    if (IsDisposing || IsDisposed)
                    {
                        throw new ObjectDisposedException(nameof(PrimitiveObjectPool <T>));
                    }

                    InUse++;
                    Size++;          //Increment Size so releasing item will just add to pool in TryRelease
                    return(new T()); //Create new item
                }
            }
        }
        public bool TryPeek(out T item, int timeoutMilliseconds = 0)
        {
            //This method only throws exception on thread lock timeout
            using (SyncRoot.Enter(timeoutMilliseconds))
            {
                if (IsDisposing || IsDisposed)
                {
                    item = null;
                    return(false);
                }

                if (m_count == 0)
                {
                    item = null;
                    return(false);
                }

                item = m_items[m_head];
                return(true);
            }
        }
        public T Peek(int timeoutMilliseconds = -1, bool waitForEnqueue = false)
        {
            using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable)
            {
                if (IsDisposing || IsDisposed)
                {
                    throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>));
                }

                if (m_count == 0)
                {
                    if (waitForEnqueue)
                    {
                        //While queue is empty, wait for an item to enqueue
                        while (m_count == 0)
                        {
                            //Wait for a signal from an enqueue
                            if (!syncLock.Wait(timeoutMilliseconds))
                            {
                                throw new TimeoutException("Dequeue timed out while waiting for queue item to dequeue");
                            }

                            //Double check not disposed since waiting for item to be enqueued
                            if (IsDisposing || IsDisposed)
                            {
                                throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>));
                            }
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Bounded Blocking Queue is empty");
                    }
                }

                T value = m_items[m_head];
                return(value);
            }
        }
Exemple #25
0
        private IEnumerable <Soulseek.File> QueryTable(string text)
        {
            // sanitize the query string. there's probably more to it than this.
            text = text
                   .Replace("/", " ")
                   .Replace("\\", " ")
                   .Replace(":", " ")
                   .Replace("\"", " ");

            var query = $"SELECT * FROM cache WHERE cache MATCH '\"{text.Replace("'", "''")}\"'";

            SyncRoot.EnterReadLock();

            try
            {
                using (var cmd = new SqliteCommand(query, SQLite))
                {
                    var results = new List <string>();
                    var reader  = cmd.ExecuteReader();

                    while (reader.Read())
                    {
                        results.Add(reader.GetString(0));
                    }

                    return(results.Select(r => Files[r.Replace("''", "'")]));
                }
            }
            catch (Exception ex)
            {
                // temporary error trap to refine substitution rules
                Console.WriteLine($"[MALFORMED QUERY]: {query} ({ex.Message})");
                return(Enumerable.Empty <Soulseek.File>());
            }
            finally
            {
                SyncRoot.ExitReadLock();
            }
        }
        public T Dequeue(int timeoutMilliseconds = -1)
        {
            if (IsDisposing || IsDisposed)
            {
                throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>));
            }

            using (IWaitable syncLock = SyncRoot.Enter(timeoutMilliseconds) as IWaitable)
            {
                //Similar reasoning for here from Enqueue method
                //While queue is empty, wait for an item to enqueue
                while (m_count == 0)
                {
                    //Wait for a signal from an enqueue
                    if (!syncLock.Wait(timeoutMilliseconds))
                    {
                        throw new TimeoutException("Dequeue timed out while waiting for queue item to dequeue");
                    }

                    //Double check not disposed since waiting for item to be enqueued
                    if (IsDisposing || IsDisposed)
                    {
                        throw new ObjectDisposedException(nameof(BoundedBlockingQueue <T>));
                    }
                }

                T value = m_items[m_head];  // Get item at head of queue
                m_items[m_head++] = null;   // Clear item at head of queue then increment head pos
                m_head           %= m_size; // Modulus new head pos with size so queue items will wrap around
                m_count--;                  // Count will never be less than zero after decrementing here

                //Signal that an item has been dequeued to unblock waiting
                //enqueue threads
                syncLock.PulseAll();

                return(value);
            }
        }
Exemple #27
0
        /// <summary>
        /// Сохраняет свою сделку.
        /// </summary>
        /// <param name="fill">Данные своей сделки.</param>
        protected void AddFill(FillMessage fill)
        {
            if (!storeFillsInMemory)
            {
                return;
            }

            if (!IsPermittedAccount(fill.Account))
            {
                return;
            }

            using (SyncRoot.Lock())
            {
                Dictionary <Instrument, List <FillMessage> > accountFills;

                if (!AvailableAccounts.Contains(fill.Account))
                {
                    AvailableAccounts.Add(fill.Account);
                    accountFills = new Dictionary <Instrument, List <FillMessage> >();
                    Fills.Add(fill.Account, accountFills);
                }
                else
                {
                    accountFills = Fills[fill.Account];
                }

                List <FillMessage> instrumentFills;

                if (!accountFills.TryGetValue(fill.Instrument, out instrumentFills))
                {
                    instrumentFills = new List <FillMessage>();
                    accountFills.Add(fill.Instrument, instrumentFills);
                }

                instrumentFills.Add(fill);
            }
        }
Exemple #28
0
        /// <summary>
        /// <c>TryRelease</c> an object and add it back into the pool - does not throw exception if pool is full
        /// </summary>
        /// <param name="item">the object released back into the pool</param>
        /// <returns>returns true if successful, false if successful i.e. if pool is full</returns>
        /// <exception cref="ObjectDisposedException">throws when accessed during or after disposal</exception>
        public bool TryRelease(T item)
        {
            using (SyncRoot.Enter())
            {
                //This is called from Obtain so only need to check dispose state here
                if (IsDisposing || IsDisposed)
                {
                    throw new ObjectDisposedException(nameof(PrimitiveObjectPool <T>));
                }

                //If storage bag is full i.e., equal to initial size, don't release item into bag
                if (m_internalStorage.Count == Size)
                {
                    return(false);
                }
                else
                {
                    m_internalStorage.Add(item); //This will increment storage bag count
                    InUse--;
                    return(true);
                }
            }
        }
Exemple #29
0
        protected bool AddAccount(string account)
        {
            if (string.IsNullOrWhiteSpace(account))
            {
                return(false);
            }

            if (!IsPermittedAccount(account))
            {
                return(false);
            }

            using (SyncRoot.Lock())
            {
                if (AvailableAccounts.Contains(account))
                {
                    return(false);
                }

                AvailableAccounts.Add(account);
                Fills.Add(account, new Dictionary <Instrument, List <FillMessage> >());
                return(true);
            }
        }
 public void Exit()
 {
     SyncRoot.Exit();
 }