update snapshot

This commit is contained in:
siddontang 2014-10-10 22:45:22 +08:00
parent 180091e10f
commit 36f015268f
3 changed files with 81 additions and 19 deletions

View File

@ -81,7 +81,7 @@ compression = true
[snapshot] [snapshot]
# Path to store snapshot dump file # Path to store snapshot dump file
# if not set, use data_dir/snapshot # if not set, use data_dir/snapshot
# snapshot file name format is snap-2006-01-02T15:04:05.dump # snapshot file name format is snap-2006-01-02T15:04:05.999999999.dmp
path = "" path = ""
# Reserve newest max_num snapshot dump files # Reserve newest max_num snapshot dump files

View File

@ -14,7 +14,7 @@ import (
) )
const ( const (
snapshotTimeFormat = "2006-01-02T15:04:05" snapshotTimeFormat = "2006-01-02T15:04:05.999999999"
) )
type snapshotStore struct { type snapshotStore struct {
@ -91,28 +91,37 @@ func (s *snapshotStore) run() {
for { for {
select { select {
case <-t.C: case <-t.C:
s.purge() s.Lock()
s.purge(false)
s.Unlock()
case <-s.quit: case <-s.quit:
return return
} }
} }
} }
func (s *snapshotStore) purge() { func (s *snapshotStore) purge(create bool) {
s.Lock()
var names []string var names []string
num := s.cfg.Snapshot.MaxNum maxNum := s.cfg.Snapshot.MaxNum
if len(s.names) > num { num := len(s.names) - maxNum
names = s.names[0:num]
s.names = s.names[num:] if create {
num++
if num > len(s.names) {
num = len(s.names)
}
} }
s.Unlock() if num > 0 {
names = s.names[0:num]
for _, n := range names { n := copy(s.names, s.names[num:])
if err := os.Remove(s.snapshotPath(n)); err != nil { s.names = s.names[0:n]
log.Error("purge snapshot %s error %s", n, err.Error()) }
for _, name := range names {
if err := os.Remove(s.snapshotPath(name)); err != nil {
log.Error("purge snapshot %s error %s", name, err.Error())
} }
} }
} }
@ -125,10 +134,31 @@ type snapshotDumper interface {
Dump(w io.Writer) error Dump(w io.Writer) error
} }
func (s *snapshotStore) Create(d snapshotDumper) (*os.File, time.Time, error) { type snapshot struct {
io.ReadCloser
f *os.File
}
func (st *snapshot) Read(b []byte) (int, error) {
return st.f.Read(b)
}
func (st *snapshot) Close() error {
return st.f.Close()
}
func (st *snapshot) Size() int64 {
s, _ := st.f.Stat()
return s.Size()
}
func (s *snapshotStore) Create(d snapshotDumper) (*snapshot, time.Time, error) {
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
s.purge(true)
now := time.Now() now := time.Now()
name := snapshotName(now) name := snapshotName(now)
@ -147,14 +177,16 @@ func (s *snapshotStore) Create(d snapshotDumper) (*os.File, time.Time, error) {
return nil, time.Time{}, err return nil, time.Time{}, err
} }
f.Sync()
s.names = append(s.names, name) s.names = append(s.names, name)
f.Seek(0, os.SEEK_SET) f.Seek(0, os.SEEK_SET)
return f, now, nil return &snapshot{f: f}, now, nil
} }
func (s *snapshotStore) OpenLatest() (*os.File, time.Time, error) { func (s *snapshotStore) OpenLatest() (*snapshot, time.Time, error) {
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
@ -170,5 +202,5 @@ func (s *snapshotStore) OpenLatest() (*os.File, time.Time, error) {
return nil, time.Time{}, err return nil, time.Time{}, err
} }
return f, t, err return &snapshot{f: f}, t, err
} }

View File

@ -37,10 +37,40 @@ func TestSnapshot(t *testing.T) {
if b, _ := ioutil.ReadAll(f); string(b) != "hello world" { if b, _ := ioutil.ReadAll(f); string(b) != "hello world" {
t.Fatal("invalid read snapshot") t.Fatal("invalid read snapshot")
} }
if len(s.names) != 1 {
t.Fatal("must 1 snapshot")
}
} }
if len(s.names) != 1 { if f, _, err := s.Create(d); err != nil {
t.Fatal("mut one snapshot") t.Fatal(err)
} else {
defer f.Close()
if b, _ := ioutil.ReadAll(f); string(b) != "hello world" {
t.Fatal("invalid read snapshot")
}
if len(s.names) != 2 {
t.Fatal("must 2 snapshot")
}
}
if f, _, err := s.Create(d); err != nil {
t.Fatal(err)
} else {
defer f.Close()
if b, _ := ioutil.ReadAll(f); string(b) != "hello world" {
t.Fatal("invalid read snapshot")
}
if len(s.names) != 2 {
t.Fatal("must 2 snapshot")
}
}
fs, _ := ioutil.ReadDir(cfg.Snapshot.Path)
if len(fs) != 2 {
t.Fatal("must 2 snapshot")
} }
s.Close() s.Close()