修改memecache客户端API,解决ttserver反序列化问题

  之前在一篇随笔中提到使用Memcache的API无法正确将保存在ttserver中的值正确反序列化,原因是,Memcache协议中的对象类型值未被保存到ttserver上,于是简单的修改了一下Memcache API(使用的beit-memcached)中的Serializer.cs文件,将序列化对象的原始类型保存在序列化串的第一个字节中,也就是将值的类型,连同值一起保存到ttserver上。

 

代码
// Copyright (c) 2007-2008 Henrik Schr鰀er, Oliver Kofoed Pedersen

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#region  文件信息
/* =================================================================
 *  文件:Serializer.cs
 *  创建者:<原作者>
 *  创建日期:<未知>
 *  最后修改:(楼下请注意保持队形)
 *  ##############################################################
 *  时间          修改人                      备注
 *  2010-04-19       田真                 因为TT不支持Memcached的类型存储,这里修改了序列化方式,主要体现在对Serialize和Deserialize方法的修改
 *  2010-04-19       田真                 增加了MergedBuffer和ParsedBuffer两个方法
 *  2010-04-19       田真                 修改SerializedType继承自byte,以前是ushort
 *  2010-04-19       田真                 修改CompressedByteArray = 255, CompressedObject = 256, CompressedString = 257
 *                                              为:CompressedByteArray = 253, CompressedObject = 254, CompressedString = 255
 *  ##############################################################
 * ================================================================
*/
#endregion

using  System;
using  System.IO;
using  System.IO.Compression;
using  System.Runtime.Serialization.Formatters.Binary;
using  System.Text;

namespace  SubCon.Caching.MemCached
{
    
///   <summary>
    
///  序列化的对象类型
    
///   </summary>
     internal   enum  SerializedType :  byte
    {
        ByteArray    
=   0 ,
        Object        
=   1 ,
        String        
=   2 ,
        Datetime    
=   3 ,
        Bool        
=   4 ,
        
// SByte        = 5,  // Makes no sense.
        Byte         =   6 ,
        Short        
=   7 ,
        UShort        
=   8 ,
        Int            
=   9 ,
        UInt        
=   10 ,
        Long        
=   11 ,
        ULong        
=   12 ,
        Float        
=   13 ,
        Double        
=   14 ,

        CompressedByteArray    
=   253 ,
        CompressedObject    
=   254 ,
        CompressedString    
=   255 ,
    }

    
///   <summary>
    
///  存储值序列器
    
///   </summary>
     internal   class  Serializer
    {
        
///   <summary>
        
///  序列化存储值
        
///   </summary>
        
///   <param name="value"> 要进行序列化的值 </param>
        
///   <param name="type"> 被序列的值是什么类型 </param>
        
///   <param name="compressionThreshold"> 压缩基准,当序列化后的字节数组长度大于该值时进行压缩 </param>
        
///   <returns></returns>
         public   static   byte [] Serialize( object  value,  out  SerializedType type,  uint  compressionThreshold) {
            
byte [] bytes;
            
if  (value  is   byte []) {
                bytes 
=  ( byte [])value;
                type 
=  SerializedType.ByteArray;
                
if  (bytes.Length  >  compressionThreshold) {
                    bytes 
=  Compress(bytes);
                    type 
=  SerializedType.CompressedByteArray;
                }
            } 
else   if  (value  is   string ) {
                bytes 
=  Encoding.UTF8.GetBytes(( string )value);
                type 
=  SerializedType.String;
                
if  (bytes.Length  >  compressionThreshold) {
                    bytes 
=  Compress(bytes);
                    type 
=  SerializedType.CompressedString;
                }
            } 
else   if  (value  is  DateTime) {
                bytes 
=  BitConverter.GetBytes(((DateTime)value).Ticks);
                type 
=  SerializedType.Datetime;
            } 
else   if  (value  is   bool ) {
                bytes 
=   new   byte []{( byte )(( bool )value  ?   1  :  0 )};
                type 
=  SerializedType.Bool;
            } 
else   if  (value  is   byte ) {
                bytes 
=   new   byte []{( byte )value};
                type 
=  SerializedType.Byte;
            } 
else   if  (value  is   short ) {
                bytes 
=  BitConverter.GetBytes(( short )value);
                type 
=  SerializedType.Short;
            } 
else   if  (value  is   ushort ) {
                bytes 
=  BitConverter.GetBytes(( ushort )value);
                type 
=  SerializedType.UShort;
            } 
else   if  (value  is   int ) {
                bytes 
=  BitConverter.GetBytes(( int )value);
                type 
=  SerializedType.Int;
            } 
else   if  (value  is   uint ) {
                bytes 
=  BitConverter.GetBytes(( uint )value);
                type 
=  SerializedType.UInt;
            } 
else   if  (value  is   long ) {
                bytes 
=  BitConverter.GetBytes(( long )value);
                type 
=  SerializedType.Long;
            } 
else   if  (value  is   ulong ) {
                bytes 
=  BitConverter.GetBytes(( ulong )value);
                type 
=  SerializedType.ULong;
            } 
else   if  (value  is   float ) {
                bytes 
=  BitConverter.GetBytes(( float )value);
                type 
=  SerializedType.Float;
            } 
else   if  (value  is   double ) {
                bytes 
=  BitConverter.GetBytes(( double )value);
                type 
=  SerializedType.Double;
            } 
else  {
                
// Object
                 using (MemoryStream ms  =   new  MemoryStream()) {
                    
new  BinaryFormatter().Serialize(ms, value);
                    bytes 
=  ms.ToArray();
                    type 
=  SerializedType.Object;
                    
if  (bytes.Length  >  compressionThreshold) {
                        bytes 
=  Compress(bytes);
                        type 
=  SerializedType.CompressedObject;
                    }
                }
            }
            
// 针对TT进行的修改
            
// edited by: 2010-4-19
            
// 田真
             return  MergedBuffer(bytes, type);
        }

        
///   <summary>
        
///  解析缓存字节数组,解析出实际数据和数据类型
        
///   </summary>
        
///   <param name="buffer"></param>
        
///   <param name="type"></param>
        
///   <returns></returns>
         private   static   byte [] ParsedBuffer( byte [] buffer,  out  SerializedType type)
        {
            
// 构造实际数据字节数组
             byte [] bytes  =   new   byte [buffer.Length  -   1 ];
            
// 提取类型
             if  ( ! Enum.IsDefined( typeof (SerializedType), buffer[ 0 ]))
                type 
=  SerializedType.ByteArray;
            
else
                type 
=  (SerializedType)buffer[ 0 ];
            
// 提取数据
            Buffer.BlockCopy(buffer,  1 , bytes,  0 , bytes.Length);
            
return  bytes;

        }

        
///   <summary>
        
///  将序列化类型整合到存储的字节数组中(因为TT不支持Memcached的Type值存储)
        
///   </summary>
        
///   <param name="bytes"> 字节数组 </param>
        
///   <param name="type"> 字节数组的类型 </param>
        
///   <returns></returns>
         private   static   byte [] MergedBuffer( byte [] bytes, SerializedType type)
        { 
            
// 增加一个字节,用于存放字节数组的类型
             byte [] buffer  =   new   byte [bytes.Length  +   1 ];
            
// 将类型存储到第一个字节中
            buffer[ 0 =  ( byte )type;
            Buffer.BlockCopy(bytes, 
0 , buffer,  1 , bytes.Length);
            
return  buffer;
        }

        
///   <summary>
        
///  压缩指定的字节数组
        
///   </summary>
        
///   <param name="bytes"></param>
        
///   <returns></returns>
         private   static   byte [] Compress( byte [] bytes) {
            
using  (MemoryStream ms  =   new  MemoryStream()) {
                
using  (DeflateStream gzs  =   new  DeflateStream(ms, CompressionMode.Compress,  false )) {
                    gzs.Write(bytes, 
0 , bytes.Length);
                }
                ms.Close();
                
return  ms.ToArray();
            }
        }

        
///   <summary>
        
///  解压缩指定的字节数组
        
///   </summary>
        
///   <param name="bytes"></param>
        
///   <returns></returns>
         private   static   byte [] Decompress ( byte [] bytes) {
            
using  (MemoryStream ms  =   new  MemoryStream(bytes,  false )) {
                
using (DeflateStream gzs  =   new  DeflateStream(ms, CompressionMode.Decompress,  false )) {
                    
using (MemoryStream dest  =   new  MemoryStream()) {
                        
byte [] tmp  =   new   byte [bytes.Length];
                        
int  read;
                        
while  ((read  =  gzs.Read(tmp,  0 , tmp.Length))  !=   0 ) {
                            dest.Write(tmp, 
0 , read);
                        }
                        dest.Close();
                        
return  dest.ToArray();
                    }
                }
            }
        }

        
///   <summary>
        
///  反序列化数据
        
///   </summary>
        
///   <param name="bytes"></param>
        
///   <param name="type"></param>
        
///   <returns></returns>
         public   static   object  Deserialize( byte [] bytes, SerializedType type) {
            
// 针对TT进行的修改
            
// edited by: 2010-4-19
            
// 田真
            bytes  =  ParsedBuffer(bytes,  out  type);
            
switch  (type) {
                
case  SerializedType.String:
                    
return  Encoding.UTF8.GetString(bytes);
                
case  SerializedType.Datetime:
                    
return   new  DateTime(BitConverter.ToInt64(bytes,  0 ));
                
case  SerializedType.Bool:
                    
return  bytes[ 0 ==   1 ;
                
case  SerializedType.Byte:
                    
return  bytes[ 0 ];
                
case  SerializedType.Short:
                    
return  BitConverter.ToInt16(bytes,  0 );
                
case  SerializedType.UShort:
                    
return  BitConverter.ToUInt16(bytes,  0 );
                
case  SerializedType.Int:
                    
return  BitConverter.ToInt32(bytes,  0 );
                
case  SerializedType.UInt:
                    
return  BitConverter.ToUInt32(bytes,  0 );
                
case  SerializedType.Long:
                    
return  BitConverter.ToInt64(bytes,  0 );
                
case  SerializedType.ULong:
                    
return  BitConverter.ToUInt64(bytes,  0 );
                
case  SerializedType.Float:
                    
return  BitConverter.ToSingle(bytes,  0 );
                
case  SerializedType.Double:
                    
return  BitConverter.ToDouble(bytes,  0 );
                
case  SerializedType.Object:
                    
using (MemoryStream ms  =   new  MemoryStream(bytes)) {
                        
return   new  BinaryFormatter().Deserialize(ms);
                    }
                
case  SerializedType.CompressedByteArray:
                    
return  Deserialize(Decompress(bytes), SerializedType.ByteArray);
                
case  SerializedType.CompressedString:
                    
return  Deserialize(Decompress(bytes), SerializedType.String);
                
case  SerializedType.CompressedObject:
                    
return  Deserialize(Decompress(bytes), SerializedType.Object);
                
case  SerializedType.ByteArray:
                
default :
                    
return  bytes;
            }
        }
    }
}

 

 

Raw file: Serializer.cs

你可能感兴趣的:(ttserver)