Skip to content

Commit 9783782

Browse files
committed
tmp
1 parent 515c6ca commit 9783782

35 files changed

+5409
-5
lines changed

Makefile

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.PHONY: generate
2+
generate:
3+
docker build -t n0stack/storage/protoc proto
4+
docker run -it --rm \
5+
-u $(UID):$(GID) \
6+
-v /etc/passwd:/etc/passwd:ro \
7+
-v /etc/group:/etc/group:ro \
8+
-v $(PWD):/src/n0stack/storage \
9+
-v $(PWD):/go/src/github.com/n0stack/storage \
10+
n0stack/storage/protoc
11+
go generate -v ./...
12+
13+
.PHONY: build
14+
build:
15+
go build -o bin/api-generator api/generator/*

api/database/database.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package database
2+
3+
import (
4+
"context"
5+
6+
"github.com/n0stack/storage/api"
7+
8+
"github.com/golang/protobuf/proto"
9+
)
10+
11+
type Entity interface {
12+
proto.Message
13+
14+
GetMetadata() *api.Metadata
15+
}
16+
17+
type Database interface {
18+
List(ctx context.Context, f func(length int) []Entity) error
19+
Get(ctx context.Context, name string, entity Entity) error
20+
Apply(ctx context.Context, entity Entity) error
21+
SoftDelete(ctx context.Context, entity Entity) error
22+
HardDelete(ctx context.Context, entity Entity) error
23+
}

api/database/errors.go

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package database
2+
3+
import "errors"
4+
5+
var (
6+
ErrorNotFound = errors.New("not found")
7+
ErrorConflict = errors.New("conflicted")
8+
)

api/database/etcd.go

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package database
2+
3+
// const (
4+
// etcdDialTimeout = 5 * time.Second
5+
// etcdRequestTimeout = 500 * time.Millisecond
6+
// )
7+
8+
// type EtcdDatabase struct {
9+
// client clientv3.KV
10+
// conn *clientv3.Client
11+
// }
12+
13+
// func NewEtcdDatabase(endpoints []string) (*EtcdDatabase, error) {
14+
// e := &EtcdDatabase{}
15+
16+
// var err error
17+
// e.conn, err = clientv3.New(clientv3.Config{
18+
// Endpoints: endpoints,
19+
// DialTimeout: etcdDialTimeout,
20+
// })
21+
// if err != nil {
22+
// return nil, err
23+
// }
24+
25+
// e.client = e.conn.KV
26+
27+
// return e, nil
28+
// }
29+
30+
// // func (d *EtcdDatabase) AddPrefix(prefix string) datastore.Database {
31+
// // return &EtcdDatabase{
32+
// // client: namespace.NewKV(d.client, prefix+"/"),
33+
// // conn: d.conn,
34+
// // }
35+
// // }
36+
37+
// func defaultKey(key string) string {
38+
// return "default/" + key
39+
// }
40+
// func deletedKey(key string) string {
41+
// return "deleted/" + key
42+
// }
43+
44+
// func (d EtcdDatabase) List(ctx context.Context, f func(int) []proto.Message) error {
45+
// c, cancel := context.WithTimeout(ctx, etcdRequestTimeout)
46+
// defer cancel()
47+
48+
// resp, err := d.client.Get(c, defaultKey(""), clientv3.WithFromKey())
49+
// if err != nil {
50+
// return errors.Wrap(err, "Get()")
51+
// }
52+
// if len(resp.Kvs) == 0 {
53+
// return ErrorNotFound
54+
// }
55+
56+
// pb := f(len(resp.Kvs))
57+
58+
// for i, ev := range resp.Kvs {
59+
// err = proto.Unmarshal(ev.Value, pb[i])
60+
// if err != nil {
61+
// return errors.Wrap(err, "proto.Unmarshal()")
62+
// }
63+
// }
64+
65+
// return nil
66+
// }
67+
68+
// func (d EtcdDatabase) Get(ctx context.Context, name string, entity Entity) error {
69+
// resp, err := d.client.Get(ctx, defaultKey(name))
70+
// if err != nil {
71+
// return err
72+
// }
73+
// if resp.Count == 0 {
74+
// entity = nil
75+
// return ErrorNotFound
76+
// }
77+
78+
// err = proto.Unmarshal(resp.Kvs[0].Value, entity)
79+
// if err != nil {
80+
// return errors.Wrap(err, "proto.Unmarshal()")
81+
// }
82+
83+
// return nil
84+
// }
85+
86+
// func (d EtcdDatabase) Apply(ctx context.Context, entity Entity) error {
87+
// md := entity.GetMetadata()
88+
89+
// s, err := proto.Marshal(entity)
90+
// if err != nil {
91+
// return errors.Wrapf(err, "proto.Marshal(%v)", entity)
92+
// }
93+
94+
// txn := d.client.Txn(ctx)
95+
// txnRes, err := txn.
96+
// If(clientv3.Compare(clientv3.Version(defaultKey(md.Name)), "=", md.Revision)).
97+
// Then(clientv3.OpPut(defaultKey(md.Name), string(s))).
98+
// Commit()
99+
// if err != nil {
100+
// return err
101+
// }
102+
103+
// if !txnRes.Succeeded {
104+
// return ErrorConflict
105+
// }
106+
107+
// return nil
108+
// }
109+
110+
// func (d EtcdDatabase) SoftDelete(ctx context.Context, entity Entity) error {
111+
// md := entity.GetMetadata()
112+
// md.DeletedAt = ptypes.TimestampNow()
113+
114+
// s, err := proto.Marshal(entity)
115+
// if err != nil {
116+
// return errors.Wrapf(err, "proto.Marshal(%v)", entity)
117+
// }
118+
119+
// txn := d.client.Txn(ctx)
120+
// txnRes, err := txn.
121+
// If(clientv3.Compare(clientv3.Version(md.Name), "=", md.Revision)).
122+
// Then(
123+
// clientv3.OpDelete(defaultKey(md.Name)),
124+
// clientv3.OpPut(deletedKey(md.Uid), string(s)),
125+
// ).
126+
// Commit()
127+
// if err != nil {
128+
// return errors.Wrap(err, "txn.Commit()")
129+
// }
130+
131+
// if !txnRes.Succeeded {
132+
// return ErrorConflict
133+
// }
134+
135+
// return nil
136+
// }
137+
138+
// func (d EtcdDatabase) HardDelete(ctx context.Context, entity Entity) error {
139+
// return fmt.Errorf("unimplemented")
140+
// }
141+
142+
// func (d EtcdDatabase) Close() error {
143+
// return d.conn.Close()
144+
// }

api/database/memory.go

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package database
2+
3+
import (
4+
"context"
5+
"strings"
6+
7+
"github.com/golang/protobuf/proto"
8+
)
9+
10+
type MemoryDatabase struct {
11+
// 本当は `proto.Message` を入れたいが、何故か中身がなかったのでとりあえずシリアライズする
12+
Data map[string][]byte
13+
Deleted map[string][]byte
14+
15+
prefix string
16+
}
17+
18+
func NewMemoryDatabase() *MemoryDatabase {
19+
return &MemoryDatabase{
20+
Data: make(map[string][]byte),
21+
Deleted: make(map[string][]byte),
22+
}
23+
}
24+
25+
// func (m *MemoryDatabase) AddPrefix(prefix string) datastore.Datastore {
26+
// return &MemoryDatabase{
27+
// Data: m.Data,
28+
// prefix: m.prefix + prefix + "/",
29+
// }
30+
// }
31+
32+
func (m MemoryDatabase) List(ctx context.Context, f func(length int) []Entity) error {
33+
l := 0
34+
for k, _ := range m.Data {
35+
if strings.HasPrefix(k, m.prefix) {
36+
l++
37+
}
38+
}
39+
40+
if l == 0 {
41+
return ErrorNotFound
42+
}
43+
44+
pb := f(l)
45+
i := 0
46+
for k, v := range m.Data {
47+
if !strings.HasPrefix(k, m.prefix) {
48+
continue
49+
}
50+
51+
if err := proto.Unmarshal(v, pb[i]); err != nil {
52+
return err
53+
}
54+
55+
i++
56+
}
57+
58+
return nil
59+
}
60+
61+
func (m MemoryDatabase) Get(ctx context.Context, name string, entity Entity) error {
62+
v, ok := m.Data[m.getKey(name)]
63+
if !ok {
64+
entity = nil
65+
return ErrorNotFound
66+
}
67+
68+
if err := proto.Unmarshal(v, entity); err != nil {
69+
return err
70+
}
71+
72+
return nil
73+
}
74+
75+
func (m *MemoryDatabase) Apply(ctx context.Context, entity Entity) error {
76+
// if v, ok := m.Data[m.getKey(entity.GetMetadata().Name)]; ok {
77+
// if v.GetMetadata().Revision+1 != entity.GetMetadata().Revision {
78+
// return ErrorNotFound
79+
// }
80+
// }
81+
82+
var err error
83+
m.Data[m.getKey(entity.GetMetadata().Name)], err = proto.Marshal(entity)
84+
if err != nil {
85+
return err
86+
}
87+
88+
return nil
89+
}
90+
91+
func (m *MemoryDatabase) SoftDelete(ctx context.Context, entity Entity) error {
92+
md := entity.GetMetadata()
93+
94+
_, ok := m.Data[m.getKey(md.Name)]
95+
if ok {
96+
// if prev.GetMetadata().Revision+1 != md.Revision {
97+
// return ErrorNotFound
98+
// }
99+
100+
delete(m.Data, m.getKey(md.Name))
101+
102+
var err error
103+
m.Deleted[md.Uid], err = proto.Marshal(entity)
104+
if err != nil {
105+
return err
106+
}
107+
108+
return nil
109+
}
110+
111+
return ErrorNotFound
112+
}
113+
114+
func (m *MemoryDatabase) HardDelete(ctx context.Context, entity Entity) error {
115+
md := entity.GetMetadata()
116+
117+
_, ok := m.Deleted[m.getKey(md.Name)]
118+
if ok {
119+
// if prev.GetMetadata().Revision+1 != md.Revision {
120+
// return ErrorConflict
121+
// }
122+
123+
delete(m.Deleted, m.getKey(md.Name))
124+
125+
return nil
126+
}
127+
128+
return ErrorNotFound
129+
}
130+
131+
func (m MemoryDatabase) getKey(key string) string {
132+
return m.prefix + key
133+
}

0 commit comments

Comments
 (0)