code: func (db *db) Close() error {
  	// Since all transactions have a read lock on this mutex, this will
  	// cause Close to wait for all readers to complete.
  	db.closeLock.Lock()
  	defer db.closeLock.Unlock()
  
  	if db.closed {
  		return makeDbErr(database.ErrDbNotOpen, errDbNotOpenStr, nil)
  	}
  	db.closed = true
  
  	// NOTE: Since the above lock waits for all transactions to finish and
  	// prevents any new ones from being started, it is safe to flush the
  	// cache and clear all state without the individual locks.
  
  	// Close the database cache which will flush any existing entries to
  	// disk and close the underlying leveldb database.  Any error is saved
  	// and returned at the end after the remaining cleanup since the
  	// database will be marked closed even if this fails given there is no
  	// good way for the caller to recover from a failure here anyways.
  	closeErr := db.cache.Close()
  
  	// Close any open flat files that house the blocks.
  	wc := db.store.writeCursor
  	if wc.curFile.file != nil {
  		_ = wc.curFile.file.Close()
  		wc.curFile.file = nil
  	}
  	for _, blockFile := range db.store.openBlockFiles {
  		_ = blockFile.file.Close()
  	}
  	db.store.openBlockFiles = nil
  	db.store.openBlocksLRU.Init()
  	db.store.fileNumToLRUElem = nil
  
  	return closeErr
  }
docs: // Close cleanly shuts down the database and syncs all data.  It will block
  // until all database transactions have been finalized (rolled back or
  // committed).
  //
  // This function is part of the database.DB interface implementation.