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))
		}
	}
}
Exemple #2
0
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
		}
	}
}