Search code examples
databasemultithreadinggoleveldblevigo

What is the appropriate way to multithread LevelDB in Go?


I have implemented the levigo wrapper in my project so I can use LevelDB. The declaration is fairly boilerplate, like so:

func NewLeveldbStorage(dbPath string) *leveldbStorage {
     opts := levigo.NewOptions()
     opts.SetCache(levigo.NewLRUCache(3<<30))
     opts.SetCreateIfMissing(true)
     log.Debugf("Entering Open")
     db, err := levigo.Open(dbPath, opts); if err != nil {
         log.Fatal("BOOM %v", err)
     }
     log.Debugf("Finished calling open")
     opts.Close()
     return &leveldbStorage{db:db}
 }

Here is the struct returned:

type leveldbStorage struct {
     db *levigo.DB
}

I then made a few simple GET and STORE commands on the struct that essentially just use s.db.Get and s.db.Put. This works fine in my tests, but when I run the following benchmark:

 func BenchmarkLeviDbGet(b *testing.B) {
     s := storage.NewLeveldbStorage("/path/to/db")
     value := "value"
     uid,_ := s.Store(value)

     b.ResetTimer()
     for i := 0; i < b.N; i++ {
         s.Get(uid)
     }

This benchmark, when run, returns:

 2014/10/12 21:17:09 BOOM %vIO error: lock /path/to/db/LOCK: already held by process

Is there an appropriate way to use levigo/leveldb to enable multithreaded reading? What about writing? I would not be surprised if multithreaded writing is not possible, but multithreaded reading seems like it should be. What am I doing wrong here?


Solution

  • You either need to close the database file or use a global instance to it, you can't open the file multiple times, you can however access the same instance from multiple goroutines.