/// <summary> /// Finds the <see cref="T:MemcachedNode"/> which is responsible for the specified item /// </summary> /// <param name="itemKey"></param> /// <returns></returns> private MemcachedNode LocateNode(string itemKey) { this.serverAccessLock.AcquireReaderLock(Timeout.Infinite); try { MemcachedNode node = this.NodeLocator.Locate(itemKey); if (node == null) { return(null); } if (node.IsAlive) { return(node); } this.MarkAsDead(node); return(this.LocateNode(itemKey)); } finally { this.serverAccessLock.ReleaseLock(); } }
internal InternalPoolImpl( MemcachedNode ownerNode, ISocketPoolConfiguration config, ILogger logger) { if (config.MinPoolSize < 0) { throw new InvalidOperationException("minItems must be larger >= 0", null); } if (config.MaxPoolSize < config.MinPoolSize) { throw new InvalidOperationException("maxItems must be larger than minItems", null); } if (config.QueueTimeout < TimeSpan.Zero) { throw new InvalidOperationException("queueTimeout must be >= TimeSpan.Zero", null); } this.ownerNode = ownerNode; this.isAlive = true; _endPoint = ownerNode.EndPoint; this.queueTimeout = config.QueueTimeout; this.minItems = config.MinPoolSize; this.maxItems = config.MaxPoolSize; _semaphore = new SemaphoreSlim(maxItems, maxItems); _freeItems = new InterlockedStack <PooledSocket>(); _logger = logger; _isDebugEnabled = _logger.IsEnabled(LogLevel.Debug); }
internal InternalPoolImpl(MemcachedNode ownerNode, ISocketPoolConfiguration config) { if (config.MinPoolSize < 0) { throw new InvalidOperationException("minItems must be larger >= 0", null); } if (config.MaxPoolSize < config.MinPoolSize) { throw new InvalidOperationException("maxItems must be larger than minItems", null); } if (config.QueueTimeout < TimeSpan.Zero) { throw new InvalidOperationException("queueTimeout must be >= TimeSpan.Zero", null); } this.ownerNode = ownerNode; this.isAlive = true; this.endPoint = ownerNode.EndPoint; this.queueTimeout = config.QueueTimeout; this.minItems = config.MinPoolSize; this.maxItems = config.MaxPoolSize; this.semaphore = new Semaphore(maxItems, maxItems); this.freeItems = new InterlockedStack <PooledSocket>(); }
internal InternalPoolImpl(MemcachedNode ownerNode, ISocketPoolConfiguration config) { if (config.MinPoolSize < 0) { throw new InvalidOperationException("Min pool size must be larger >= 0", null); } if (config.MaxPoolSize < config.MinPoolSize) { throw new InvalidOperationException("Max pool size must be larger than min pool size", null); } if (config.QueueTimeout < TimeSpan.Zero) { throw new InvalidOperationException("queueTimeout must be >= TimeSpan.Zero", null); } this._ownerNode = ownerNode; this._endpoint = ownerNode.EndPoint; this._queueTimeout = config.QueueTimeout; this._minItems = config.MinPoolSize; this._maxItems = config.MaxPoolSize; this._semaphore = new Semaphore(this._maxItems, this._maxItems); this._freeItems = new InterlockedStack <PooledSocket>(); this._logger = Logger.CreateLogger <InternalPoolImpl>(); }
/// <summary> /// Releases all resources allocated by this instance /// </summary> public void Dispose() { // 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 if (!this.isDisposed) { this.isAlive = false; this.isDisposed = true; PooledSocket ps; while (this.freeItems.TryPop(out ps)) { try { ps.Destroy(); } catch { } } this.ownerNode = null; this.semaphore.Close(); this.semaphore = null; this.freeItems = null; } }
private static List <uint> GenerateKeys(MemcachedNode node, int numberOfKeys) { const int KeyLength = 4; const int PartCount = 1; // (ModifiedFNV.HashSize / 8) / KeyLength; // HashSize is in bits, uint is 4 byte long //if (partCount < 1) // throw new ArgumentOutOfRangeException("The hash algorithm must provide at least 32 bits long hashes"); List <uint> k = new List <uint>(PartCount * numberOfKeys); // every server is registered numberOfKeys times // using UInt32s generated from the different parts of the hash // i.e. hash is 64 bit: // 00 00 aa bb 00 00 cc dd // server will be stored with keys 0x0000aabb & 0x0000ccdd // (or a bit differently based on the little/big indianness of the host) string address = node.EndPoint.ToString(); for (int i = 0; i < numberOfKeys; i++) { byte[] data = new FNV1a().ComputeHash(Encoding.ASCII.GetBytes(String.Concat(address, "-", i))); for (int h = 0; h < PartCount; h++) { k.Add(BitConverter.ToUInt32(data, h * KeyLength)); } } return(k); }
protected virtual IMemcachedNode CreateNode(EndPoint endpoint, Action <IMemcachedNode> onNodeFailed = null) { var node = new MemcachedNode(endpoint, this._configuration.SocketPool); if (onNodeFailed != null) { node.Failed += onNodeFailed; } return(node); }
public PooledSocket Acquire(string itemKey) { if (this.serverAccessLock == null) { throw new ObjectDisposedException("ServerPool"); } MemcachedNode server = this.LocateNode(itemKey); if (server == null) { return(null); } return(server.Acquire()); }
void IMemcachedNodeLocator.Initialize(IList<MemcachedNode> nodes) { if (this.isInitialized) throw new InvalidOperationException("Instance is already initialized."); // locking on this is rude but easy lock (this) { if (this.isInitialized) throw new InvalidOperationException("Instance is already initialized."); if (nodes.Count > 0) node = nodes[0]; this.isInitialized = true; } }
/// <summary> /// Marks a node as dead (unusable) /// - moves hte node to the "dead list" /// - recreates the locator based on the new list of still functioning servers /// </summary> /// <param name="node"></param> private void MarkAsDead(MemcachedNode node) { this.serverAccessLock.UpgradeToWriterLock(Timeout.Infinite); try { // server gained AoeREZ while AFK? if (!node.IsAlive) { this.workingServers.Remove(node); this.deadServers.Add(node); this.RebuildIndexes(); } } finally { this.serverAccessLock.ReleaseLock(); } }
public IDictionary <MemcachedNode, IList <string> > SplitKeys(IEnumerable <string> keys) { Dictionary <MemcachedNode, IList <string> > keysByNode = new Dictionary <MemcachedNode, IList <string> >(MemcachedNode.Comparer.Instance); foreach (string key in keys) { MemcachedNode node = LocateNode(key); IList <string> nodeKeys; if (!keysByNode.TryGetValue(node, out nodeKeys)) { nodeKeys = new List <string>(); keysByNode.Add(node, nodeKeys); } nodeKeys.Add(key); } return(keysByNode); }
void IMemcachedNodeLocator.Initialize(IList <MemcachedNode> nodes) { if (this.isInitialized) { throw new InvalidOperationException("Instance is already initialized."); } // locking on this is rude but easy lock (this) { if (this.isInitialized) { throw new InvalidOperationException("Instance is already initialized."); } if (nodes.Count > 0) { node = nodes[0]; } this.isInitialized = true; } }
void Dispose(bool disposing) { if (disposing && !isDisposed) { GC.SuppressFinalize(this); } if (!isDisposed) { new Timer((s) => { if (!this.isDisposed) { log.Debug("Disposing InternalPoolImpl"); IPooledSocket ps; while (this.freeItems.TryPop(out ps)) { try { ps.Dispose(); } catch (Exception e) { log.Error(e); } } this.ownerNode = null; this.semaphore.Close(); this.semaphore = null; this.freeItems = null; this.isAlive = false; this.isDisposed = true; } }, null, 1000, Timeout.Infinite); } }
protected abstract void WriteNodeInfo(MemcachedNode node);
protected override void WriteNodeInfo(MemcachedNode node) { WriteVerbose(Key + " - decrementing on - " + node.EndPoint.ToString()); }
protected override void WriteNodeInfo(MemcachedNode node) { WriteVerbose(Key + " - retrieving from - " + node.EndPoint.ToString()); }
public static void Publish(MemcachedNode node) { registrants.ForEach(a => a.Invoke(node)); }
/// <summary> /// Marks a node as dead (unusable) /// - moves hte node to the "dead list" /// - recreates the locator based on the new list of still functioning servers /// </summary> /// <param name="node"></param> private void MarkAsDead(MemcachedNode node) { this.serverAccessLock.UpgradeToWriterLock(Timeout.Infinite); try { // server gained AoeREZ while AFK? if (!node.IsAlive) { this.workingServers.Remove(node); this.deadServers.Add(node); this.RebuildIndexes(); } } finally { this.serverAccessLock.ReleaseLock(); } }
public InstancePerformanceCounters(MemcachedNode node) : this(node.EndPoint.ToString()) { }
private static List<uint> GenerateKeys(MemcachedNode node, int numberOfKeys) { const int KeyLength = 4; const int PartCount = 1; // (ModifiedFNV.HashSize / 8) / KeyLength; // HashSize is in bits, uint is 4 byte long //if (partCount < 1) // throw new ArgumentOutOfRangeException("The hash algorithm must provide at least 32 bits long hashes"); List<uint> k = new List<uint>(PartCount * numberOfKeys); // every server is registered numberOfKeys times // using UInt32s generated from the different parts of the hash // i.e. hash is 64 bit: // 00 00 aa bb 00 00 cc dd // server will be stored with keys 0x0000aabb & 0x0000ccdd // (or a bit differently based on the little/big indianness of the host) string address = node.EndPoint.ToString(); for (int i = 0; i < numberOfKeys; i++) { byte[] data = new FNV1a().ComputeHash(Encoding.ASCII.GetBytes(String.Concat(address, "-", i))); for (int h = 0; h < PartCount; h++) { k.Add(BitConverter.ToUInt32(data, h * KeyLength)); } } return k; }