Exemple #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="pool"></param>
        /// <param name="host"></param>
        /// <param name="timeout"></param>
        /// <param name="connectTimeout"></param>
        /// <param name="noDelay"></param>
        public SockIO(SockIOPool pool, String host, int timeout, int connectTimeout, bool noDelay)
            : this()
        {
            if (host == null || host.Length == 0)
            {
                throw new ArgumentNullException(GetLocalizedString("host"), GetLocalizedString("null host"));
            }

            _pool = pool;

            String[] ip = host.Split(':');

            if (connectTimeout > 0)
            {
                _socket = GetSocket(ip[0], int.Parse(ip[1], new System.Globalization.NumberFormatInfo()), connectTimeout);
            }
            else
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _socket.Connect(new IPEndPoint(IPAddress.Parse(ip[0]), int.Parse(ip[1], new System.Globalization.NumberFormatInfo())));
            }

            _networkStream = new BufferedStream(new NetworkStreamIgnoreSeek(_socket));
            _host          = host;
        }
Exemple #2
0
        /// <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)
        {
            // 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(UTF8Encoding.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()));
                }
                else if (NOTFOUND == line)
                {
                }
                else
                {
                }
            }
            catch (IOException e)
            {
                try
                {
                    sock.TrueClose();
                }
                catch (IOException)
                {
                }

                sock = null;
            }

            if (sock != null)
            {
                sock.Close();
            }
            return(-1);
        }
Exemple #3
0
        public static SockIOPool GetInstance(String poolName)
        {
            if (Pools.ContainsKey(poolName))
            {
                return((SockIOPool)Pools[poolName]);
            }

            SockIOPool pool = new SockIOPool();

            Pools[poolName] = pool;

            return(pool);
        }
Exemple #4
0
        /// <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)
        {
            // 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(UTF8Encoding.UTF8.GetBytes(cmd));
                sock.Flush();

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

                // return the value for this key if we found it
                // else return null
                sock.Close();
                return(hm[key]);
            }
            catch (IOException e)
            {
                try
                {
                    sock.TrueClose();
                }
                catch (IOException ioe)
                {
                }
                sock = null;
            }

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

            return(null);
        }
Exemple #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="pool"></param>
        /// <param name="host"></param>
        /// <param name="port"></param>
        /// <param name="timeout"></param>
        /// <param name="connectTimeout"></param>
        /// <param name="noDelay"></param>
        public SockIO(SockIOPool pool, String host, int port, int timeout, int connectTimeout, bool noDelay)
            : this()
        {
            if (host == null || host.Length == 0)
            {
                throw new ArgumentNullException(GetLocalizedString("host"), GetLocalizedString("null host"));
            }

            _pool = pool;

            if (connectTimeout > 0)
            {
                _socket = GetSocket(host, port, connectTimeout);
            }
            else
            {
                _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _socket.Connect(new IPEndPoint(IPAddress.Parse(host), port));
            }

            _networkStream = new BufferedStream(new NetworkStreamIgnoreSeek(_socket));

            _host = host + ":" + port;
        }
Exemple #6
0
        /// <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(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(" " + 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(UTF8Encoding.UTF8.GetBytes(cmd));
                    sock.Flush();
                    LoadItems(sock, ret, asString);
                }
                catch (IOException e)
                {
                    // clear this sockIO obj from the list
                    // and from the map containing keys
                    toRemove.Add(host);
                    try
                    {
                        sock.TrueClose();
                    }
                    catch (IOException ioe)
                    {
                    }
                    sock = null;
                }

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

            foreach (string host in toRemove)
            {
                sockKeys.Remove(host);
            }
            return(ret);
        }
Exemple #7
0
        /// <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="value">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 || key == null || key.Length == 0)
            {
                return(false);
            }

            // 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    = UTF8Encoding.UTF8.GetBytes(obj.ToString());
                            length = val.Length;
                        }
                        catch (ArgumentException ex)
                        {
                            sock.Close();
                            sock = null;
                            return(false);
                        }
                    }
                    else
                    {
                        val    = new byte[0];
                        length = 0;
                    }
                }
                else
                {
                    try
                    {
                        val    = NativeHandler.Encode(obj);
                        length = val.Length;
                    }
                    catch (ArgumentException e)
                    {
                        sock.Close();
                        sock = null;
                        return(false);
                    }
                }
            }
            else
            {
                if (obj != null)
                {
                    try
                    {
                        MemoryStream memStream = new MemoryStream();
                        new BinaryFormatter().Serialize(memStream, obj);
                        val    = memStream.GetBuffer();
                        length = (int)memStream.Length;
                        flags |= F_SERIALIZED;
                    }
                    catch (IOException e)
                    {
                        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)
            {
                try
                {
                    MemoryStream     memoryStream = new MemoryStream();
                    GZipOutputStream gos          = new GZipOutputStream(memoryStream);
                    gos.Write(val, 0, length);
                    gos.Finish();

                    // store it and set compression flag
                    val    = memoryStream.GetBuffer();
                    length = (int)memoryStream.Length;
                    flags |= F_COMPRESSED;
                }
                catch (IOException e)
                {
                }
            }

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

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

                if (STORED == line)
                {
                    sock.Close();
                    sock = null;
                    return(true);
                }
                else if (NOTSTORED == line)
                {
                }
                else
                {
                }
            }
            catch (IOException e)
            {
                try
                {
                    sock.TrueClose();
                }
                catch (IOException ioe)
                {
                }

                sock = null;
            }

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

            return(false);
        }
Exemple #8
0
        /// <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);
            }

            // 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(UTF8Encoding.UTF8.GetBytes(command.ToString()));
                sock.Flush();

                // if we get appropriate response back, then we return true
                string line = sock.ReadLine();
                if (DELETED == line)
                {
                    sock.Close();
                    sock = null;
                    return(true);
                }
                else if (NOTFOUND == line)
                {
                }
                else
                {
                }
            }
            catch (IOException e)
            {
                try
                {
                    sock.TrueClose();
                }
                catch (IOException ioe)
                {
                }

                sock = null;
            }

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

            return(false);
        }
Exemple #9
0
        /// <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);
        }
Exemple #10
0
        /// <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(UTF8Encoding.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 (IOException ioe)
                    {
                    }

                    success = false;
                    sock    = null;
                }

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

            return(success);
        }
Exemple #11
0
 public MaintenanceThread(SockIOPool pool)
 {
     _thread = new Thread(new ThreadStart(Maintain));
     _pool   = pool;
 }