// NewLDBDatabase returns a LevelDB wrapped object. func NewLDBDatabase(file string, cache int) (*LDBDatabase, error) { // Calculate the cache allowance for this particular database cache = int(float64(cache) * cacheRatio[filepath.Base(file)]) if cache < 16 { cache = 16 } glog.V(logger.Info).Infof("Alloted %dMB cache to %s", cache, file) // Open the db and recover any potential corruptions db, err := leveldb.OpenFile(file, &opt.Options{ OpenFilesCacheCapacity: OpenFileLimit, BlockCacheCapacity: cache / 2 * opt.MiB, WriteBuffer: cache / 4 * opt.MiB, // Two of these are used internally }) if _, corrupted := err.(*errors.ErrCorrupted); corrupted { db, err = leveldb.RecoverFile(file, nil) } // (Re)check for errors and abort if opening of the db failed if err != nil { return nil, err } return &LDBDatabase{ fn: file, db: db, }, nil }
// newPersistentNodeDB creates/opens a leveldb backed persistent node database, // also flushing its contents in case of a version mismatch. func newPersistentNodeDB(path string, version int, self NodeID) (*nodeDB, error) { opts := &opt.Options{OpenFilesCacheCapacity: 5} db, err := leveldb.OpenFile(path, opts) if _, iscorrupted := err.(*errors.ErrCorrupted); iscorrupted { db, err = leveldb.RecoverFile(path, nil) } if err != nil { return nil, err } // The nodes contained in the cache correspond to a certain protocol version. // Flush all nodes if the version doesn't match. currentVer := make([]byte, binary.MaxVarintLen64) currentVer = currentVer[:binary.PutVarint(currentVer, int64(version))] blob, err := db.Get(nodeDBVersionKey, nil) switch err { case leveldb.ErrNotFound: // Version not found (i.e. empty cache), insert it if err := db.Put(nodeDBVersionKey, currentVer, nil); err != nil { db.Close() return nil, err } case nil: // Version present, flush if different if !bytes.Equal(blob, currentVer) { db.Close() if err = os.RemoveAll(path); err != nil { return nil, err } return newPersistentNodeDB(path, version, self) } } return &nodeDB{ lvl: db, self: self, quit: make(chan struct{}), }, nil }