From 034e11ae50fe61d0d14556fc7c317b18c93676e9 Mon Sep 17 00:00:00 2001 From: ale <ale@incal.net> Date: Tue, 25 Nov 2014 23:57:47 +0000 Subject: [PATCH] add command to regenerate the search index --- cmd/liber/liber.go | 15 +++++++++++++-- database.go | 30 +++++++++++++++++++++++++++++- database_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ sync_test.go | 8 ++++++-- 4 files changed, 88 insertions(+), 5 deletions(-) diff --git a/cmd/liber/liber.go b/cmd/liber/liber.go index f423492..728a430 100644 --- a/cmd/liber/liber.go +++ b/cmd/liber/liber.go @@ -24,6 +24,7 @@ var ( update = flag.Bool("update", false, "update the db") search = flag.Bool("search", false, "search something") remotesync = flag.String("sync", "", "push data to remote server") + reindex = flag.Bool("reindex", false, "re-create the search index") httpserver = flag.String("http-server", "", "start the HTTP server on the specified address") noninteractive = flag.Bool("noninteractive", false, "disable interactive metadata prompts on update") ) @@ -185,6 +186,14 @@ func doHttpServer(db *liber.Database, addr string) { log.Fatal(server.ListenAndServe()) } +func doReindex(db *liber.Database) { + log.Println("starting database indexing") + if err := db.Reindex(); err != nil { + log.Fatal(err) + } + log.Println("database indexing complete") +} + func b2i(b bool) int { if b { return 1 @@ -203,9 +212,9 @@ func expandTilde(path string) string { func main() { log.SetFlags(0) flag.Parse() - nset := b2i(*update) + b2i(*search) + b2i(*httpserver != "") + b2i(*remotesync != "") + nset := b2i(*update) + b2i(*search) + b2i(*httpserver != "") + b2i(*remotesync != "") + b2i(*reindex) if nset != 1 { - log.Fatal("Must specify one of --update, --sync, --search or --http-server") + log.Fatal("Must specify one of --update, --sync, --search, --reindex or --http-server") } if *bookDir == "" { log.Fatal("Must specify --book-dir") @@ -236,6 +245,8 @@ func main() { log.Fatal("No query specified") } doSearch(db, query) + } else if *reindex { + doReindex(db) } else if *httpserver != "" { doHttpServer(db, *httpserver) } diff --git a/database.go b/database.go index 101e413..6db4027 100644 --- a/database.go +++ b/database.go @@ -175,6 +175,8 @@ type Database struct { leveldbFilter *levigo.FilterPolicy index bleve.Index + + path string } func NewDb(path string) (*Database, error) { @@ -186,7 +188,7 @@ func NewDb(path string) (*Database, error) { } // Initialize our database and the index. - d := &Database{} + d := &Database{path: path} if err := d.setupLevelDb(filepath.Join(path, "db")); err != nil { return nil, err } @@ -385,6 +387,32 @@ func (db *Database) Scan(bucket []byte) *DatabaseIterator { } } +// Reindex the entire database. This is an administrative operation, +// to be performed after an incompatible index schema change. It will +// delete the existing index and re-create it from scratch. +func (db *Database) Reindex() error { + // Close the index, delete it, and re-open it. + db.index.Close() + + indexPath := filepath.Join(db.path, "index") + if err := os.RemoveAll(indexPath); err != nil { + return err + } + if err := db.setupIndex(indexPath); err != nil { + return err + } + + // Scan the database and re-index everything. + for i := db.Scan(BookBucket); i.Valid(); i.Next() { + var book Book + if err := i.Value(&book); err != nil { + continue + } + db.index.Index(i.Id().String(), flatten(&book)) + } + return nil +} + type SearchResult struct { Results []*Book NumResults int diff --git a/database_test.go b/database_test.go index 72665f8..d6453d4 100644 --- a/database_test.go +++ b/database_test.go @@ -229,6 +229,46 @@ func TestDatabase_Find(t *testing.T) { } } +func TestDatabase_Reindex(t *testing.T) { + td, db := newTestDatabase2(t) + defer td.Close() + book, _ := db.GetBook(td.refbookid) + m := book.Metadata + + doTest := func() { + // Find the first time. + if result, err := db.Find(m.Uniques()); err != nil { + t.Errorf("Not found: %v", err) + } else if result.Id != book.Id { + t.Errorf("Bad match with ISBN: got=%d, expected=%d", result.Id, book.Id) + } + } + + doTest() + if err := db.Reindex(); err != nil { + t.Fatalf("Reindex: %v", err) + } + doTest() +} + +// func TestDatabase_Find2(t *testing.T) { +// td, db := newTestDatabase(t) +// defer td.Close() + +// testdata := []*Metadata{ +// &Metadata{Title: "PHILIP K", Creator: []string{"Antonio Marigonda"}, Language: []string{"it"}, Sources: []MetadataSource{MetadataSource{Name: "opf", ID: "6809f8b6-3151-41ef-b05a-0eb113746674"}}}, +// } + +// for _, m := range testdata { +// t.Logf("uniques = %v", m.Uniques()) +// id := NewID() +// db.PutBook(&Book{Id: id, Metadata: m}) +// if _, err := db.Find(m.Uniques()); err != nil { +// t.Errorf("Could not find book: %#v", m) +// } +// } +// } + func TestDatabase_Suggest(t *testing.T) { td, db := newTestDatabase(t) defer td.Close() diff --git a/sync_test.go b/sync_test.go index acb7b7e..ec87c35 100644 --- a/sync_test.go +++ b/sync_test.go @@ -50,8 +50,7 @@ func TestSync_Sync(t *testing.T) { defer srv.Close() cl := NewRemoteServer(srv.URL) - err := db.Sync(clientStorage, cl) - if err != nil { + if err := db.Sync(clientStorage, cl); err != nil { t.Fatalf("Sync(): %v", err) } @@ -64,4 +63,9 @@ func TestSync_Sync(t *testing.T) { t.Errorf("Book %d missing from db2: %v", i+1, err) } } + + // Calling Sync again should not result in errors. + if err := db.Sync(clientStorage, cl); err != nil { + t.Fatalf("Sync(): %v", err) + } } -- GitLab