diff --git a/store/memo/memo.go b/store/memo/memo.go new file mode 100644 index 00000000..83d634cd --- /dev/null +++ b/store/memo/memo.go @@ -0,0 +1,131 @@ +package memo + +import ( + "github.com/docker/libkv" + "github.com/docker/libkv/store" + kvs "github.com/docker/libkv/store/memo/memo_kvs" + "golang.org/x/net/context" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" +) + +// Memo is the receiver type for the Store interface +type Memo struct { + kvs kvs.KeyValueStoreClient +} + +// Register registers memo to libkv +func Register() { + libkv.AddStore("memo", New) +} + +// New creates a new memo client +func New(addrs []string, options *store.Config) (store.Store, error) { + conn, err := grpc.Dial(addrs[0], grpc.WithInsecure()) + if err != nil { + return nil, err + } + kvs := kvs.NewKeyValueStoreClient(conn) + return &Memo{kvs: kvs}, nil +} + +// Get current value at "key". +func (s *Memo) Get(key string) (*store.KVPair, error) { + res, err := s.kvs.Fetch(context.Background(), &kvs.FetchRequest{Key: key}) + if err != nil { + if grpc.Code(err) == codes.NotFound { + return nil, store.ErrKeyNotFound + } + return nil, err + } + return &store.KVPair{ + Key: key, + Value: res.Value, + LastIndex: 0, + }, nil +} + +// Put value at "key" +func (s *Memo) Put(key string, value []byte, options *store.WriteOptions) error { + _, err := s.kvs.Upsert(context.Background(), + &kvs.UpsertRequest{Key: key, Value: value}) + return err +} + +// Delete value at "key" +func (s *Memo) Delete(key string) error { + _, err := s.kvs.Delete(context.Background(), &kvs.DeleteRequest{Key: key}) + return err +} + +// Existts checks if "key" is present in the store +func (s *Memo) Exists(key string) (bool, error) { + _, err := s.kvs.Fetch(context.Background(), &kvs.FetchRequest{Key: key}) + if err == nil { + return true, nil + } + if grpc.Code(err) == codes.NotFound { + return false, nil + } + return false, err +} + +// Watch for changes. Not supported by memo. +func (s *Memo) Watch(key string, stopCh <-chan struct{}) (<-chan *store.KVPair, error) { + return nil, store.ErrCallNotSupported +} + +// WatchTree for changes. Not supported by memo. +func (s *Memo) WatchTree(directory string, stopCh <-chan struct{}) (<-chan []*store.KVPair, error) { + return nil, store.ErrCallNotSupported +} + +// NewLock is not supported by memo. +func (s *Memo) NewLock(key string, options *store.LockOptions) (store.Locker, error) { + return nil, store.ErrCallNotSupported +} + +// List keys with given prefix. +func (s *Memo) List(directory string) ([]*store.KVPair, error) { + keys, err := s.kvs.List(context.Background(), + &kvs.ListRequest{Prefix: directory, MaxKeys: 1000000000}) + if err != nil { + return nil, err + } + var res []*store.KVPair + for _, k := range keys.Items { + kv, err := s.Get(k.Key) + if err != nil { + return nil, err + } + res = append(res, kv) + } + return res, nil +} + +// DeleteTree deletes all entries with given prefix. +func (s *Memo) DeleteTree(directory string) error { + keys, err := s.kvs.List(context.Background(), + &kvs.ListRequest{Prefix: directory, MaxKeys: 1000000000}) + if err != nil { + return err + } + for _, k := range keys.Items { + s.Delete(k.Key) + } + return nil +} + +// AtomicPut is not supported by memo. +func (s *Memo) AtomicPut(key string, value []byte, previous *store.KVPair, options *store.WriteOptions) (bool, *store.KVPair, error) { + return false, nil, store.ErrCallNotSupported +} + +// AtomicDelete is not supported by memo. +func (s *Memo) AtomicDelete(key string, previous *store.KVPair) (bool, error) { + return false, store.ErrCallNotSupported +} + +// Close the connection +func (s *Memo) Close() { +} diff --git a/store/memo/memo_kvs/memo_kvs.pb.go b/store/memo/memo_kvs/memo_kvs.pb.go new file mode 100644 index 00000000..a6b32529 --- /dev/null +++ b/store/memo/memo_kvs/memo_kvs.pb.go @@ -0,0 +1,570 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: memo_kvs.proto + +/* +Package memo_kvs is a generated protocol buffer package. + +It is generated from these files: + memo_kvs.proto + +It has these top-level messages: + InsertRequest + InsertResponse + UpdateRequest + UpdateResponse + UpsertRequest + UpsertResponse + FetchRequest + FetchResponse + DeleteRequest + DeleteResponse + ListRequest + ListItem + ListResponse +*/ +package memo_kvs + +import proto "github.com/golang/protobuf/proto" +import fmt "fmt" +import math "math" + +import ( + context "golang.org/x/net/context" + grpc "google.golang.org/grpc" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package + +type InsertRequest struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *InsertRequest) Reset() { *m = InsertRequest{} } +func (m *InsertRequest) String() string { return proto.CompactTextString(m) } +func (*InsertRequest) ProtoMessage() {} +func (*InsertRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } + +func (m *InsertRequest) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *InsertRequest) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type InsertResponse struct { +} + +func (m *InsertResponse) Reset() { *m = InsertResponse{} } +func (m *InsertResponse) String() string { return proto.CompactTextString(m) } +func (*InsertResponse) ProtoMessage() {} +func (*InsertResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +type UpdateRequest struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *UpdateRequest) Reset() { *m = UpdateRequest{} } +func (m *UpdateRequest) String() string { return proto.CompactTextString(m) } +func (*UpdateRequest) ProtoMessage() {} +func (*UpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } + +func (m *UpdateRequest) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *UpdateRequest) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type UpdateResponse struct { +} + +func (m *UpdateResponse) Reset() { *m = UpdateResponse{} } +func (m *UpdateResponse) String() string { return proto.CompactTextString(m) } +func (*UpdateResponse) ProtoMessage() {} +func (*UpdateResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } + +type UpsertRequest struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` + Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *UpsertRequest) Reset() { *m = UpsertRequest{} } +func (m *UpsertRequest) String() string { return proto.CompactTextString(m) } +func (*UpsertRequest) ProtoMessage() {} +func (*UpsertRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } + +func (m *UpsertRequest) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +func (m *UpsertRequest) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type UpsertResponse struct { +} + +func (m *UpsertResponse) Reset() { *m = UpsertResponse{} } +func (m *UpsertResponse) String() string { return proto.CompactTextString(m) } +func (*UpsertResponse) ProtoMessage() {} +func (*UpsertResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } + +type FetchRequest struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` +} + +func (m *FetchRequest) Reset() { *m = FetchRequest{} } +func (m *FetchRequest) String() string { return proto.CompactTextString(m) } +func (*FetchRequest) ProtoMessage() {} +func (*FetchRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } + +func (m *FetchRequest) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +type FetchResponse struct { + Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` +} + +func (m *FetchResponse) Reset() { *m = FetchResponse{} } +func (m *FetchResponse) String() string { return proto.CompactTextString(m) } +func (*FetchResponse) ProtoMessage() {} +func (*FetchResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } + +func (m *FetchResponse) GetValue() []byte { + if m != nil { + return m.Value + } + return nil +} + +type DeleteRequest struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` +} + +func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } +func (m *DeleteRequest) String() string { return proto.CompactTextString(m) } +func (*DeleteRequest) ProtoMessage() {} +func (*DeleteRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } + +func (m *DeleteRequest) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +type DeleteResponse struct { +} + +func (m *DeleteResponse) Reset() { *m = DeleteResponse{} } +func (m *DeleteResponse) String() string { return proto.CompactTextString(m) } +func (*DeleteResponse) ProtoMessage() {} +func (*DeleteResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } + +type ListRequest struct { + Prefix string `protobuf:"bytes,1,opt,name=prefix" json:"prefix,omitempty"` + Marker string `protobuf:"bytes,2,opt,name=marker" json:"marker,omitempty"` + Delimiter string `protobuf:"bytes,3,opt,name=delimiter" json:"delimiter,omitempty"` + MaxKeys uint64 `protobuf:"varint,4,opt,name=maxKeys" json:"maxKeys,omitempty"` +} + +func (m *ListRequest) Reset() { *m = ListRequest{} } +func (m *ListRequest) String() string { return proto.CompactTextString(m) } +func (*ListRequest) ProtoMessage() {} +func (*ListRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } + +func (m *ListRequest) GetPrefix() string { + if m != nil { + return m.Prefix + } + return "" +} + +func (m *ListRequest) GetMarker() string { + if m != nil { + return m.Marker + } + return "" +} + +func (m *ListRequest) GetDelimiter() string { + if m != nil { + return m.Delimiter + } + return "" +} + +func (m *ListRequest) GetMaxKeys() uint64 { + if m != nil { + return m.MaxKeys + } + return 0 +} + +type ListItem struct { + Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` +} + +func (m *ListItem) Reset() { *m = ListItem{} } +func (m *ListItem) String() string { return proto.CompactTextString(m) } +func (*ListItem) ProtoMessage() {} +func (*ListItem) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } + +func (m *ListItem) GetKey() string { + if m != nil { + return m.Key + } + return "" +} + +type ListResponse struct { + Items []*ListItem `protobuf:"bytes,1,rep,name=items" json:"items,omitempty"` + Prefixes []string `protobuf:"bytes,2,rep,name=prefixes" json:"prefixes,omitempty"` + Truncated bool `protobuf:"varint,3,opt,name=truncated" json:"truncated,omitempty"` +} + +func (m *ListResponse) Reset() { *m = ListResponse{} } +func (m *ListResponse) String() string { return proto.CompactTextString(m) } +func (*ListResponse) ProtoMessage() {} +func (*ListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } + +func (m *ListResponse) GetItems() []*ListItem { + if m != nil { + return m.Items + } + return nil +} + +func (m *ListResponse) GetPrefixes() []string { + if m != nil { + return m.Prefixes + } + return nil +} + +func (m *ListResponse) GetTruncated() bool { + if m != nil { + return m.Truncated + } + return false +} + +func init() { + proto.RegisterType((*InsertRequest)(nil), "memo.kvs.InsertRequest") + proto.RegisterType((*InsertResponse)(nil), "memo.kvs.InsertResponse") + proto.RegisterType((*UpdateRequest)(nil), "memo.kvs.UpdateRequest") + proto.RegisterType((*UpdateResponse)(nil), "memo.kvs.UpdateResponse") + proto.RegisterType((*UpsertRequest)(nil), "memo.kvs.UpsertRequest") + proto.RegisterType((*UpsertResponse)(nil), "memo.kvs.UpsertResponse") + proto.RegisterType((*FetchRequest)(nil), "memo.kvs.FetchRequest") + proto.RegisterType((*FetchResponse)(nil), "memo.kvs.FetchResponse") + proto.RegisterType((*DeleteRequest)(nil), "memo.kvs.DeleteRequest") + proto.RegisterType((*DeleteResponse)(nil), "memo.kvs.DeleteResponse") + proto.RegisterType((*ListRequest)(nil), "memo.kvs.ListRequest") + proto.RegisterType((*ListItem)(nil), "memo.kvs.ListItem") + proto.RegisterType((*ListResponse)(nil), "memo.kvs.ListResponse") +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// Client API for KeyValueStore service + +type KeyValueStoreClient interface { + Insert(ctx context.Context, in *InsertRequest, opts ...grpc.CallOption) (*InsertResponse, error) + Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) + Upsert(ctx context.Context, in *UpsertRequest, opts ...grpc.CallOption) (*UpsertResponse, error) + Fetch(ctx context.Context, in *FetchRequest, opts ...grpc.CallOption) (*FetchResponse, error) + Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) + List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) +} + +type keyValueStoreClient struct { + cc *grpc.ClientConn +} + +func NewKeyValueStoreClient(cc *grpc.ClientConn) KeyValueStoreClient { + return &keyValueStoreClient{cc} +} + +func (c *keyValueStoreClient) Insert(ctx context.Context, in *InsertRequest, opts ...grpc.CallOption) (*InsertResponse, error) { + out := new(InsertResponse) + err := grpc.Invoke(ctx, "/memo.kvs.KeyValueStore/Insert", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *keyValueStoreClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*UpdateResponse, error) { + out := new(UpdateResponse) + err := grpc.Invoke(ctx, "/memo.kvs.KeyValueStore/Update", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *keyValueStoreClient) Upsert(ctx context.Context, in *UpsertRequest, opts ...grpc.CallOption) (*UpsertResponse, error) { + out := new(UpsertResponse) + err := grpc.Invoke(ctx, "/memo.kvs.KeyValueStore/Upsert", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *keyValueStoreClient) Fetch(ctx context.Context, in *FetchRequest, opts ...grpc.CallOption) (*FetchResponse, error) { + out := new(FetchResponse) + err := grpc.Invoke(ctx, "/memo.kvs.KeyValueStore/Fetch", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *keyValueStoreClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error) { + out := new(DeleteResponse) + err := grpc.Invoke(ctx, "/memo.kvs.KeyValueStore/Delete", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *keyValueStoreClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) { + out := new(ListResponse) + err := grpc.Invoke(ctx, "/memo.kvs.KeyValueStore/List", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// Server API for KeyValueStore service + +type KeyValueStoreServer interface { + Insert(context.Context, *InsertRequest) (*InsertResponse, error) + Update(context.Context, *UpdateRequest) (*UpdateResponse, error) + Upsert(context.Context, *UpsertRequest) (*UpsertResponse, error) + Fetch(context.Context, *FetchRequest) (*FetchResponse, error) + Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) + List(context.Context, *ListRequest) (*ListResponse, error) +} + +func RegisterKeyValueStoreServer(s *grpc.Server, srv KeyValueStoreServer) { + s.RegisterService(&_KeyValueStore_serviceDesc, srv) +} + +func _KeyValueStore_Insert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InsertRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KeyValueStoreServer).Insert(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/memo.kvs.KeyValueStore/Insert", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KeyValueStoreServer).Insert(ctx, req.(*InsertRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _KeyValueStore_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KeyValueStoreServer).Update(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/memo.kvs.KeyValueStore/Update", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KeyValueStoreServer).Update(ctx, req.(*UpdateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _KeyValueStore_Upsert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpsertRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KeyValueStoreServer).Upsert(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/memo.kvs.KeyValueStore/Upsert", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KeyValueStoreServer).Upsert(ctx, req.(*UpsertRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _KeyValueStore_Fetch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(FetchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KeyValueStoreServer).Fetch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/memo.kvs.KeyValueStore/Fetch", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KeyValueStoreServer).Fetch(ctx, req.(*FetchRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _KeyValueStore_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KeyValueStoreServer).Delete(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/memo.kvs.KeyValueStore/Delete", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KeyValueStoreServer).Delete(ctx, req.(*DeleteRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _KeyValueStore_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KeyValueStoreServer).List(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/memo.kvs.KeyValueStore/List", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KeyValueStoreServer).List(ctx, req.(*ListRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _KeyValueStore_serviceDesc = grpc.ServiceDesc{ + ServiceName: "memo.kvs.KeyValueStore", + HandlerType: (*KeyValueStoreServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Insert", + Handler: _KeyValueStore_Insert_Handler, + }, + { + MethodName: "Update", + Handler: _KeyValueStore_Update_Handler, + }, + { + MethodName: "Upsert", + Handler: _KeyValueStore_Upsert_Handler, + }, + { + MethodName: "Fetch", + Handler: _KeyValueStore_Fetch_Handler, + }, + { + MethodName: "Delete", + Handler: _KeyValueStore_Delete_Handler, + }, + { + MethodName: "List", + Handler: _KeyValueStore_List_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "memo_kvs.proto", +} + +func init() { proto.RegisterFile("memo_kvs.proto", fileDescriptor0) } + +var fileDescriptor0 = []byte{ + // 413 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x9c, 0x53, 0xbf, 0x8f, 0xd3, 0x30, + 0x14, 0xbe, 0x5c, 0xda, 0x92, 0xbc, 0x6b, 0x4e, 0x27, 0x0b, 0x7a, 0x56, 0x75, 0x43, 0x88, 0x84, + 0x94, 0x29, 0xc3, 0x31, 0x9c, 0x84, 0xc4, 0x86, 0x90, 0x4e, 0x65, 0x32, 0x82, 0x15, 0x85, 0xf6, + 0x21, 0xa2, 0x34, 0x4d, 0xb0, 0x9d, 0xaa, 0xdd, 0xf8, 0xd3, 0x91, 0x63, 0xbb, 0x71, 0x52, 0x60, + 0xe8, 0x96, 0xf7, 0xfc, 0xbe, 0x1f, 0xcf, 0xfe, 0x02, 0xb7, 0x15, 0x56, 0xf5, 0xb7, 0x72, 0x2f, + 0xb2, 0x86, 0xd7, 0xb2, 0x26, 0x81, 0xaa, 0xb3, 0x72, 0x2f, 0x92, 0x27, 0x88, 0x9e, 0x77, 0x02, + 0xb9, 0x64, 0xf8, 0xab, 0x45, 0x21, 0xc9, 0x1d, 0xf8, 0x25, 0x1e, 0xa9, 0x17, 0x7b, 0x69, 0xc8, + 0xd4, 0x27, 0x79, 0x09, 0xd3, 0x7d, 0xbe, 0x6d, 0x91, 0x5e, 0xc7, 0x5e, 0x3a, 0x67, 0xba, 0x48, + 0xee, 0xe0, 0xd6, 0x02, 0x45, 0x53, 0xef, 0x04, 0x2a, 0xaa, 0x2f, 0xcd, 0x26, 0x97, 0x78, 0x01, + 0x95, 0x05, 0xba, 0x54, 0x17, 0xba, 0xb2, 0x40, 0x43, 0x15, 0xc3, 0xfc, 0x23, 0xca, 0xf5, 0xcf, + 0x7f, 0x32, 0x25, 0x6f, 0x20, 0x32, 0x13, 0x1a, 0xd2, 0x53, 0x7b, 0x2e, 0xf5, 0x6b, 0x88, 0x3e, + 0xe0, 0x16, 0xff, 0xb3, 0x9e, 0x52, 0xb7, 0x23, 0x46, 0xbd, 0x85, 0x9b, 0x4f, 0x85, 0x38, 0xad, + 0xb1, 0x80, 0x59, 0xc3, 0xf1, 0x47, 0x71, 0x30, 0x28, 0x53, 0xa9, 0x7e, 0x95, 0xf3, 0x12, 0x79, + 0xb7, 0x4d, 0xc8, 0x4c, 0x45, 0x1e, 0x20, 0xdc, 0xe0, 0xb6, 0xa8, 0x0a, 0x89, 0x9c, 0xfa, 0xdd, + 0x51, 0xdf, 0x20, 0x14, 0x5e, 0x54, 0xf9, 0x61, 0x85, 0x47, 0x41, 0x27, 0xb1, 0x97, 0x4e, 0x98, + 0x2d, 0x93, 0x07, 0x08, 0x94, 0xec, 0xb3, 0xc4, 0xea, 0x2f, 0x36, 0x39, 0xcc, 0xb5, 0x29, 0xb3, + 0x6f, 0x0a, 0xd3, 0x42, 0x62, 0x25, 0xa8, 0x17, 0xfb, 0xe9, 0xcd, 0x23, 0xc9, 0x6c, 0x3a, 0x32, + 0x4b, 0xc2, 0xf4, 0x00, 0x59, 0x42, 0xa0, 0x1d, 0xa3, 0xa0, 0xd7, 0xb1, 0x9f, 0x86, 0xec, 0x54, + 0x2b, 0xaf, 0x92, 0xb7, 0xbb, 0x75, 0x2e, 0x71, 0xd3, 0x79, 0x0d, 0x58, 0xdf, 0x78, 0xfc, 0xed, + 0x43, 0xb4, 0xc2, 0xe3, 0x57, 0x75, 0x95, 0x9f, 0x65, 0xcd, 0x91, 0xbc, 0x87, 0x99, 0x0e, 0x10, + 0xb9, 0xef, 0x05, 0x07, 0x59, 0x5c, 0xd2, 0xf3, 0x03, 0x73, 0xaf, 0x57, 0x0a, 0xae, 0x43, 0xe3, + 0xc2, 0x07, 0xf9, 0x73, 0xe1, 0xa3, 0x7c, 0x19, 0xf8, 0x58, 0x7d, 0x90, 0xb9, 0x21, 0x7c, 0xa4, + 0xfe, 0x0e, 0xa6, 0x5d, 0x66, 0xc8, 0xa2, 0x1f, 0x72, 0x63, 0xb6, 0xbc, 0x3f, 0xeb, 0xbb, 0xd2, + 0x3a, 0x25, 0xae, 0xf4, 0x20, 0x5a, 0xae, 0xf4, 0x28, 0x50, 0x57, 0xe4, 0x09, 0x26, 0xea, 0x59, + 0xc8, 0xab, 0xe1, 0x33, 0x59, 0xe8, 0x62, 0xdc, 0xb6, 0xc0, 0xef, 0xb3, 0xee, 0xdf, 0x7f, 0xfb, + 0x27, 0x00, 0x00, 0xff, 0xff, 0x6d, 0x76, 0x2d, 0x69, 0x0d, 0x04, 0x00, 0x00, +} diff --git a/store/store.go b/store/store.go index 7a4850c0..4efad4b1 100644 --- a/store/store.go +++ b/store/store.go @@ -18,6 +18,8 @@ const ( ZK Backend = "zk" // BOLTDB backend BOLTDB Backend = "boltdb" + // MEMO backend + MEMO Backend = "memo" ) var (