示例#1
0
// Restore takes the snapshot from the reader and attempts to apply it to the
// given Raft instance.
func Restore(logger *log.Logger, in io.Reader, r *raft.Raft) error {
	// Wrap the reader in a gzip decompressor.
	decomp, err := gzip.NewReader(in)
	if err != nil {
		return fmt.Errorf("failed to decompress snapshot: %v", err)
	}
	defer func() {
		if err := decomp.Close(); err != nil {
			logger.Printf("[ERR] snapshot: Failed to close snapshot decompressor: %v", err)
		}
	}()

	// Make a scratch file to receive the contents of the snapshot data so
	// we can avoid buffering in memory.
	snap, err := ioutil.TempFile("", "snapshot")
	if err != nil {
		return fmt.Errorf("failed to create temp snapshot file: %v", err)
	}
	defer func() {
		if err := snap.Close(); err != nil {
			logger.Printf("[ERR] snapshot: Failed to close temp snapshot: %v", err)
		}
		if err := os.Remove(snap.Name()); err != nil {
			logger.Printf("[ERR] snapshot: Failed to clean up temp snapshot: %v", err)
		}
	}()

	// Read the archive.
	var metadata raft.SnapshotMeta
	if err := read(decomp, &metadata, snap); err != nil {
		return fmt.Errorf("failed to read snapshot file: %v", err)
	}

	// Sync and rewind the file so it's ready to be read again.
	if err := snap.Sync(); err != nil {
		return fmt.Errorf("failed to sync temp snapshot: %v", err)
	}
	if _, err := snap.Seek(0, 0); err != nil {
		return fmt.Errorf("failed to rewind temp snapshot: %v", err)
	}

	// Feed the snapshot into Raft.
	if err := r.Restore(&metadata, snap, 60*time.Second); err != nil {
		return fmt.Errorf("Raft error when restoring snapshot: %v", err)
	}

	return nil
}