func (s *v3Manager) saveDB() error {
	f, ferr := os.OpenFile(s.dbPath, os.O_RDONLY, 0600)
	if ferr != nil {
		return ferr
	}
	defer f.Close()

	// get snapshot integrity hash
	if _, err := f.Seek(-sha256.Size, io.SeekEnd); err != nil {
		return err
	}
	sha := make([]byte, sha256.Size)
	if _, err := f.Read(sha); err != nil {
		return err
	}
	if _, err := f.Seek(0, io.SeekStart); err != nil {
		return err
	}

	if err := fileutil.CreateDirAll(s.snapDir); err != nil {
		return err
	}

	dbpath := filepath.Join(s.snapDir, "db")
	db, dberr := os.OpenFile(dbpath, os.O_RDWR|os.O_CREATE, 0600)
	if dberr != nil {
		return dberr
	}
	if _, err := io.Copy(db, f); err != nil {
		return err
	}

	// truncate away integrity hash, if any.
	off, serr := db.Seek(0, io.SeekEnd)
	if serr != nil {
		return serr
	}
	hasHash := (off % 512) == sha256.Size
	if hasHash {
		if err := db.Truncate(off - sha256.Size); err != nil {
			return err
		}
	}

	if !hasHash && !s.skipHashCheck {
		return fmt.Errorf("snapshot missing hash but --skip-hash-check=false")
	}

	if hasHash && !s.skipHashCheck {
		// check for match
		if _, err := db.Seek(0, io.SeekStart); err != nil {
			return err
		}
		h := sha256.New()
		if _, err := io.Copy(h, db); err != nil {
			return err
		}
		dbsha := h.Sum(nil)
		if !reflect.DeepEqual(sha, dbsha) {
			return fmt.Errorf("expected sha256 %v, got %v", sha, dbsha)
		}
	}

	// db hash is OK, can now modify DB so it can be part of a new cluster
	db.Close()

	commit := len(s.cl.Members())

	// update consistentIndex so applies go through on etcdserver despite
	// having a new raft instance
	be := backend.NewDefaultBackend(dbpath)

	// a lessor never timeouts leases
	lessor := lease.NewLessor(s.lg, be, lease.LessorConfig{MinLeaseTTL: math.MaxInt64})

	mvs := mvcc.NewStore(s.lg, be, lessor, (*initIndex)(&commit))
	txn := mvs.Write()
	btx := be.BatchTx()
	del := func(k, v []byte) error {
		txn.DeleteRange(k, nil)
		return nil
	}

	// delete stored members from old cluster since using new members
	btx.UnsafeForEach([]byte("members"), del)

	// todo: add back new members when we start to deprecate old snap file.
	btx.UnsafeForEach([]byte("members_removed"), del)

	// trigger write-out of new consistent index
	txn.End()

	mvs.Commit()
	mvs.Close()
	be.Close()

	return nil
}
func (s *v3Manager) saveDB() error {
	f, ferr := os.OpenFile(s.dbPath, os.O_RDONLY, 0600)
	if ferr != nil {
		return ferr
	}
	defer f.Close()

	
	if _, err := f.Seek(-sha256.Size, io.SeekEnd); err != nil {
		return err
	}
	sha := make([]byte, sha256.Size)
	if _, err := f.Read(sha); err != nil {
		return err
	}
	if _, err := f.Seek(0, io.SeekStart); err != nil {
		return err
	}

	if err := fileutil.CreateDirAll(s.snapDir); err != nil {
		return err
	}

	dbpath := filepath.Join(s.snapDir, "db")
	db, dberr := os.OpenFile(dbpath, os.O_RDWR|os.O_CREATE, 0600)
	if dberr != nil {
		return dberr
	}
	if _, err := io.Copy(db, f); err != nil {
		return err
	}

	
	off, serr := db.Seek(0, io.SeekEnd)
	if serr != nil {
		return serr
	}
	hasHash := (off % 512) == sha256.Size
	if hasHash {
		if err := db.Truncate(off - sha256.Size); err != nil {
			return err
		}
	}

	if !hasHash && !s.skipHashCheck {
		return fmt.Errorf("snapshot missing hash but --skip-hash-check=false")
	}

	if hasHash && !s.skipHashCheck {
		
		if _, err := db.Seek(0, io.SeekStart); err != nil {
			return err
		}
		h := sha256.New()
		if _, err := io.Copy(h, db); err != nil {
			return err
		}
		dbsha := h.Sum(nil)
		if !reflect.DeepEqual(sha, dbsha) {
			return fmt.Errorf("expected sha256 %v, got %v", sha, dbsha)
		}
	}

	
	db.Close()

	commit := len(s.cl.Members())

	
	
	be := backend.NewDefaultBackend(dbpath)

	
	lessor := lease.NewLessor(s.lg, be, lease.LessorConfig{MinLeaseTTL: math.MaxInt64})

	mvs := mvcc.NewStore(s.lg, be, lessor, (*initIndex)(&commit))
	txn := mvs.Write()
	btx := be.BatchTx()
	del := func(k, v []byte) error {
		txn.DeleteRange(k, nil)
		return nil
	}

	
	btx.UnsafeForEach([]byte("members"), del)

	
	btx.UnsafeForEach([]byte("members_removed"), del)

	
	txn.End()

	mvs.Commit()
	mvs.Close()
	be.Close()

	return nil
}
func ( s * v3Manager ) saveDB ( ) error { f , ferr := os . OpenFile ( s . dbPath , os . O_RDONLY , 0600 ) if ferr != nil { return ferr } defer f . Close ( ) // get snapshot integrity hash if _ , err := f . Seek ( - sha256 . Size , io . SeekEnd ) ; err != nil { return err } sha := make ( [ ] byte , sha256 . Size ) if _ , err := f . Read ( sha ) ; err != nil { return err } if _ , err := f . Seek ( 0 , io . SeekStart ) ; err != nil { return err } if err := fileutil . CreateDirAll ( s . snapDir ) ; err != nil { return err } dbpath := filepath . Join ( s . snapDir , " " ) db , dberr := os . OpenFile ( dbpath , os . O_RDWR | os . O_CREATE , 0600 ) if dberr != nil { return dberr } if _ , err := io . Copy ( db , f ) ; err != nil { return err } // truncate away integrity hash, if any. off , serr := db . Seek ( 0 , io . SeekEnd ) if serr != nil { return serr } hasHash := ( off % 512 ) == sha256 . Size if hasHash { if err := db . Truncate ( off - sha256 . Size ) ; err != nil { return err } } if ! hasHash && ! s . skipHashCheck { return fmt . Errorf ( " " ) } if hasHash && ! s . skipHashCheck { // check for match if _ , err := db . Seek ( 0 , io . SeekStart ) ; err != nil { return err } h := sha256 . New ( ) if _ , err := io . Copy ( h , db ) ; err != nil { return err } dbsha := h . Sum ( nil ) if ! reflect . DeepEqual ( sha , dbsha ) { return fmt . Errorf ( " " , sha , dbsha ) } } // db hash is OK, can now modify DB so it can be part of a new cluster db . Close ( ) commit := len ( s . cl . Members ( ) ) // update consistentIndex so applies go through on etcdserver despite // having a new raft instance be := backend . NewDefaultBackend ( dbpath ) // a lessor never timeouts leases lessor := lease . NewLessor ( s . lg , be , lease . LessorConfig { MinLeaseTTL : math . MaxInt64 } ) mvs := mvcc . NewStore ( s . lg , be , lessor , ( * initIndex ) ( & commit ) ) txn := mvs . Write ( ) btx := be . BatchTx ( ) del := func ( k , v [ ] byte ) error { txn . DeleteRange ( k , nil ) return nil } // delete stored members from old cluster since using new members btx . UnsafeForEach ( [ ] byte ( " " ) , del ) // todo: add back new members when we start to deprecate old snap file. btx . UnsafeForEach ( [ ] byte ( " " ) , del ) // trigger write-out of new consistent index txn . End ( ) mvs . Commit ( ) mvs . Close ( ) be . Close ( ) return nil }
// saveDB copies the database snapshot to the snapshot directory
saveDB copies the database snapshot to the snapshot directory