btcd/upgrade.go
Dave Collins eb8688df79 Convert btcd to use new btclog package.
Also, make every subsystem within btcd use its own logger instance so each
subsystem can have its own level specified independent of the others.

This is work towards #48.
2013-11-21 17:41:21 -06:00

178 lines
5.1 KiB
Go

// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
import (
"io"
"os"
"path/filepath"
)
// dirEmpty returns whether or not the specified directory path is empty.
func dirEmpty(dirPath string) (bool, error) {
f, err := os.Open(dirPath)
defer f.Close()
// Read the names of a max of one entry from the directory. When the
// directory is empty, an io.EOF error will be returned, so allow it.
names, err := f.Readdirnames(1)
if err != nil && err != io.EOF {
return false, err
}
return len(names) == 0, nil
}
// oldBtcdHomeDir returns the OS specific home directory btcd used prior to
// version 0.3.3. This has since been replaced with btcutil.AppDataDir, but
// this function is still provided for the automatic upgrade path.
func oldBtcdHomeDir() string {
// Search for Windows APPDATA first. This won't exist on POSIX OSes.
appData := os.Getenv("APPDATA")
if appData != "" {
return filepath.Join(appData, "btcd")
}
// Fall back to standard HOME directory that works for most POSIX OSes.
home := os.Getenv("HOME")
if home != "" {
return filepath.Join(home, ".btcd")
}
// In the worst case, use the current directory.
return "."
}
// upgradeDBPathNet moves the database for a specific network from its
// location prior to btcd version 0.2.0 and uses heuristics to ascertain the old
// database type to rename to the new format.
func upgradeDBPathNet(oldDbPath, netName string) error {
// Prior to version 0.2.0, the database was named the same thing for
// both sqlite and leveldb. Use heuristics to figure out the type
// of the database and move it to the new path and name introduced with
// version 0.2.0 accordingly.
fi, err := os.Stat(oldDbPath)
if err == nil {
oldDbType := "sqlite"
if fi.IsDir() {
oldDbType = "leveldb"
}
// The new database name is based on the database type and
// resides in the a directory named after the network type.
newDbRoot := filepath.Join(filepath.Dir(cfg.DataDir), netName)
newDbName := blockDbNamePrefix + "_" + oldDbType
if oldDbType == "sqlite" {
newDbName = newDbName + ".db"
}
newDbPath := filepath.Join(newDbRoot, newDbName)
// Create the new path if needed.
err = os.MkdirAll(newDbRoot, 0700)
if err != nil {
return err
}
// Move and rename the old database.
err := os.Rename(oldDbPath, newDbPath)
if err != nil {
return err
}
}
return nil
}
// upgradeDBPaths moves the databases from their locations prior to btcd
// version 0.2.0 to their new locations.
func upgradeDBPaths() error {
// Prior to version 0.2.0, the databases were in the "db" directory and
// their names were suffixed by "testnet" and "regtest" for their
// respective networks. Check for the old database and update it to the
// new path introduced with version 0.2.0 accodingly.
oldDbRoot := filepath.Join(oldBtcdHomeDir(), "db")
upgradeDBPathNet(filepath.Join(oldDbRoot, "btcd.db"), "mainnet")
upgradeDBPathNet(filepath.Join(oldDbRoot, "btcd_testnet.db"), "testnet")
upgradeDBPathNet(filepath.Join(oldDbRoot, "btcd_regtest.db"), "regtest")
// Remove the old db directory.
err := os.RemoveAll(oldDbRoot)
if err != nil {
return err
}
return nil
}
// upgradeDataPaths moves the application data from its location prior to btcd
// version 0.3.3 to its new location.
func upgradeDataPaths() error {
// No need to migrate if the old and new home paths are the same.
oldHomePath := oldBtcdHomeDir()
newHomePath := btcdHomeDir
if oldHomePath == newHomePath {
return nil
}
// Only migrate if the old path exists and the new one doesn't.
if fileExists(oldHomePath) && !fileExists(newHomePath) {
// Create the new path.
btcdLog.Infof("Migrating application home path from '%s' to '%s'",
oldHomePath, newHomePath)
err := os.MkdirAll(newHomePath, 0700)
if err != nil {
return err
}
// Move old btcd.conf into new location if needed.
oldConfPath := filepath.Join(oldHomePath, defaultConfigFilename)
newConfPath := filepath.Join(newHomePath, defaultConfigFilename)
if fileExists(oldConfPath) && !fileExists(newConfPath) {
err := os.Rename(oldConfPath, newConfPath)
if err != nil {
return err
}
}
// Move old data directory into new location if needed.
oldDataPath := filepath.Join(oldHomePath, defaultDataDirname)
newDataPath := filepath.Join(newHomePath, defaultDataDirname)
if fileExists(oldDataPath) && !fileExists(newDataPath) {
err := os.Rename(oldDataPath, newDataPath)
if err != nil {
return err
}
}
// Remove the old home if it is empty or show a warning if not.
ohpEmpty, err := dirEmpty(oldHomePath)
if err != nil {
return err
}
if ohpEmpty {
err := os.Remove(oldHomePath)
if err != nil {
return err
}
} else {
btcdLog.Warnf("Not removing '%s' since it contains files "+
"not created by this application. You may "+
"want to manually move them or delete them.",
oldHomePath)
}
}
return nil
}
// doUpgrades performs upgrades to btcd as new versions require it.
func doUpgrades() error {
err := upgradeDBPaths()
if err != nil {
return err
}
return upgradeDataPaths()
}