Skip to content

Commit bea727b

Browse files
author
Hongchao Deng
committed
add log init and restore
1 parent cbf9f1c commit bea727b

File tree

5 files changed

+124
-38
lines changed

5 files changed

+124
-38
lines changed

db/backend.go

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package db
22

33
import (
4+
"fmt"
5+
"io/ioutil"
6+
"os"
47
"strings"
58

69
"github.com/go-distributed/xtree/db/log"
@@ -9,23 +12,46 @@ import (
912
)
1013

1114
type backend struct {
12-
bt *btree.BTree
13-
cache *cache
14-
rev int
15-
log *log.Log
15+
bt *btree.BTree
16+
cache *cache
17+
rev int
18+
log *log.Log
19+
config *DBConfig
1620
}
1721

1822
func newBackend() *backend {
19-
bt := btree.New(10)
20-
log, err := log.Create()
23+
dataDir, err := ioutil.TempDir("", "backend")
24+
if err != nil {
25+
panic("not implemented")
26+
}
27+
28+
config := &DBConfig{
29+
DataDir: dataDir,
30+
}
31+
b, err := newBackendWithConfig(config)
2132
if err != nil {
22-
panic("Not implemented")
33+
panic("not implemented")
2334
}
24-
return &backend{
25-
bt: bt,
26-
cache: newCache(),
27-
log: log,
35+
return b
36+
}
37+
38+
func newBackendWithConfig(config *DBConfig) (b *backend, err error) {
39+
bt := btree.New(10)
40+
b = &backend{
41+
bt: bt,
42+
cache: newCache(),
43+
config: config,
2844
}
45+
haveLog := log.Exist(config.DataDir)
46+
switch haveLog {
47+
case false:
48+
fmt.Println("didn't have log file. Init...")
49+
err = b.init(config)
50+
case true:
51+
fmt.Println("had log file. Restore...")
52+
err = b.restore(config)
53+
}
54+
return
2955
}
3056

3157
func (b *backend) getData(offset int64) []byte {
@@ -102,5 +128,26 @@ func (b *backend) Ls(pathname string) (paths []Path) {
102128
paths = append(paths, *p)
103129
return true
104130
})
131+
105132
return
106133
}
134+
135+
// init() creates a new log file
136+
func (b *backend) init(config *DBConfig) (err error) {
137+
b.log, err = log.Create(config.DataDir)
138+
return
139+
}
140+
141+
// restore() restores database from the log file.
142+
func (b *backend) restore(config *DBConfig) (err error) {
143+
panic("not implemented")
144+
}
145+
146+
func (b *backend) testableCrash() (err error) {
147+
panic("not implemented")
148+
}
149+
150+
// clean up resource after testing
151+
func (b *backend) testableCleanupResource() (err error) {
152+
return os.RemoveAll(b.config.DataDir)
153+
}

db/backend_test.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ func TestPut(t *testing.T) {
2727
t.Errorf("#%d: data = %s, want %s", i, v.data, tt.data)
2828
}
2929
}
30+
31+
b.testableCleanupResource()
3032
}
3133

3234
func TestPutOnExistingPath(t *testing.T) {
@@ -61,6 +63,7 @@ func TestPutOnExistingPath(t *testing.T) {
6163
t.Errorf("#%d 2: data = %s, want %s", i, v.data, tt.data2)
6264
}
6365
}
66+
b.testableCleanupResource()
6467
}
6568

6669
func TestGetMVCC(t *testing.T) {
@@ -96,15 +99,16 @@ func TestGetMVCC(t *testing.T) {
9699
t.Errorf("#%d: data = %s, want %s", i, v.data, tt.data)
97100
}
98101
}
102+
b.testableCleanupResource()
99103
}
100104

101105
func TestLs(t *testing.T) {
102-
back := newBackend()
106+
b := newBackend()
103107
d := []byte("somedata")
104-
back.Put(1, *newPath("/a"), d)
105-
back.Put(2, *newPath("/a/b"), d)
106-
back.Put(3, *newPath("/a/c"), d)
107-
back.Put(4, *newPath("/b"), d)
108+
b.Put(1, *newPath("/a"), d)
109+
b.Put(2, *newPath("/a/b"), d)
110+
b.Put(3, *newPath("/a/c"), d)
111+
b.Put(4, *newPath("/b"), d)
108112

109113
tests := []struct {
110114
p string
@@ -118,7 +122,7 @@ func TestLs(t *testing.T) {
118122
{"/c", []string{}},
119123
}
120124
for i, tt := range tests {
121-
ps := back.Ls(tt.p)
125+
ps := b.Ls(tt.p)
122126
if len(ps) != len(tt.wps) {
123127
t.Fatalf("#%d: len(ps) = %d, want %d", i, len(ps), len(tt.wps))
124128
}
@@ -128,6 +132,10 @@ func TestLs(t *testing.T) {
128132
}
129133
}
130134
}
135+
b.testableCleanupResource()
136+
}
137+
138+
func TestRestore(t *testing.T) {
131139
}
132140

133141
func BenchmarkPut(b *testing.B) {
@@ -143,6 +151,7 @@ func BenchmarkPut(b *testing.B) {
143151
for i := 1; i < b.N; i++ {
144152
back.Put(i, path[i], d)
145153
}
154+
back.testableCleanupResource()
146155
}
147156

148157
func BenchmarkGetWithCache(b *testing.B) {
@@ -163,6 +172,7 @@ func BenchmarkGetWithCache(b *testing.B) {
163172
back.Get(i, path[i])
164173
}
165174
}
175+
back.testableCleanupResource()
166176
}
167177

168178
func BenchmarkGetWithOutCache(b *testing.B) {
@@ -184,4 +194,5 @@ func BenchmarkGetWithOutCache(b *testing.B) {
184194
back.Get(i, path[i])
185195
}
186196
}
197+
back.testableCleanupResource()
187198
}

db/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package db
2+
3+
type DBConfig struct {
4+
DataDir string
5+
}

db/log/log.go

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,64 @@
11
package log
22

33
import (
4-
"io/ioutil"
54
"os"
5+
"path"
66

77
"github.com/go-distributed/xtree/db/message"
88
)
99

10+
const (
11+
logFilename = "records.log"
12+
)
13+
1014
type Log struct {
11-
f *os.File
15+
writeFile, readFile *os.File
16+
encoder *encoder
1217
}
1318

14-
func Create() (*Log, error) {
15-
f, err := ioutil.TempFile("", "backend")
16-
if err != nil {
17-
return nil, err
19+
func Create(dataDir string) (l *Log, err error) {
20+
p := path.Join(dataDir, logFilename)
21+
22+
var writeFile, readFile *os.File
23+
if writeFile, err = os.OpenFile(p,
24+
os.O_WRONLY|os.O_APPEND|os.O_SYNC|os.O_CREATE,
25+
0600); err != nil {
26+
return
1827
}
19-
return &Log{f}, nil
28+
if readFile, err = os.Open(p); err != nil {
29+
return
30+
}
31+
l = &Log{
32+
writeFile: writeFile,
33+
readFile: readFile,
34+
encoder: newEncoder(writeFile),
35+
}
36+
return
2037
}
2138

22-
func (l *Log) Destroy() error {
23-
if err := l.f.Close(); err != nil {
24-
return err
25-
}
26-
return os.Remove(l.f.Name())
39+
func Exist(dataDir string) bool {
40+
p := path.Join(dataDir, logFilename)
41+
_, err := os.Stat(p)
42+
return err == nil
2743
}
2844

2945
func (l *Log) GetRecord(offset int64) (r *message.Record, err error) {
30-
if _, err = l.f.Seek(offset, 0); err != nil {
46+
if _, err = l.readFile.Seek(offset, 0); err != nil {
3147
return
3248
}
33-
decoder := newDecoder(l.f)
49+
decoder := newDecoder(l.readFile)
3450
r = &message.Record{}
3551
err = decoder.decode(r)
3652
return
3753
}
3854

3955
func (l *Log) Append(r *message.Record) (offset int64, err error) {
40-
if offset, err = l.f.Seek(0, 2); err != nil {
56+
if offset, err = l.writeFile.Seek(0, os.SEEK_CUR); err != nil {
4157
return
4258
}
43-
encoder := newEncoder(l.f)
44-
if err = encoder.encode(r); err != nil {
59+
if err = l.encoder.encode(r); err != nil {
4560
return
4661
}
47-
err = encoder.flush()
62+
err = l.encoder.flush()
4863
return offset, err
4964
}

db/log/log_test.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package log
22

33
import (
4+
"io/ioutil"
5+
"os"
46
"reflect"
57
"testing"
68

@@ -10,11 +12,17 @@ import (
1012
func TestAppendAndGetRecord(t *testing.T) {
1113
var err error
1214
var log *Log
13-
if log, err = Create(); err != nil {
14-
t.Errorf("Create failed: %v", err)
15+
var dataDir string
16+
17+
if dataDir, err = ioutil.TempDir("", "logtest"); err != nil {
18+
t.Errorf("ioutil.TempDir failed: %v", err)
1519
}
1620

17-
defer log.Destroy()
21+
defer os.RemoveAll(dataDir)
22+
23+
if log, err = Create(dataDir); err != nil {
24+
t.Errorf("Create failed: %v", err)
25+
}
1826

1927
tests := []struct {
2028
offset int64

0 commit comments

Comments
 (0)