func New(path string) (s *Storage, err error) { kyoto := cabinet.New() if err = kyoto.Open(path, cabinet.KCOWRITER|cabinet.KCOCREATE); err != nil { return } s = &Storage{ kyoto: kyoto, counters: make(map[string]*counter), } s.loadState() go s.keepStatePersisted() return }
func OpenKyotoDB(filename string, writemode bool) (KyotoDB, error) { db := KyotoDB{} db.kcdb = cabinet.New() mode := cabinet.KCOREADER if writemode { mode = cabinet.KCOWRITER | cabinet.KCOCREATE } err := db.kcdb.Open(filename, mode) if err != nil { db.kcdb.Del() db.kcdb = nil // errors returned by KC are pretty sparse ;-( return db, fmt.Errorf("could not open %s: %s", filename, err) } err = db.checkVersion( filename, writemode, CURRENT_VERSION, MIN_VERSION, MAX_VERSION) if err != nil { db.Close() return db, err } return db, nil }
func Test_KyotoDB_checkVersion(t *testing.T) { cleanup := testutils.Chtemp() defer cleanup() // brand-new empty DB with no version number in it db := KyotoDB{} db.kcdb = cabinet.New() filename := "test.kch" err := db.kcdb.Open(filename, cabinet.KCOWRITER|cabinet.KCOCREATE) if err != nil { t.Fatal(err) } // checkVersion() on an empty DB in read-only mode fails, because // it can neither read nor write the version number err = db.checkVersion(filename, false, 0, 0, 0) expect := "database test.kch has no version number" if err == nil || err.Error() != expect { t.Errorf("expected error %s, but got %v", expect, err) } // in write mode it's OK, and sets the version number in the file err = db.checkVersion(filename, true, 513, 513, 513) assert.Nil(t, err) versionkey := makekey(PREFIX_META, "version") val, err := db.kcdb.Get(versionkey) assert.Nil(t, err) assert.Equal(t, "\x00\x00\x02\x01", string(val)) // once the version number is in the file, write mode doesn't // matter -- now it's down to comparing with the supported range // of versions err = db.checkVersion(filename, false, 513, 134, 231) expect = "database test.kch is from the future (database version = 513, but max supported version = 231)" if err == nil || err.Error() != expect { t.Errorf("expected error\n%s\nbut got\n%v", expect, err) } err = db.checkVersion(filename, false, 513, 534, 546) expect = "database test.kch is too old (database version = 513, but min supported version = 534)" if err == nil || err.Error() != expect { t.Errorf("expected error\n%s\nbut got\n%v", expect, err) } err = db.checkVersion(filename, false, 513, 512, 514) assert.Nil(t, err) err = db.checkVersion(filename, false, 513, 513, 513) assert.Nil(t, err) err = db.checkVersion(filename, false, 513, 512, 513) assert.Nil(t, err) err = db.checkVersion(filename, false, 513, 513, 514) assert.Nil(t, err) // corrupt version number err = db.kcdb.Set(versionkey, []byte{0, 0x43, 0}) assert.Nil(t, err) err = db.checkVersion(filename, false, 513, 513, 513) expect = "database test.kch: unable to decode version number (004300)" if err == nil || err.Error() != expect { t.Errorf("expected error\n%s\nbut got\n%v", expect, err) } }