/// <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); }
/// <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; } } }