Exemple #1
0
        protected static void RemoveSocketFromPool(Hashtable pool, string host, SockIO socket)
        {
            if (string.IsNullOrEmpty(host) || pool == null)
            {
                return;
            }

            if (pool.ContainsKey(host))
            {
                var sockets = (Hashtable)pool[host];
                if (sockets != null)
                {
                    sockets.Remove(socket);
                }
            }
        }
        /// <summary>
        /// Increments/decrements the value at the specified key by inc.
        ///
        /// Note that the server uses a 32-bit unsigned integer, and checks for
        /// underflow. In the event of underflow, the result will be zero.  Because
        /// Java lacks unsigned types, the value is returned as a 64-bit integer.
        /// The server will only decrement a value if it already exists;
        /// if a value is not found, -1 will be returned.
        ///
        /// TODO: C# has unsigned types.  We can fix this.
        /// </summary>
        /// <param name="cmdname">increment/decrement</param>
        /// <param name="key">cache key</param>
        /// <param name="inc">amount to incr or decr</param>
        /// <param name="hashCode">if not null, then the int hashcode to use</param>
        /// <returns>new value or -1 if not exist</returns>
        private long IncrementOrDecrement(string cmdname, string key, long inc, object hashCode)
        {
            key = Prefix + key;

            // get SockIO obj for given cache key
            SockIO sock = SockIOPool.GetInstance(_poolName).GetSock(key, hashCode);

            if (sock == null)
            {
                return(-1);
            }

            try
            {
                string cmd = cmdname + " " + key + " " + inc + "\r\n";

                sock.Write(Encoding.UTF8.GetBytes(cmd));
                sock.Flush();

                // get result back
                string line = sock.ReadLine();

                if (new Regex("\\d+").Match(line).Success)
                {
                    // return sock to pool and return result
                    sock.Close();
                    return(long.Parse(line, new NumberFormatInfo()));
                }
            }
            catch (IOException e)
            {
                try
                {
                    sock.TrueClose();
                }
                finally
                {
                    sock = null;
                }
            }

            if (sock != null)
            {
                sock.Close();
            }
            return(-1);
        }
Exemple #3
0
        public void CheckIn(SockIO socket, bool addToAvail)
        {
            if (socket == null)
            {
                return;
            }

            string host = socket.Host;

            RemoveSocketFromPool(_busyPool, host, socket);

            // add to avail pool
            if (addToAvail && socket.IsConnected)
            {
                AddSocketToPool(_availPool, host, socket);
            }
        }
        /// <summary>
        /// Retrieve a key from the server, using a specific hash.
        ///
        /// If the data was compressed or serialized when compressed, it will automatically
        /// be decompressed or serialized, as appropriate. (Inclusive or)
        ///
        /// Non-serialized data will be returned as a string, so explicit conversion to
        /// numeric types will be necessary, if desired
        /// </summary>
        /// <param name="key">key where data is stored</param>
        /// <param name="hashCode">if not null, then the int hashcode to use</param>
        /// <param name="asString">if true, then return string val</param>
        /// <returns>the object that was previously stored, or null if it was not previously stored</returns>
        public object Get(string key, object hashCode, bool asString)
        {
            if (string.IsNullOrEmpty(key))
            {
                return(null);
            }
            key = Prefix + key;
            // get SockIO obj using cache key
            SockIO sock = SockIOPool.GetInstance(_poolName).GetSock(key, hashCode);

            if (sock == null)
            {
                return(null);
            }

            try
            {
                string cmd = "get " + key + "\r\n";

                sock.Write(Encoding.UTF8.GetBytes(cmd));
                sock.Flush();

                // build empty map
                // and fill it from server
                Hashtable hm = new Hashtable();
                LoadItems(sock, hm, asString);

                // return the value for this key if we found it
                // else return null
                sock.Close();
                return(hm[key]);
            }
            catch
            {
                try
                {
                    sock.TrueClose();
                }
                finally
                {
                    sock = null;
                }
            }
            return(null);
        }
Exemple #5
0
        /// <summary>
        /// Adds a socket to a given pool for the given host.
        ///
        /// Internal utility method.
        /// </summary>
        /// <param name="pool">pool to add to</param>
        /// <param name="host">host this socket is connected to</param>
        /// <param name="socket">socket to add</param>
        //[MethodImpl(MethodImplOptions.Synchronized)]
        protected static void AddSocketToPool(Hashtable pool, string host, SockIO socket)
        {
            if (pool == null || string.IsNullOrEmpty(host))
            {
                return;
            }

            Hashtable sockets;

            if (!string.IsNullOrEmpty(host) && pool.ContainsKey(host))
            {
                sockets = (Hashtable)pool[host];
                if (sockets != null)
                {
                    sockets[socket] = DateTime.Now; //MaxM 1.16.05: Use current DateTime to indicate socker creation time rather than milliseconds since 1970

                    return;
                }
            }

            sockets         = new Hashtable();
            sockets[socket] = DateTime.Now; //MaxM 1.16.05: Use current DateTime to indicate socker creation time rather than milliseconds since 1970
            pool[host]      = sockets;
        }
Exemple #6
0
        /// <summary>
        /// Creates a new SockIO obj for the given server.
        ///
        ///If server fails to connect, then return null and do not try
        ///again until a duration has passed.  This duration will grow
        ///by doubling after each failed attempt to connect.
        /// </summary>
        /// <param name="host">host:port to connect to</param>
        /// <returns>SockIO obj or null if failed to create</returns>
        protected SockIO CreateSocket(string host)
        {
            SockIO socket = null;

            // if host is dead, then we don't need to try again
            // until the dead status has expired
            // we do not try to put back in if failover is off
            if(_failover && _hostDead.ContainsKey(host) && _hostDeadDuration.ContainsKey(host))
            {

                DateTime store = (DateTime)_hostDead[host];
                long expire = ((long)_hostDeadDuration[host]);

                if((store.AddMilliseconds(expire)) > DateTime.Now)
                    return null;
            }

            try
            {
                socket = new SockIO(this, host, _socketTimeout, _socketConnectTimeout, _nagle);

                if (!socket.IsConnected)
                {
                    try
                    {
                        socket.TrueClose();
                    }
                    catch (SocketException)
                    {
                        socket = null;
                    }
                }
            }
            catch
            {
                socket = null;
            }

            // if we failed to get socket, then mark
            // host dead for a duration which falls off
            if(socket == null)
            {
                DateTime now = DateTime.Now;
                _hostDead[host] = now;
                long expire = (_hostDeadDuration.ContainsKey(host)) ? (((long)_hostDeadDuration[host]) * 2) : 100;
                _hostDeadDuration[host] = expire;
				
                // also clear all entries for this host from availPool
                ClearHostFromPool(_availPool, host);
            }
            else
            {
                _hostDead.Remove(host);
                _hostDeadDuration.Remove(host);
                if(_buckets.BinarySearch(host) < 0)
                    _buckets.Add(host);
            }

            return socket;
        }
Exemple #7
0
        /// <summary>
        /// Returns appropriate SockIO object given
        /// string cache key and optional hashcode.
        ///
        /// Trys to get SockIO from pool.  Fails over
        /// to additional pools in event of server failure.
        /// </summary>
        /// <param name="key">hashcode for cache key</param>
        /// <param name="hashCode">if not null, then the int hashcode to use</param>
        /// <returns>SockIO obj connected to server</returns>
        public SockIO GetSock(string key, object hashCode)
        {
            //string hashCodeString = "<null>";
            //if(hashCode != null)
            //    hashCodeString = hashCode.ToString();

            if (string.IsNullOrEmpty(key) || !_initialized || _buckets.Count == 0)
            {
                return(null);
            }

            // if only one server, return it
            if (_buckets.Count == 1)
            {
                return(GetConnection((string)_buckets[0]));
            }

            int tries = 0;

            int hv;

            if (hashCode != null)
            {
                hv = (int)hashCode;
            }
            else
            {
                // NATIVE_HASH = 0
                // OLD_COMPAT_HASH = 1
                // NEW_COMPAT_HASH = 2
                switch (_hashingAlgorithm)
                {
                case HashingAlgorithm.Native:
                    hv = key.GetHashCode();
                    break;

                case HashingAlgorithm.OldCompatibleHash:
                    hv = OriginalHashingAlgorithm(key);
                    break;

                case HashingAlgorithm.NewCompatibleHash:
                    hv = NewHashingAlgorithm(key);
                    break;

                default:
                    // use the native hash as a default
                    hv = key.GetHashCode();
                    _hashingAlgorithm = HashingAlgorithm.Native;
                    break;
                }
            }

            // keep trying different servers until we find one
            while (tries++ <= _buckets.Count)
            {
                // get bucket using hashcode
                // get one from factory
                int bucket = hv % _buckets.Count;
                if (bucket < 0)
                {
                    bucket += _buckets.Count;
                }

                SockIO sock = GetConnection((string)_buckets[bucket]);

                if (sock != null)
                {
                    return(sock);
                }

                // if we do not want to failover, then bail here
                if (!_failover)
                {
                    return(null);
                }

                // if we failed to get a socket from this server
                // then we try again by adding an incrementer to the
                // current key and then rehashing
                switch (_hashingAlgorithm)
                {
                case HashingAlgorithm.Native:
                    hv += ((string)("" + tries + key)).GetHashCode();
                    break;

                case HashingAlgorithm.OldCompatibleHash:
                    hv += OriginalHashingAlgorithm("" + tries + key);
                    break;

                case HashingAlgorithm.NewCompatibleHash:
                    hv += NewHashingAlgorithm("" + tries + key);
                    break;

                default:
                    // use the native hash as a default
                    hv += ((string)("" + tries + key)).GetHashCode();
                    _hashingAlgorithm = HashingAlgorithm.Native;
                    break;
                }
            }

            return(null);
        }
Exemple #8
0
        public SockIO GetConnection(string host)
        {
            if (!_initialized)
            {
                return(null);
            }

            if (host == null)
            {
                return(null);
            }

            // if we have items in the pool
            // then we can return it
            if (_availPool != null && _availPool.Count != 0)
            {
                // take first connected socket
                Hashtable aSockets = (Hashtable)_availPool[host];

                if (aSockets != null && aSockets.Count != 0)
                {
                    foreach (SockIO socket in new IteratorIsolateCollection(aSockets.Keys))
                    {
                        if (socket.IsConnected)
                        {
                            // remove from avail pool
                            aSockets.Remove(socket);

                            // add to busy pool
                            AddSocketToPool(_busyPool, host, socket);

                            // return socket
                            return(socket);
                        }
                        // remove from avail pool
                        aSockets.Remove(socket);
                    }
                }
            }

            // if here, then we found no sockets in the pool
            // try to create on a sliding scale up to maxCreate
            object cShift = _createShift[host];
            int    shift  = (cShift != null) ? (int)cShift : 0;

            int create = 1 << shift;

            if (create >= _maxCreate)
            {
                create = _maxCreate;
            }
            else
            {
                shift++;
            }

            // store the shift value for this host
            _createShift[host] = shift;

            for (int i = create; i > 0; i--)
            {
                SockIO socket = CreateSocket(host);
                if (socket == null)
                {
                    break;
                }

                if (i == 1)
                {
                    // last iteration, add to busy pool and return sockio
                    AddSocketToPool(_busyPool, host, socket);
                    return(socket);
                }
                // add to avail pool
                AddSocketToPool(_availPool, host, socket);
            }

            // should never get here
            return(null);
        }
Exemple #9
0
        public void Initialize()
        {
            // check to see if already initialized
            if (_initialized &&
                _buckets != null &&
                _availPool != null &&
                _busyPool != null)
            {
                return;
            }

            // initialize empty maps
            _buckets          = new ArrayList();
            _availPool        = new Hashtable(_servers.Count * _initConns);
            _busyPool         = new Hashtable(_servers.Count * _initConns);
            _hostDeadDuration = new Hashtable();
            _hostDead         = new Hashtable();
            _createShift      = new Hashtable();
            _maxCreate        = (_poolMultiplier > _minConns) ? _minConns : _minConns / _poolMultiplier;                // only create up to maxCreate connections at once

            // if servers is not set, or it empty, then
            // throw a runtime exception
            if (_servers == null || _servers.Count <= 0)
            {
                throw new ArgumentException();
            }

            for (int i = 0; i < _servers.Count; i++)
            {
                // add to bucket
                // with weights if we have them
                if (_weights != null && _weights.Count > i)
                {
                    for (int k = 0; k < ((int)_weights[i]); k++)
                    {
                        _buckets.Add(_servers[i]);
                    }
                }
                else
                {
                    _buckets.Add(_servers[i]);
                }

                for (int j = 0; j < _initConns; j++)
                {
                    SockIO socket = CreateSocket((string)_servers[i]);
                    if (socket == null)
                    {
                        break;
                    }

                    AddSocketToPool(_availPool, (string)_servers[i], socket);
                }
            }

            // mark pool as initialized
            _initialized = true;

            // start maint thread TODO: re-enable
            if (_maintThreadSleep > 0)
            {
                this.StartMaintenanceThread();
            }
        }
Exemple #10
0
        /// <summary>
        /// Creates a new SockIO obj for the given server.
        ///
        ///If server fails to connect, then return null and do not try
        ///again until a duration has passed.  This duration will grow
        ///by doubling after each failed attempt to connect.
        /// </summary>
        /// <param name="host">host:port to connect to</param>
        /// <returns>SockIO obj or null if failed to create</returns>
        protected SockIO CreateSocket(string host)
        {
            SockIO socket = null;

            // if host is dead, then we don't need to try again
            // until the dead status has expired
            // we do not try to put back in if failover is off
            if (_failover && _hostDead.ContainsKey(host) && _hostDeadDuration.ContainsKey(host))
            {
                DateTime store  = (DateTime)_hostDead[host];
                long     expire = ((long)_hostDeadDuration[host]);

                if ((store.AddMilliseconds(expire)) > DateTime.Now)
                {
                    return(null);
                }
            }

            try
            {
                socket = new SockIO(this, host, _socketTimeout, _socketConnectTimeout, _nagle);

                if (!socket.IsConnected)
                {
                    try
                    {
                        socket.TrueClose();
                    }
                    catch (SocketException)
                    {
                        socket = null;
                    }
                }
            }
            catch
            {
                socket = null;
            }

            // if we failed to get socket, then mark
            // host dead for a duration which falls off
            if (socket == null)
            {
                DateTime now = DateTime.Now;
                _hostDead[host] = now;
                long expire = (_hostDeadDuration.ContainsKey(host)) ? (((long)_hostDeadDuration[host]) * 2) : 100;
                _hostDeadDuration[host] = expire;

                // also clear all entries for this host from availPool
                ClearHostFromPool(_availPool, host);
            }
            else
            {
                _hostDead.Remove(host);
                _hostDeadDuration.Remove(host);
                if (_buckets.BinarySearch(host) < 0)
                {
                    _buckets.Add(host);
                }
            }

            return(socket);
        }
Exemple #11
0
        public void CheckIn(SockIO socket, bool addToAvail)
        {
            if (socket == null)
                return; 

            string host = socket.Host;
            RemoveSocketFromPool(_busyPool, host, socket);

            // add to avail pool
            if(addToAvail && socket.IsConnected)
            {
                AddSocketToPool(_availPool, host, socket);
            }
        }
Exemple #12
0
 public void CheckIn(SockIO socket)
 {
     CheckIn(socket, true);
 }
Exemple #13
0
 public void CheckIn(SockIO socket)
 {
     CheckIn(socket, true);
 }
        /// <summary>
        /// Invalidates the entire cache.
        ///
        /// Will return true only if succeeds in clearing all servers.
        /// If pass in null, then will try to flush all servers.
        /// </summary>
        /// <param name="servers">optional array of host(s) to flush (host:port)</param>
        /// <returns>success true/false</returns>
        public bool FlushAll(ArrayList servers)
        {
            // get SockIOPool instance
            SockIOPool pool = SockIOPool.GetInstance(_poolName);

            // return false if unable to get SockIO obj
            if (pool == null)
            {
                return(false);
            }

            // get all servers and iterate over them
            if (servers == null)
            {
                servers = pool.Servers;
            }

            // if no servers, then return early
            if (servers == null || servers.Count <= 0)
            {
                return(false);
            }

            bool success = true;

            for (int i = 0; i < servers.Count; i++)
            {
                SockIO sock = pool.GetConnection((string)servers[i]);
                if (sock == null)
                {
                    success = false;
                    continue;
                }

                // build command
                string command = "flush_all\r\n";

                try
                {
                    sock.Write(Encoding.UTF8.GetBytes(command));
                    sock.Flush();

                    // if we get appropriate response back, then we return true
                    string line = sock.ReadLine();
                    success = (OK == line)
                                                ? success && true
                                                : false;
                }
                catch (IOException e)
                {
                    try
                    {
                        sock.TrueClose();
                    }
                    catch {}

                    success = false;
                    sock    = null;
                }

                if (sock != null)
                {
                    sock.Close();
                }
            }

            return(success);
        }
        /// <summary>
        /// Retrieves stats for passed in servers (or all servers).
        ///
        /// Returns a map keyed on the servername.
        /// The value is another map which contains stats
        /// with stat name as key and value as value.
        /// </summary>
        /// <param name="servers">string array of servers to retrieve stats from, or all if this is null</param>
        /// <returns>Stats map</returns>
        public Hashtable Stats(ArrayList servers)
        {
            // get SockIOPool instance
            SockIOPool pool = SockIOPool.GetInstance(_poolName);

            // return false if unable to get SockIO obj
            if (pool == null)
            {
                return(null);
            }

            // get all servers and iterate over them
            if (servers == null)
            {
                servers = pool.Servers;
            }

            // if no servers, then return early
            if (servers == null || servers.Count <= 0)
            {
                return(null);
            }

            // array of stats Hashtables
            Hashtable statsMaps = new Hashtable();

            for (int i = 0; i < servers.Count; i++)
            {
                SockIO sock = pool.GetConnection((string)servers[i]);
                if (sock == null)
                {
                    continue;
                }

                // build command
                string command = "stats\r\n";

                try
                {
                    sock.Write(UTF8Encoding.UTF8.GetBytes(command));
                    sock.Flush();

                    // map to hold key value pairs
                    Hashtable stats = new Hashtable();

                    // loop over results
                    while (true)
                    {
                        string line = sock.ReadLine();

                        if (line.StartsWith(STATS))
                        {
                            string[] info = line.Split(' ');
                            string   key  = info[1];
                            string   val  = info[2];

                            stats[key] = val;
                        }
                        else if (END == line)
                        {
                            break;
                        }

                        statsMaps[servers[i]] = stats;
                    }
                }
                catch (IOException e)
                {
                    try
                    {
                        sock.TrueClose();
                    }
                    catch (IOException)
                    {
                    }

                    sock = null;
                }

                if (sock != null)
                {
                    sock.Close();
                }
            }

            return(statsMaps);
        }
		/// <summary>
		/// This method loads the data from cache into a Hashtable.
		/// 
		/// Pass a SockIO object which is ready to receive data and a Hashtable
		/// to store the results.
		/// </summary>
		/// <param name="sock">socket waiting to pass back data</param>
		/// <param name="hm">hashmap to store data into</param>
		/// <param name="asString">if true, and if we are using NativehHandler, return string val</param>
		private void LoadItems(SockIO sock, Hashtable hm, bool asString) 
		{
			while(true) 
			{
				string line = sock.ReadLine();

				if(line.StartsWith(VALUE)) 
				{
					string[] info = line.Split(' ');
					string key    = info[1];
					int flag      = int.Parse(info[2], new NumberFormatInfo());
					int length    = int.Parse(info[3], new NumberFormatInfo());
				
					// read obj into buffer
					byte[] buf = new byte[length];
					sock.Read(buf);
					sock.ClearEndOfLine();

					// ready object
					object o=null;
				
					// check for compression
					if((flag & F_COMPRESSED) != 0)
					{
					    MemoryStream mem = null;
					    GZipStream gzi = null;
						try 
						{
							// read the input stream, and write to a byte array output stream since
							// we have to read into a byte array, but we don't know how large it
							// will need to be, and we don't want to resize it a bunch
                            mem = new MemoryStream(buf.Length);
						    gzi = new GZipStream(new MemoryStream(buf), CompressionMode.Compress);
							
							int count;
							var tmp = new byte[2048];
                            while ((count = gzi.Read(tmp, 0, tmp.Length)) > 0)
                            {
                                mem.Write(tmp, 0, count);
                            }

						    // store uncompressed back to buffer
							buf = mem.ToArray();
						}
						finally
						{
						    if(mem!=null)
						    {
						        mem.Close();
                                mem.Dispose();
						    }
                            if(gzi != null)
                            {
                                gzi.Close();
                                gzi.Dispose();
                            }
						}
					}

					// we can only take out serialized objects
					if((flag & F_SERIALIZED) == 0) 
					{
						if(_primitiveAsString || asString) 
						{
							o = Encoding.GetEncoding(_defaultEncoding).GetString(buf);
						}
						else 
						{
							// decoding object
							try 
							{
								o = NativeHandler.Decode(buf);    
							}
							catch(Exception e) 
							{
                                return;
							}
						}
					}
					else 
					{
						// deserialize if the data is serialized
					    MemoryStream memStream = null;
						try 
						{
							memStream = new MemoryStream(buf);
							o = new BinaryFormatter().Deserialize(memStream);
						}
						catch(SerializationException e) 
						{
						}
                        finally
						{
						    if(memStream != null)
						    {
						        memStream.Close();
                                memStream.Dispose();
						    }
						}
					}

					// store the object into the cache
					hm[ key ] =  o ;
				}
				else if(END == line) 
				{
					break;
				}
			}
		}
        /// <summary>
        /// Retrieve multiple objects from the memcache.
        ///
        /// This is recommended over repeated calls to <see cref="get">get(string)</see>, since it
        /// is more efficient.
        /// </summary>
        /// <param name="keys">string array of keys to retrieve</param>
        /// <param name="hashCodes">hashCodes if not null, then the int array of hashCodes</param>
        /// <param name="asString">if true then retrieve using string val</param>
        /// <returns>
        /// a hashmap with entries for each key is found by the server,
        /// keys that are not found are not entered into the hashmap, but attempting to
        /// retrieve them from the hashmap gives you null.
        /// </returns>
        public Hashtable GetMultiple(string[] keys, int[] hashCodes, bool asString)
        {
            if (keys == null)
            {
                return(new Hashtable());
            }

            Hashtable sockKeys = new Hashtable();

            for (int i = 0; i < keys.Length; ++i)
            {
                object hash = null;
                if (hashCodes != null && hashCodes.Length > i)
                {
                    hash = hashCodes[i];
                }

                // get SockIO obj from cache key
                SockIO sock = SockIOPool.GetInstance(_poolName).GetSock(Prefix + keys[i], hash);

                if (sock == null)
                {
                    continue;
                }

                // store in map and list if not already
                if (!sockKeys.ContainsKey(sock.Host))
                {
                    sockKeys[sock.Host] = new StringBuilder();
                }

                ((StringBuilder)sockKeys[sock.Host]).Append(" " + Prefix + keys[i]);

                // return to pool
                sock.Close();
            }

            // now query memcache
            Hashtable ret      = new Hashtable();
            ArrayList toRemove = new ArrayList();

            foreach (string host in sockKeys.Keys)
            {
                // get SockIO obj from hostname
                SockIO sock = SockIOPool.GetInstance(_poolName).GetConnection(host);

                try
                {
                    string cmd = "get" + (StringBuilder)sockKeys[host] + "\r\n";
                    sock.Write(Encoding.UTF8.GetBytes(cmd));
                    sock.Flush();
                    LoadItems(sock, ret, asString);
                }
                catch
                {
                    // clear this sockIO obj from the list
                    // and from the map containing keys
                    toRemove.Add(host);
                    try
                    {
                        sock.TrueClose();
                    }
                    finally
                    {
                        sock = null;
                    }
                }

                // Return socket to pool
                if (sock != null)
                {
                    sock.Close();
                }
            }

            foreach (string host in toRemove)
            {
                sockKeys.Remove(host);
            }
            return(ret);
        }
        /// <summary>
        /// Deletes an object from cache given cache key, a delete time, and an optional hashcode.
        ///
        /// The item is immediately made non retrievable.<br/>
        /// Keep in mind:
        /// <see cref="add">add(string, object)</see> and <see cref="replace">replace(string, object)</see>
        ///	will fail when used with the same key will fail, until the server reaches the
        ///	specified time. However, <see cref="set">set(string, object)</see> will succeed
        /// and the new value will not be deleted.
        /// </summary>
        /// <param name="key">the key to be removed</param>
        /// <param name="hashCode">if not null, then the int hashcode to use</param>
        /// <param name="expiry">when to expire the record.</param>
        /// <returns><c>true</c>, if the data was deleted successfully</returns>
        public bool Delete(string key, object hashCode, DateTime expiry)
        {
            if (key == null)
            {
                return(false);
            }
            key = Prefix + key;

            // get SockIO obj from hash or from key
            SockIO sock = SockIOPool.GetInstance(_poolName).GetSock(key, hashCode);

            // return false if unable to get SockIO obj
            if (sock == null)
            {
                return(false);
            }

            // build command
            StringBuilder command = new StringBuilder("delete ").Append(key);

            if (expiry != DateTime.MaxValue)
            {
                command.Append(" " + GetExpirationTime(expiry) / 1000);
            }

            command.Append("\r\n");

            try
            {
                sock.Write(Encoding.UTF8.GetBytes(command.ToString()));
                sock.Flush();

                // if we get appropriate response back, then we return true
                string line = sock.ReadLine();
                if (DELETED == line)
                {
                    // return sock to pool and bail here
                    sock.Close();
                    sock = null;
                    return(true);
                }
            }
            catch
            {
                try
                {
                    if (sock != null)
                    {
                        sock.TrueClose();
                    }
                }
                finally
                {
                    sock = null;
                }
            }
            if (sock != null)
            {
                sock.Close();
            }

            return(false);
        }
        /// <summary>
        /// Stores data to cache.
        ///
        /// If data does not already exist for this key on the server, or if the key is being
        /// deleted, the specified value will not be stored.
        /// The server will automatically delete the value when the expiration time has been reached.
        ///
        /// If compression is enabled, and the data is longer than the compression threshold
        /// the data will be stored in compressed form.
        ///
        /// As of the current release, all objects stored will use .NET serialization.
        /// </summary>
        /// <param name="cmdname">action to take (set, add, replace)</param>
        /// <param name="key">key to store cache under</param>
        /// <param name="obj">object to cache</param>
        /// <param name="expiry">expiration</param>
        /// <param name="hashCode">if not null, then the int hashcode to use</param>
        /// <param name="asString">store this object as a string?</param>
        /// <returns>true/false indicating success</returns>
        private bool Set(string cmdname, string key, object obj, DateTime expiry, object hashCode, bool asString)
        {
            if (expiry < DateTime.Now)
            {
                return(true);
            }

            if (cmdname == null || cmdname.Trim().Length == 0 || string.IsNullOrEmpty(key))
            {
                return(false);
            }
            key = Prefix + key;

            // get SockIO obj
            SockIO sock = SockIOPool.GetInstance(_poolName).GetSock(key, hashCode);

            if (sock == null)
            {
                return(false);
            }

            if (expiry == DateTime.MaxValue)
            {
                expiry = new DateTime(0);
            }

            // store flags
            int flags = 0;

            // byte array to hold data
            byte[] val;
            int    length = 0;

            // useful for sharing data between .NET and non-.NET
            // and also for storing ints for the increment method
            if (NativeHandler.IsHandled(obj))
            {
                if (asString)
                {
                    if (obj != null)
                    {
                        try
                        {
                            val    = Encoding.UTF8.GetBytes(obj.ToString());
                            length = val.Length;
                        }
                        catch
                        {
                            sock.Close();
                            sock = null;
                            return(false);
                        }
                    }
                    else
                    {
                        val    = new byte[0];
                        length = 0;
                    }
                }
                else
                {
                    try
                    {
                        val    = NativeHandler.Encode(obj);
                        length = val.Length;
                    }
                    catch
                    {
                        sock.Close();
                        sock = null;
                        return(false);
                    }
                }
            }
            else
            {
                if (obj != null)
                {
                    // always serialize for non-primitive types
                    try
                    {
                        var memStream = new MemoryStream();
                        new BinaryFormatter().Serialize(memStream, obj);
                        val    = memStream.GetBuffer();
                        length = (int)memStream.Length;
                        flags |= F_SERIALIZED;
                    }
                    catch
                    {
                        // return socket to pool and bail
                        sock.Close();
                        sock = null;
                        return(false);
                    }
                }
                else
                {
                    val    = new byte[0];
                    length = 0;
                }
            }

            // now try to compress if we want to
            // and if the length is over the threshold
            if (_compressEnable && length > _compressThreshold)
            {
                MemoryStream memoryStream = null;
                GZipStream   gos          = null;
                try
                {
                    memoryStream = new MemoryStream();
                    gos          = new GZipStream(memoryStream, CompressionMode.Compress);
                    gos.Write(val, 0, length);
                    gos.Flush();

                    // store it and set compression flag
                    val    = memoryStream.GetBuffer();
                    length = (int)memoryStream.Length;
                    flags |= F_COMPRESSED;
                }
                finally
                {
                    if (memoryStream != null)
                    {
                        memoryStream.Close();
                        memoryStream.Dispose();
                    }
                    if (gos != null)
                    {
                        gos.Close();
                        gos.Dispose();
                    }
                }
            }

            // now write the data to the cache server
            try
            {
                string cmd = cmdname + " " + key + " " + flags + " "
                             + GetExpirationTime(expiry) + " " + length + "\r\n";
                sock.Write(Encoding.UTF8.GetBytes(cmd));
                sock.Write(val, 0, length);
                sock.Write(Encoding.UTF8.GetBytes("\r\n"));
                sock.Flush();

                // get result code
                string line = sock.ReadLine();

                if (STORED == line)
                {
                    sock.Close();
                    sock = null;
                    return(true);
                }
            }
            catch
            {
                try
                {
                    if (sock != null)
                    {
                        sock.TrueClose();
                    }
                }
                finally
                {
                    sock = null;
                }
            }

            if (sock != null)
            {
                sock.Close();
            }

            return(false);
        }
Exemple #20
0
        /// <summary>
        /// Adds a socket to a given pool for the given host.
        /// 
        /// Internal utility method. 
        /// </summary>
        /// <param name="pool">pool to add to</param>
        /// <param name="host">host this socket is connected to</param>
        /// <param name="socket">socket to add</param>
        //[MethodImpl(MethodImplOptions.Synchronized)]
        protected static void AddSocketToPool(Hashtable pool, string host, SockIO socket)
        {
            if (pool == null || string.IsNullOrEmpty(host))
                return; 

            Hashtable sockets;
            if (!string.IsNullOrEmpty(host) && pool.ContainsKey(host))
            {
                sockets = (Hashtable)pool[host];
                if (sockets != null)
                {
                    sockets[socket] = DateTime.Now; //MaxM 1.16.05: Use current DateTime to indicate socker creation time rather than milliseconds since 1970

                    return;
                }
            }

            sockets = new Hashtable();
            sockets[socket] = DateTime.Now; //MaxM 1.16.05: Use current DateTime to indicate socker creation time rather than milliseconds since 1970
            pool[host] = sockets;
        }
Exemple #21
0
        protected static void RemoveSocketFromPool(Hashtable pool, string host, SockIO socket)
        {
            if (string.IsNullOrEmpty(host) || pool == null)
                return;

            if(pool.ContainsKey(host))
            {
                var sockets = (Hashtable)pool[host];
                if(sockets != null)
                {
                    sockets.Remove(socket);
                }
            }
        }
Exemple #22
0
        protected void SelfMaintain()
        {
            // go through avail sockets and create/destroy sockets
            // as needed to maintain pool settings
            foreach (string host in new IteratorIsolateCollection(_availPool.Keys))
            {
                Hashtable sockets = (Hashtable)_availPool[host];

                // if pool is too small (n < minSpare)
                if (sockets.Count < _minConns)
                {
                    // need to create new sockets
                    int need = _minConns - sockets.Count;

                    for (int j = 0; j < need; j++)
                    {
                        SockIO socket = CreateSocket(host);

                        if (socket == null)
                        {
                            break;
                        }

                        AddSocketToPool(_availPool, host, socket);
                    }
                }
                else if (sockets.Count > _maxConns)
                {
                    // need to close down some sockets
                    int diff        = sockets.Count - _maxConns;
                    int needToClose = (diff <= _poolMultiplier)
                        ? diff
                        : (diff) / _poolMultiplier;

                    foreach (SockIO socket in new IteratorIsolateCollection(sockets.Keys))
                    {
                        if (needToClose <= 0)
                        {
                            break;
                        }

                        // remove stale entries
                        DateTime expire = (DateTime)sockets[socket];

                        // if past idle time
                        // then close socket
                        // and remove from pool
                        if ((expire.AddMilliseconds(_maxIdle)) < DateTime.Now)
                        {
                            try
                            {
                                socket.TrueClose();
                            }
                            finally
                            {
                                sockets.Remove(socket);
                                needToClose--;
                            }
                        }
                    }
                }

                // reset the shift value for creating new SockIO objects
                _createShift[host] = 0;
            }

            // go through busy sockets and destroy sockets
            // as needed to maintain pool settings
            foreach (string host in _busyPool.Keys)
            {
                Hashtable sockets = (Hashtable)_busyPool[host];

                // loop through all connections and check to see if we have any hung connections
                foreach (SockIO socket in new IteratorIsolateCollection(sockets.Keys))
                {
                    // remove stale entries
                    DateTime hungTime = (DateTime)sockets[socket];

                    // if past max busy time
                    // then close socket
                    // and remove from pool
                    if ((hungTime.AddMilliseconds(_maxBusyTime)) < DateTime.Now)
                    {
                        try
                        {
                            socket.TrueClose();
                        }
                        finally
                        {
                            sockets.Remove(socket);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// This method loads the data from cache into a Hashtable.
        ///
        /// Pass a SockIO object which is ready to receive data and a Hashtable
        /// to store the results.
        /// </summary>
        /// <param name="sock">socket waiting to pass back data</param>
        /// <param name="hm">hashmap to store data into</param>
        /// <param name="asString">if true, and if we are using NativehHandler, return string val</param>
        private void LoadItems(SockIO sock, Hashtable hm, bool asString)
        {
            while (true)
            {
                string line = sock.ReadLine();

                if (line.StartsWith(VALUE))
                {
                    string[] info   = line.Split(' ');
                    string   key    = info[1];
                    int      flag   = int.Parse(info[2], new NumberFormatInfo());
                    int      length = int.Parse(info[3], new NumberFormatInfo());

                    // read obj into buffer
                    byte[] buf = new byte[length];
                    sock.Read(buf);
                    sock.ClearEndOfLine();

                    // ready object
                    object o = null;

                    // check for compression
                    if ((flag & F_COMPRESSED) != 0)
                    {
                        MemoryStream mem = null;
                        GZipStream   gzi = null;
                        try
                        {
                            // read the input stream, and write to a byte array output stream since
                            // we have to read into a byte array, but we don't know how large it
                            // will need to be, and we don't want to resize it a bunch
                            mem = new MemoryStream(buf.Length);
                            gzi = new GZipStream(new MemoryStream(buf), CompressionMode.Compress);

                            int count;
                            var tmp = new byte[2048];
                            while ((count = gzi.Read(tmp, 0, tmp.Length)) > 0)
                            {
                                mem.Write(tmp, 0, count);
                            }

                            // store uncompressed back to buffer
                            buf = mem.ToArray();
                        }
                        finally
                        {
                            if (mem != null)
                            {
                                mem.Close();
                                mem.Dispose();
                            }
                            if (gzi != null)
                            {
                                gzi.Close();
                                gzi.Dispose();
                            }
                        }
                    }

                    // we can only take out serialized objects
                    if ((flag & F_SERIALIZED) == 0)
                    {
                        if (_primitiveAsString || asString)
                        {
                            o = Encoding.GetEncoding(_defaultEncoding).GetString(buf);
                        }
                        else
                        {
                            // decoding object
                            try
                            {
                                o = NativeHandler.Decode(buf);
                            }
                            catch (Exception e)
                            {
                                return;
                            }
                        }
                    }
                    else
                    {
                        // deserialize if the data is serialized
                        MemoryStream memStream = null;
                        try
                        {
                            memStream = new MemoryStream(buf);
                            o         = new BinaryFormatter().Deserialize(memStream);
                        }
                        catch (SerializationException e)
                        {
                        }
                        finally
                        {
                            if (memStream != null)
                            {
                                memStream.Close();
                                memStream.Dispose();
                            }
                        }
                    }

                    // store the object into the cache
                    hm[key] = o;
                }
                else if (END == line)
                {
                    break;
                }
            }
        }