func writer( conn *doozer.Conn, root string, entryc chan *journal.Entry, errc chan error, ) { for entry := range entryc { if strings.HasPrefix(entry.Path, root) && !strings.HasPrefix(entry.Path, journal.InternalPrefix) { var err error switch entry.Op { case journal.OpSet: _, e := conn.Set(entry.Path, -1, entry.Value) if e != nil { err = fmt.Errorf("unable setting '%s' to '%s'", entry.Path, string(entry.Value)) } case journal.OpDel: e := conn.Del(entry.Path, -1) if e != nil { err = fmt.Errorf("unable deleting '%s'", entry.Path) } default: err = fmt.Errorf("unknown operation %s", entry.Op) } if err != nil { errc <- err return } b, err := journal.Marshal(entry) if err != nil { continue } fmt.Println(string(b)) } } }
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 } } }