Esempio n. 1
0
        public MemcachedNode(
            EndPoint endpoint,
            ISocketPoolConfiguration socketPoolConfig,
            ILogger logger)
        {
            this.endPoint = endpoint;
            this.config   = socketPoolConfig;

            if (socketPoolConfig.ConnectionTimeout.TotalMilliseconds >= Int32.MaxValue)
            {
                throw new InvalidOperationException("ConnectionTimeout must be < Int32.MaxValue");
            }

            if (socketPoolConfig.InitPoolTimeout.TotalSeconds < 1)
            {
                _initPoolTimeout = new TimeSpan(0, 1, 0);
            }
            else
            {
                _initPoolTimeout = socketPoolConfig.InitPoolTimeout;
            }

            _logger = logger;
            this.internalPoolImpl = new InternalPoolImpl(this, socketPoolConfig, _logger);
        }
        /// <summary>
        /// Gets a value indicating whether the server is working or not.
        /// If the server is back online, we'll ercreate the internal socket pool and mark the server as alive so operations can target it.
        /// </summary>
        /// <returns>true if the server is alive; false otherwise.</returns>
        public bool Ping()
        {
            // is the server working?
            if (this.IsAlive)
            {
                return(true);
            }

            // this codepath is (should be) called very rarely
            // if you get here hundreds of times then you have bigger issues
            // and try to make the memcached instaces more stable and/or increase the deadTimeout
            try
            {
                // we could connect to the server, let's recreate the socket pool
                lock (MemcachedNode.Locker)
                {
                    if (this._isDisposed)
                    {
                        return(false);
                    }

                    // try to connect to the server
                    using (var socket = this.CreateSocket())
                    {
                        if (this._logger.IsEnabled(LogLevel.Debug))
                        {
                            this._logger.LogDebug($"Try to connect to the memcached server: {this.EndPoint}");
                        }
                    }

                    if (this.IsAlive)
                    {
                        return(true);
                    }

                    // it's easier to create a new pool than reinitializing a dead one
                    // rewrite-then-dispose to avoid a race condition with Acquire (which does no locking)
                    var oldPool = this._internalPoolImpl;
                    var newPool = new InternalPoolImpl(this, this._config);
                    Interlocked.Exchange(ref this._internalPoolImpl, newPool);
                    try
                    {
                        oldPool.Dispose();
                    }
                    catch { }
                }

                return(true);
            }
            catch
            {
                return(false);                  // could not reconnect
            }
        }
Esempio n. 3
0
        public MemcachedNode(IPEndPoint endpoint, ISocketPoolConfiguration socketPoolConfig)
        {
            this.endPoint = endpoint;
            this.config   = socketPoolConfig;

            if (socketPoolConfig.ConnectionTimeout.TotalMilliseconds >= Int32.MaxValue)
            {
                throw new InvalidOperationException("ConnectionTimeout must be < Int32.MaxValue");
            }

            this.internalPoolImpl = new InternalPoolImpl(this, socketPoolConfig);
        }
        internal MemcachedNode(IPEndPoint endpoint, ISocketPoolConfiguration config)
        {
            endPoint         = endpoint;
            this.config      = config;
            internalPoolImpl = new InternalPoolImpl(endpoint, config);

            deadTimeout = (int)config.DeadTimeout.TotalSeconds;
            if (deadTimeout < 0)
            {
                throw new InvalidOperationException("deadTimeout must be >= TimeSpan.Zero");
            }
        }
        public MemcachedNode(EndPoint endpoint, ISocketPoolConfiguration config)
        {
            if (config.ConnectionTimeout.TotalMilliseconds >= Int32.MaxValue)
            {
                throw new InvalidOperationException($"ConnectionTimeout must be < {Int32.MaxValue}");
            }

            this._logger           = Logger.CreateLogger <IMemcachedNode>();
            this._endpoint         = endpoint;
            this._config           = config;
            this._internalPoolImpl = new InternalPoolImpl(this, this._config);
        }
        /// <summary>
        /// Gets a value indicating whether the server is working or not.
        ///
        /// If the server is not working, and the "being dead" timeout has been expired it will reinitialize itself.
        /// </summary>
        /// <remarks>It's possible that the server is still not up &amp; running so the next call to <see cref="M:Acquire"/> could mark the instance as dead again.</remarks>
        /// <returns></returns>
        internal bool Ping()
        {
            // is the server working?
            if (internalPoolImpl.IsAlive)
            {
                return(true);
            }

            // deadTimeout was set to 0 which means forever
            if (deadTimeout == 0)
            {
                return(false);
            }

            TimeSpan diff = DateTime.UtcNow - internalPoolImpl.MarkedAsDeadUtc;

            // only do the real check if the configured time interval has passed
            if (diff.TotalSeconds < deadTimeout)
            {
                return(false);
            }

            // it's (relatively) safe to lock on 'this' since
            // this codepath is (should be) called very rarely
            // if you get here hundreds of times then you have bigger issues
            // and try to make the memcached instaces more stable and/or increase the deadTimeout
            lock (this)
            {
                if (internalPoolImpl.IsAlive)
                {
                    return(true);
                }

                // it's easier to create a new pool than reinitializing a dead one
                internalPoolImpl.Dispose();

                if (endPoint != null)
                {
                    internalPoolImpl = new InternalPoolImpl(endPoint, config);
                }
            }

            return(true);
        }
        /// <summary>
        /// Releases all resources allocated by this instance
        /// </summary>
        public void Dispose()
        {
            GC.SuppressFinalize(this);

            // this is not a graceful shutdown
            // if someone uses a pooled item then 99% that an exception will be thrown
            // somewhere. But since the dispose is mostly used when everyone else is finished
            // this should not kill any kittens
            lock (this)
            {
                if (isDisposed)
                {
                    return;
                }

                isDisposed = true;

                internalPoolImpl.Dispose();
                internalPoolImpl = null;
            }
        }