예제 #1
0
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
}
예제 #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
		}
	}
}