Open all account files at startup.

This change checks for all wallet files in the account directory, and
then attempts to open each of the available accounts for those
wallets.  Before, only the default account would ever be opened.
This commit is contained in:
Josh Rickmar 2014-01-23 17:12:55 -05:00
parent 830829a79f
commit b4373dc070
2 changed files with 77 additions and 9 deletions

View file

@ -325,6 +325,17 @@ func (store *AccountStore) Track() {
}
}
// WalletOpenError is a special error type so problems opening wallet
// files can be differentiated (by a type assertion) from other errors.
type WalletOpenError struct {
Err string
}
// Error satisifies the builtin error interface.
func (e *WalletOpenError) Error() string {
return e.Err
}
// OpenAccount opens an account described by account in the data
// directory specified by cfg. If the wallet does not exist, ErrNoWallet
// is returned as an error.
@ -356,12 +367,14 @@ func (store *AccountStore) OpenAccount(name string, cfg *config) error {
// Must create and save wallet first.
return ErrNoWallet
}
return fmt.Errorf("cannot open wallet file: %s", err)
msg := fmt.Sprintf("cannot open wallet file: %s", err)
return &WalletOpenError{msg}
}
defer wfile.Close()
if _, err = wlt.ReadFrom(wfile); err != nil {
return fmt.Errorf("cannot read wallet: %s", err)
msg := fmt.Sprintf("cannot read wallet: %s", err)
return &WalletOpenError{msg}
}
// Read tx file. If this fails, return a ErrNoTxs error and let

69
cmd.go
View file

@ -27,6 +27,7 @@ import (
"net/http"
_ "net/http/pprof"
"os"
"strings"
"sync"
"time"
)
@ -34,7 +35,9 @@ import (
var (
// ErrNoWallet describes an error where a wallet does not exist and
// must be created first.
ErrNoWallet = errors.New("wallet file does not exist")
ErrNoWallet = &WalletOpenError{
Err: "wallet file does not exist",
}
// ErrNoUtxos describes an error where the wallet file was successfully
// read, but the UTXO file was not. To properly handle this error,
@ -146,12 +149,8 @@ func main() {
// Check and update any old file locations.
updateOldFileLocations()
// Open default account.
// TODO(jrick): open all available accounts.
err = accountstore.OpenAccount("", cfg)
if err != nil {
log.Warnf("cannot open default account: %v", err)
}
// Open all account saved to disk.
OpenAccounts()
// Read CA file to verify a btcd TLS connection.
cafile, err := ioutil.ReadFile(cfg.CAFile)
@ -247,6 +246,62 @@ func main() {
}
}
// OpenAccounts attempts to open all saved accounts.
func OpenAccounts() {
// The default account must exist, or btcwallet acts as if no
// wallets/accounts have been created yet.
if err := accountstore.OpenAccount("", cfg); err != nil {
switch err.(type) {
case *WalletOpenError:
log.Errorf("Default account wallet file unreadable: %v", err)
return
default:
log.Warnf("Non-critical problem opening an account file: %v", err)
}
}
// Read all filenames in the account directory, and look for any
// filenames matching '*-wallet.bin'. These are wallets for
// additional saved accounts.
accountDir, err := os.Open(networkDir(cfg.Net()))
if err != nil {
// Can't continue.
log.Errorf("Unable to open account directory: %v", err)
return
}
defer accountDir.Close()
fileNames, err := accountDir.Readdirnames(0)
if err != nil {
// fileNames might be partially set, so log an error and
// at least try to open some accounts.
log.Errorf("Unable to read all account files: %v", err)
}
var accounts []string
for _, file := range fileNames {
if strings.HasSuffix(file, "-wallet.bin") {
name := strings.TrimSuffix(file, "-wallet.bin")
accounts = append(accounts, name)
}
}
// Open all additional accounts.
for _, a := range accounts {
// Log txstore/utxostore errors as these will be recovered
// from with a rescan, but wallet errors must be returned
// to the caller.
if err := accountstore.OpenAccount(a, cfg); err != nil {
switch err.(type) {
case *WalletOpenError:
log.Errorf("Error opening account's wallet: %v", err)
default:
log.Warnf("Non-critical error opening an account file: %v", err)
}
}
}
}
var accessRPC = make(chan *AccessCurrentRPCConn)
// AccessCurrentRPCConn is used to access the current RPC connection