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);
}
}
复制代码
两上个方法都不支持从外部带入buffer的情况,当需要高并发操作的情况而对象序列化内容又比较大的情况下,那的确是会让人感觉到不满意.所以在这基础上添加了一些有利于buffer复用的方法来支持高并发操作下的性能需要.
复制代码
public void put(byte[] key, byte[] value, int offset, int length, writeoptions options)
{
intptr error;
leveldbinterop.leveldb_put(this.handle, options.handle, key, (intptr)key.length, value, (intptr)length, out error);
leveldbexception.check(error);
gc.keepalive(options);
gc.keepalive(this);
}
public unsafe long get(byte[] key, byte[] buffer, 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 0;
try
{
var length = (long)lengthptr;
var valuenative = (byte*)valueptr.topointer();
marshal.copy((intptr)valueptr, buffer, 0, (int)length);
return length;
}
finally
{
leveldbinterop.leveldb_free(valueptr);
}
}
上一篇: 前端基础知识整理
下一篇: css属性的继承问题