func runSnapshot(cmd *Command) error { f, err := os.OpenFile( cmd.Globals.File, os.O_CREATE|os.O_EXCL|os.O_WRONLY|os.O_TRUNC, 0666, ) if err != nil { if os.IsExist(err) { return fmt.Errorf("Journal already exists at %s", cmd.Globals.File) } return fmt.Errorf("Unable to open journal: %s", err) } j := journal.New(f) err = journal.Snapshot(cmd.Conn, cmd.Rev, cmd.Globals.Root, j) if err != nil { return err } err = f.Sync() if err != nil { return fmt.Errorf("file sync failed: %s", err) } return nil }
func runJournal(cmd *Command) error { sighupc := make(chan os.Signal, 1) signal.Notify(sighupc, syscall.SIGHUP) f, err := newJournalFile(cmd.Globals.File) if err != nil { return err } defer f.Close() j := journal.New(f) err = journal.Snapshot(cmd.Conn, cmd.Rev, cmd.Globals.Root, j) if err != nil { return err } if err := f.Sync(); err != nil { return fmt.Errorf("file sync failed: %s", err) } var ( isUnsynced = false opCounter = 0 rev = cmd.Rev syncInterval = 10 * time.Second syncOps = 100 watchroot = path.Join(cmd.Globals.Root, "**") errc = make(chan error) eventc = make(chan doozer.Event) ticker = time.Tick(syncInterval) ) go func(errc chan error, eventc chan doozer.Event, rev int64) { for { ev, err := cmd.Conn.Wait(watchroot, rev+1) if err != nil { errc <- fmt.Errorf("conn wait failed: %s", err) return } // Advance in time! rev = ev.Rev eventc <- ev } }(errc, eventc, rev) for { select { case ev := <-eventc: var entry *journal.Entry if ev.IsSet() { entry = journal.NewEntry(ev.Rev, journal.OpSet, ev.Path, ev.Body) } else if ev.IsDel() { entry = journal.NewEntry(ev.Rev, journal.OpDel, ev.Path, []byte{}) } else { continue } err = j.Append(entry) if err != nil { return err } opCounter++ // Log entry b, err := journal.Marshal(entry) if err != nil { return fmt.Errorf("entry marshal failed: %s", err) } if !strings.HasPrefix(ev.Path, journal.InternalPrefix) { fmt.Fprintf(os.Stdout, "%s\n", string(b)) } case <-sighupc: if err := f.reopen(); err != nil { return err } case err := <-errc: return err case <-ticker: isUnsynced = true } if opCounter >= syncOps || isUnsynced { if err := f.Sync(); err != nil { return fmt.Errorf("file sync failed: %s", err) } isUnsynced = false opCounter = 0 } } }