ソースを参照

初始化数据仓库

lxg 3 年 前
コミット
c8cad622a5
6 ファイル変更337 行追加0 行削除
  1. 44 0
      .gitignore
  2. 46 0
      db.go
  3. 10 0
      go.mod
  4. 20 0
      go.sum
  5. 101 0
      leveldb.go
  6. 116 0
      redis.go

+ 44 - 0
.gitignore

@@ -0,0 +1,44 @@
+bin/
+
+.svn/
+.godeps
+./build
+.cover/
+dist
+_site
+_posts
+*.dat
+vendor
+
+# Go.gitignore
+
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+storage
+.idea
+.vscode
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+
+profile
+
+# vim stuff
+*.sw[op]

+ 46 - 0
db.go

@@ -0,0 +1,46 @@
+package kvdb
+
+import "context"
+
+type (
+
+	contextKey struct {}
+
+	Iterator interface {
+		Next() bool
+		Key() string
+		Value() []byte
+		Close() error
+	}
+
+	DB interface {
+		Open() error
+		Put(string, []byte) error
+		Get(string) ([]byte, error)
+		Delete(string) error
+		Iterator(string) (Iterator, error)
+		Close() error
+	}
+)
+
+var (
+	ctxKey = contextKey{}
+)
+
+func WithContext(c context.Context, v DB) context.Context {
+	if c == nil {
+		c = context.Background()
+	}
+	return context.WithValue(c, ctxKey, v)
+}
+
+func FromContext(c context.Context) DB {
+	if c != nil {
+		if v := c.Value(ctxKey); v != nil {
+			if x, ok := v.(DB); ok {
+				return x
+			}
+		}
+	}
+	return nil
+}

+ 10 - 0
go.mod

@@ -0,0 +1,10 @@
+module git.nspix.com/golang/kvdb
+
+go 1.17
+
+require (
+	github.com/go-redis/redis v6.15.9+incompatible
+	github.com/syndtr/goleveldb v1.0.0
+)
+
+require github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect

+ 20 - 0
go.sum

@@ -0,0 +1,20 @@
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
+github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
+github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
+github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

+ 101 - 0
leveldb.go

@@ -0,0 +1,101 @@
+package kvdb
+
+import (
+	"github.com/syndtr/goleveldb/leveldb"
+	"github.com/syndtr/goleveldb/leveldb/iterator"
+	"github.com/syndtr/goleveldb/leveldb/util"
+	"io"
+	"sync/atomic"
+)
+
+type LevelDb struct {
+	filename string
+	openFlag int32
+	engine   *leveldb.DB
+}
+
+type levelDbIterator struct {
+	v iterator.Iterator
+}
+
+func (i *levelDbIterator) Next() bool {
+	return i.v.Next()
+}
+
+func (i *levelDbIterator) Key() string {
+	return string(i.v.Key())
+}
+
+func (i *levelDbIterator) Value() []byte {
+	return i.v.Value()
+}
+
+func (i *levelDbIterator) Close() error {
+	i.v.Release()
+	return nil
+}
+
+func (db *LevelDb) Open() (err error) {
+	db.engine, err = leveldb.OpenFile(db.filename, nil)
+	if err == nil {
+		atomic.StoreInt32(&db.openFlag, 1)
+	} else {
+		if db.engine, err = leveldb.RecoverFile(db.filename, nil); err == nil {
+			atomic.StoreInt32(&db.openFlag, 1)
+		}
+	}
+	return
+}
+
+func (db *LevelDb) Put(key string, value []byte) (err error) {
+	if atomic.LoadInt32(&db.openFlag) == 0 {
+		err = io.ErrClosedPipe
+		return
+	}
+	err = db.engine.Put([]byte(key), value, nil)
+	return
+}
+
+func (db *LevelDb) Get(key string) (b []byte, err error) {
+	if atomic.LoadInt32(&db.openFlag) == 0 {
+		err = io.ErrClosedPipe
+		return
+	}
+	b, err = db.engine.Get([]byte(key), nil)
+	return
+}
+
+func (db *LevelDb) Delete(key string) (err error) {
+	if atomic.LoadInt32(&db.openFlag) == 0 {
+		err = io.ErrClosedPipe
+		return
+	}
+	err = db.engine.Delete([]byte(key), nil)
+	return
+}
+
+func (db *LevelDb) Iterator(key string) (iterator Iterator, err error) {
+	if atomic.LoadInt32(&db.openFlag) == 0 {
+		err = io.ErrClosedPipe
+		return
+	}
+	v := db.engine.NewIterator(util.BytesPrefix([]byte(key)), nil)
+	iterator = &levelDbIterator{
+		v: v,
+	}
+	return
+}
+
+func (db *LevelDb) Close() error {
+	if atomic.LoadInt32(&db.openFlag) == 1 {
+		atomic.StoreInt32(&db.openFlag, 0)
+		return db.engine.Close()
+	}
+	return nil
+}
+
+func NewLevelDb(filename string) *LevelDb {
+	return &LevelDb{
+		filename: filename,
+	}
+}

+ 116 - 0
redis.go

@@ -0,0 +1,116 @@
+package kvdb
+
+import (
+	"github.com/go-redis/redis"
+	"strings"
+)
+
+type (
+	RedisDb struct {
+		addr     string
+		db       int
+		password string
+		engine   *redis.Client
+	}
+
+	redisIterator struct {
+		pos    int      //当前位置
+		cursor uint64   //游标位置
+		key    string   //当前获取的key
+		keys   []string //存储的keys数组
+		prefix string   //搜索的前缀
+		flag   int32    //是否结束搜索
+		client *redis.Client
+	}
+)
+
+func (i *redisIterator) Next() bool {
+	if (i.keys == nil || i.pos >= len(i.keys)) && i.flag != 1 {
+		ret := i.client.Scan(i.cursor, i.prefix, 100)
+		if ret.Err() != nil {
+			return false
+		}
+		i.keys, i.cursor = ret.Val()
+		if i.cursor == 0 {
+			i.flag = 1
+		}
+		i.pos = 0
+	}
+	if i.pos < len(i.keys) {
+		i.key = i.keys[i.pos]
+		i.pos++
+		return true
+	}
+	return false
+}
+
+func (i *redisIterator) Key() string {
+	return i.key
+}
+
+func (i *redisIterator) Value() []byte {
+	cmd := i.client.Get(i.Key())
+	if cmd.Err() == nil {
+		return []byte(cmd.Val())
+	} else {
+		return nil
+	}
+}
+
+func (i *redisIterator) Close() error {
+	i.pos = 0
+	return nil
+}
+
+func newRedisIterator(c *redis.Client, prefix string) *redisIterator {
+	if !strings.HasSuffix(prefix, "*") {
+		prefix = prefix + "*"
+	}
+	return &redisIterator{client: c, prefix: prefix}
+}
+
+func (db *RedisDb) Open() error {
+	db.engine = redis.NewClient(&redis.Options{
+		Addr:     db.addr,
+		Password: db.password,
+		DB:       db.db,
+	})
+	return db.engine.Ping().Err()
+}
+
+func (db *RedisDb) generateKey(s string) string {
+	return "kv:db$:" + s
+}
+
+func (db *RedisDb) Put(s string, bytes []byte) error {
+	return db.engine.Set(db.generateKey(s), string(bytes), 0).Err()
+}
+
+func (db *RedisDb) Get(s string) ([]byte, error) {
+	cmd := db.engine.Get(db.generateKey(s))
+	if cmd.Err() == nil {
+		return []byte(cmd.Val()), nil
+	} else {
+		return nil, cmd.Err()
+	}
+}
+
+func (db *RedisDb) Delete(s string) error {
+	return db.engine.Del(db.generateKey(s)).Err()
+}
+
+func (db *RedisDb) Iterator(s string) (Iterator, error) {
+	return newRedisIterator(db.engine, db.generateKey(s)), nil
+}
+
+func (db *RedisDb) Close() error {
+	return db.engine.Close()
+}
+
+func NewRedis(addr, password string, db int) *RedisDb {
+	return &RedisDb{
+		addr:     addr,
+		password: password,
+		db:       db,
+	}
+}