leveldb.net对象读写封装

作者:郫县华伟包装厂 来源:www.cdhwms.com 发布时间:2017-09-09 10:23:48
leveldb.net对象读写封装 leveldb是一个非常高效的可嵌入式K-V数据库,在.NET下有着基于win实现的包装leveldb.net;不过leveldb.net只提供了基于byte[]和string的处理,这显然会对使用的时候带来不方便,毕竟在编写应用的时候都是希望通过对象的方式来存储,如我们常见的redis,mongodb和memcached等等都提供对象方式的读写.以下主要讲解leveldb.net基础上封装一层序列化功能方便使用.

制定对象化的访问接口

为了不修改leveldb.net的代码,所以选择在他基础过行封装,为了清楚需要些什么简单地定义了一个规则

复制代码

public interface IDBManager

{

IFormater Formater { get; set; }

void Set(string key, object data);

object Get(string key, Type type);

T Get<T>(string key);

void Open();

LevelDB.DB DataBase

{

get;

}

}

复制代码

代码非常简单主要封装了GET,SET,实际上还有DELETE操作,这里偷懒就没做了:),为了提供灵活序列化规则所以在这个管理接口上还提供了一个Formater属性.下面是这相接口的详细实现:

复制代码

public class LevelDBManager : IDBManager

{

public LevelDBManager()

{

}

private LevelDB.DB mDataBase;

public string Path { get; set; }

public IFormater Formater

{

get;

set;

}

public void Open()

{

mDataBase = new LevelDB.DB(Path, new Options() { CreateIfMissing = true });

}

public void Set(string key, object data)

{

FormaterBuffer buffer = Formater.Pop();

try

{

int count = Formater.Serialize(data, buffer, 0);

mDataBase.Put(Encoding.UTF8.GetBytes(key), buffer.Array, 0, count);

}

finally

{

Formater.Push(buffer);

}

}

public object Get(string key, Type type)

{

FormaterBuffer buffer = Formater.Pop();

long count;

object result = null;

try

{

count = mDataBase.Get(Encoding.UTF8.GetBytes(key), buffer.Array);

if (count > 0)

{

result = Formater.Deserialize(type, buffer, 0, (int)count);

}

return result;

}

finally

{

Formater.Push(buffer);

}

}

public T Get<T>(string key)

{

return (T)Get(key, typeof(T));

}

public DB DataBase

{

get { return mDataBase; }

}

}

复制代码

相信以上那些简知的代码也比较好理解,所以就不详细说明了.

可扩展的序列化规则

由于在使用上的需要,都习惯用些不同序列化方式来进行对象序列化,这个封装为了实现一个比较高的灵活度,所以对象序列化过程也制定了一个接口进行隔离.主要为了满足不同人的胃口.

复制代码

public interface IFormater

{

FormaterBuffer Pop();

void Push(FormaterBuffer data);

int Serialize(object data, FormaterBuffer buffer, int offset);

object Deserialize(Type type, FormaterBuffer buffer, int offset, int count);

}

复制代码

比较简单定义了序列化和反序列化的方法,不过为了一些性能上的考虑增加了buffer的复用功能,这个设计紧紧用作需要追求这方面性能要求而准备.下面看一下json和protobuf的实现是怎样的:

复制代码

public abstract class FormaterBase:IFormater

{

private Stack<FormaterBuffer> mBufferPool = new Stack<FormaterBuffer>();

const int BUFFER_SIZE = 1024 * 1024 * 1;

public FormaterBase()

{

for (int i = 0; i < 20; i++)

{

mBufferPool.Push(new FormaterBuffer(BUFFER_SIZE));

}

}

public FormaterBuffer Pop()

{

lock (mBufferPool)

{

if(mBufferPool.Count>0)

return mBufferPool.Pop();

return new FormaterBuffer(BUFFER_SIZE);

}

}

public void Push(FormaterBuffer data)

{

lock (mBufferPool)

{

mBufferPool.Push(data);

}

}

public abstract int Serialize(object data, FormaterBuffer buffer, int offset);

public abstract object Deserialize(Type type, FormaterBuffer buffer, int offset, int count);

}

复制代码

json

复制代码

public class JsnoFormater:FormaterBase

{

public int Serialize(object data, byte[] buffer, int offset)

{

string json = Newtonsoft.Json.JsonConvert.SerializeObject(data);

return Encoding.UTF8.GetBytes(json, 0, json.Length, buffer, offset);

}

public override int Serialize(object data, FormaterBuffer buffer, int offset)

{

string json = Newtonsoft.Json.JsonConvert.SerializeObject(data);

return Encoding.UTF8.GetBytes(json, 0, json.Length, buffer.Array, offset);

}

public override object Deserialize(Type type, FormaterBuffer buffer, int offset, int count)

{

string value = Encoding.UTF8.GetString(buffer.Array, offset, count);

return Newtonsoft.Json.JsonConvert.DeserializeObject(value, type);

}

}

复制代码

protobuf

复制代码

public class ProtobufFormater:FormaterBase

{

public override int Serialize(object data, FormaterBuffer buffer, int offset)

{

buffer.Seek(offset);

ProtoBuf.Meta.RuntimeTypeModel.Default.Serialize(buffer.Stream, data);

return (int)buffer.Stream.Position;

}

public override object Deserialize(Type type, FormaterBuffer buffer, int offset, int count)

{

buffer.Stream.SetLength(count + offset);

buffer.Seek(offset);

return ProtoBuf.Meta.RuntimeTypeModel.Default.Deserialize(buffer.Stream, null, type);

}

}

复制代码

leveldb.net的一些简单性能改造

虽然leveldb.net只以win dll的基础上包装,但在包装过程的确有些方法针对我个人来说做得并不理想,主要体现在buffer复用方面.其实get,set方法都存在这情况.

复制代码

/// <summary>

/// Set the database entry for "key" to "value".

/// </summary>

public void Put(byte[] key, byte[] value, WriteOptions options)

{

IntPtr error;

LevelDBInterop.leveldb_put(this.Handle, options.Handle, key, (IntPtr)key.Length, value, (IntPtr)value.LongLength, out error);

LevelDBException.Check(error);

GC.KeepAlive(options);

GC.KeepAlive(this);

}

public unsafe byte[] Get(byte[] key, ReadOptions options)

{

IntPtr error;

IntPtr lengthPtr;

var valuePtr = LevelDBInterop.leveldb_get(this.Handle, options.Handle, key, (IntPtr)key.Length, out lengthPtr, out error);

LevelDBException.Check(error);

if (valuePtr == IntPtr.Zero)

return null;

try

{

var length = (long)lengthPtr;

var value = new byte[length];

var valueNative = (byte*)valuePtr.ToPointer();

for (long i = 0; i < length; ++i)

value[i] = valueNative[i];

return value;

}

finally

{

LevelDBInterop.leveldb_free(valuePtr);

GC.KeepAlive(options);

GC.KeepAlive(this);

}

}

复制代码

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:潜江SEO http://qianjiang.raoyu.net

  • 上一篇:一入python深似海--dict(字典)的一种实现
  • 下一篇:最后一页