diff --git a/database.go b/database.go index 47b4bb821740350edbf7d7cd9f76e649b0b01ac4..9e004992a350ec3aa4b7895e4206322c7b7b6646 100644 --- a/database.go +++ b/database.go @@ -50,9 +50,22 @@ func (id BookId) String() string { } func (id BookId) Key() []byte { - var buf bytes.Buffer - binary.Write(&buf, binary.LittleEndian, id) - return buf.Bytes() + var b [8]byte + binary.LittleEndian.PutUint64(b[:], uint64(id)) + return b[:] +} + +func NewID() BookId { + return BookId(rand.Int63()) +} + +func ParseID(s string) BookId { + id, _ := strconv.ParseUint(s, 10, 64) + return BookId(id) +} + +func ParseBinaryID(b []byte) BookId { + return BookId(binary.LittleEndian.Uint64(b)) } type Book struct { @@ -85,15 +98,6 @@ func init() { rand.Seed(seed) } -func NewID() BookId { - return BookId(rand.Int63()) -} - -func ParseID(s string) BookId { - id, _ := strconv.ParseUint(s, 10, 64) - return BookId(id) -} - // The structure that gets actually indexed. type flatBook struct { Title string `json:"title"` @@ -251,6 +255,42 @@ func (db *Database) setupIndex(path string) error { return nil } +var schemaVersionKey = []byte("_liber_schema_version") + +func (db *Database) getSchemaVersion() uint64 { + data, err := db.ldb.Get(schemaVersionKey, nil) + if err != nil { + return 0 + } + return binary.LittleEndian.Uint64(data) +} + +func (db *Database) setSchemaVersion(v uint64) { + var b [8]byte + binary.LittleEndian.PutUint64(b[:], v) + db.ldb.Put(schemaVersionKey, b[:], nil) +} + +type databaseMigration struct { + version uint64 + run func(db *Database) error +} + +func (db *Database) runMigrations(migrations []databaseMigration) error { + version := db.getSchemaVersion() + for _, m := range migrations { + if m.version < version { + continue + } + if err := m.run(db); err != nil { + return err + } + version = m.version + db.setSchemaVersion(version) + } + return nil +} + func (db *Database) Close() { db.index.Close() db.ldb.Close() @@ -570,10 +610,7 @@ func keyToId(key []byte) BookId { if n < 0 { return 0 } - - var id uint64 - binary.Read(bytes.NewReader(key[n+1:]), binary.LittleEndian, &id) - return BookId(id) + return ParseBinaryID(key[n+1:]) } func keyRange(prefix []byte) ([]byte, []byte) {