Notify user of db upgrade.

This commit is contained in:
Qi Xiao 2017-07-20 00:51:42 +02:00
parent 06b62b2889
commit 013410db16
2 changed files with 66 additions and 19 deletions

View File

@ -21,13 +21,6 @@ var logger = util.GetLogger("[daemon] ")
func Serve(sockpath, dbpath string) {
logger.Println("pid is", syscall.Getpid())
st, err := store.NewStore(dbpath)
if err != nil {
logger.Printf("failed to create storage: %v", err)
logger.Println("aborting")
os.Exit(2)
}
logger.Println("going to listen", sockpath)
listener, err := net.Listen("unix", sockpath)
if err != nil {
@ -36,6 +29,12 @@ func Serve(sockpath, dbpath string) {
os.Exit(2)
}
st, err := store.NewStore(dbpath)
if err != nil {
logger.Printf("failed to create storage: %v", err)
logger.Printf("serving anyway")
}
quitSignals := make(chan os.Signal)
quitChan := make(chan struct{})
signal.Notify(quitSignals, syscall.SIGTERM, syscall.SIGINT)
@ -61,7 +60,7 @@ func Serve(sockpath, dbpath string) {
logger.Println("listener closed, waiting to exit")
}()
service := &Service{st}
service := &Service{st, err}
rpc.RegisterName(api.ServiceName, service)
logger.Println("starting to serve RPC calls")
@ -99,9 +98,13 @@ func Serve(sockpath, dbpath string) {
// Service provides the daemon RPC service.
type Service struct {
store *store.Store
err error
}
func (s *Service) Version(req *api.VersionRequest, res *api.VersionResponse) error {
if s.err != nil {
return s.err
}
res.Version = api.Version
return nil
}
@ -112,61 +115,94 @@ func (s *Service) Pid(req *api.PidRequest, res *api.PidResponse) error {
}
func (s *Service) NextCmdSeq(req *api.NextCmdSeqRequest, res *api.NextCmdSeqResponse) error {
if s.err != nil {
return s.err
}
seq, err := s.store.NextCmdSeq()
res.Seq = seq
return err
}
func (s *Service) AddCmd(req *api.AddCmdRequest, res *api.AddCmdResponse) error {
if s.err != nil {
return s.err
}
seq, err := s.store.AddCmd(req.Text)
res.Seq = seq
return err
}
func (s *Service) Cmd(req *api.CmdRequest, res *api.CmdResponse) error {
if s.err != nil {
return s.err
}
text, err := s.store.Cmd(req.Seq)
res.Text = text
return err
}
func (s *Service) Cmds(req *api.CmdsRequest, res *api.CmdsResponse) error {
if s.err != nil {
return s.err
}
cmds, err := s.store.Cmds(req.From, req.Upto)
res.Cmds = cmds
return err
}
func (s *Service) NextCmd(req *api.NextCmdRequest, res *api.NextCmdResponse) error {
if s.err != nil {
return s.err
}
seq, text, err := s.store.NextCmd(req.From, req.Prefix)
res.Seq, res.Text = seq, text
return err
}
func (s *Service) PrevCmd(req *api.PrevCmdRequest, res *api.PrevCmdResponse) error {
if s.err != nil {
return s.err
}
seq, text, err := s.store.PrevCmd(req.Upto, req.Prefix)
res.Seq, res.Text = seq, text
return err
}
func (s *Service) AddDir(req *api.AddDirRequest, res *api.AddDirResponse) error {
if s.err != nil {
return s.err
}
return s.store.AddDir(req.Dir, req.IncFactor)
}
func (s *Service) Dirs(req *api.DirsRequest, res *api.DirsResponse) error {
if s.err != nil {
return s.err
}
dirs, err := s.store.GetDirs(req.Blacklist)
res.Dirs = dirs
return err
}
func (s *Service) SharedVar(req *api.SharedVarRequest, res *api.SharedVarResponse) error {
if s.err != nil {
return s.err
}
value, err := s.store.GetSharedVar(req.Name)
res.Value = value
return err
}
func (s *Service) SetSharedVar(req *api.SetSharedVarRequest, res *api.SetSharedVarResponse) error {
if s.err != nil {
return s.err
}
return s.store.SetSharedVar(req.Name, req.Value)
}
func (s *Service) DelSharedVar(req *api.DelSharedVarRequest, res *api.DelSharedVarResponse) error {
if s.err != nil {
return s.err
}
return s.store.DelSharedVar(req.Name)
}

33
main.go
View File

@ -18,6 +18,7 @@ import (
"syscall"
"time"
"github.com/boltdb/bolt"
"github.com/elves/elvish/daemon"
"github.com/elves/elvish/daemon/api"
"github.com/elves/elvish/daemon/service"
@ -123,12 +124,14 @@ func main() {
} else {
// Shell or web. Set up common runtime components.
ev, cl := initRuntime()
defer func() {
err := cl.Close()
if err != nil {
fmt.Fprintln(os.Stderr, "warning: failed to close connection to daemon:", err)
}
}()
if cl != nil {
defer func() {
err := cl.Close()
if err != nil {
fmt.Fprintln(os.Stderr, "warning: failed to close connection to daemon:", err)
}
}()
}
if *isweb {
if *cmd {
@ -151,6 +154,8 @@ const (
daemonWaitTotal = daemonWaitOneLoop * daemonWaitLoops
)
const upgradeDbNotice = `If you upgraded Elvish from a pre-0.10 version, you need to upgrade your database by following instructions in https://github.com/elves/upgrade-db-for-0.10/`
func initRuntime() (*eval.Evaler, *api.Client) {
var dataDir string
var err error
@ -192,8 +197,12 @@ func initRuntime() (*eval.Evaler, *api.Client) {
version, err := cl.Version()
if err != nil {
fmt.Fprintln(os.Stderr, "warning: socket exists but not responding version RPC:", err)
cl.Close()
cl = nil
// TODO(xiaq): Remove this when the SQLite-backed database
// becomes an unmemorable past (perhaps 6 months after the
// switch to boltdb).
if err.Error() == bolt.ErrInvalid.Error() {
fmt.Fprintln(os.Stderr, upgradeDbNotice)
}
goto spawnDaemonEnd
}
logger.Printf("daemon serving version %d, want version %d", version, api.Version)
@ -225,14 +234,16 @@ func initRuntime() (*eval.Evaler, *api.Client) {
} else {
logger.Println("started daemon")
}
for i := 0; i < daemonWaitLoops; i++ {
for i := 0; i <= daemonWaitLoops; i++ {
_, err := cl.Version()
if err == nil {
logger.Println("daemon online")
goto spawnDaemonEnd
} else if i == daemonWaitLoops-1 {
} else if err.Error() == bolt.ErrInvalid.Error() {
fmt.Fprintln(os.Stderr, upgradeDbNotice)
goto spawnDaemonEnd
} else if i == daemonWaitLoops {
fmt.Fprintf(os.Stderr, "cannot connect to daemon after %v: %v\n", daemonWaitTotal, err)
cl = nil
goto spawnDaemonEnd
}
time.Sleep(daemonWaitOneLoop)