go.etcd.io/etcd@v3.3.27+incompatible/etcdserver/storage.go (about)

     1  // Copyright 2015 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package etcdserver
    16  
    17  import (
    18  	"io"
    19  
    20  	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
    21  	"github.com/coreos/etcd/pkg/pbutil"
    22  	"github.com/coreos/etcd/pkg/types"
    23  	"github.com/coreos/etcd/raft/raftpb"
    24  	"github.com/coreos/etcd/snap"
    25  	"github.com/coreos/etcd/wal"
    26  	"github.com/coreos/etcd/wal/walpb"
    27  )
    28  
    29  type Storage interface {
    30  	// Save function saves ents and state to the underlying stable storage.
    31  	// Save MUST block until st and ents are on stable storage.
    32  	Save(st raftpb.HardState, ents []raftpb.Entry) error
    33  	// SaveSnap function saves snapshot to the underlying stable storage.
    34  	SaveSnap(snap raftpb.Snapshot) error
    35  	// Close closes the Storage and performs finalization.
    36  	Close() error
    37  	// Release releases the locked wal files older than the provided snapshot.
    38  	Release(snap raftpb.Snapshot) error
    39  	// Sync WAL
    40  	Sync() error
    41  }
    42  
    43  type storage struct {
    44  	*wal.WAL
    45  	*snap.Snapshotter
    46  }
    47  
    48  func NewStorage(w *wal.WAL, s *snap.Snapshotter) Storage {
    49  	return &storage{w, s}
    50  }
    51  
    52  // SaveSnap saves the snapshot file to disk and writes the WAL snapshot entry.
    53  func (st *storage) SaveSnap(snap raftpb.Snapshot) error {
    54  	walsnap := walpb.Snapshot{
    55  		Index: snap.Metadata.Index,
    56  		Term:  snap.Metadata.Term,
    57  	}
    58  
    59  	// save the snapshot file before writing the snapshot to the wal.
    60  	// This makes it possible for the snapshot file to become orphaned, but prevents
    61  	// a WAL snapshot entry from having no corresponding snapshot file.
    62  	err := st.Snapshotter.SaveSnap(snap)
    63  	if err != nil {
    64  		return err
    65  	}
    66  
    67  	return st.WAL.SaveSnapshot(walsnap)
    68  }
    69  
    70  // Release releases resources older than the given snap and are no longer needed:
    71  // - releases the locks to the wal files that are older than the provided wal for the given snap.
    72  // - deletes any .snap.db files that are older than the given snap.
    73  func (st *storage) Release(snap raftpb.Snapshot) error {
    74  	if err := st.WAL.ReleaseLockTo(snap.Metadata.Index); err != nil {
    75  		return err
    76  	}
    77  	return st.Snapshotter.ReleaseSnapDBs(snap)
    78  }
    79  
    80  func readWAL(waldir string, snap walpb.Snapshot) (w *wal.WAL, id, cid types.ID, st raftpb.HardState, ents []raftpb.Entry) {
    81  	var (
    82  		err       error
    83  		wmetadata []byte
    84  	)
    85  
    86  	repaired := false
    87  	for {
    88  		if w, err = wal.Open(waldir, snap); err != nil {
    89  			plog.Fatalf("open wal error: %v", err)
    90  		}
    91  		if wmetadata, st, ents, err = w.ReadAll(); err != nil {
    92  			w.Close()
    93  			// we can only repair ErrUnexpectedEOF and we never repair twice.
    94  			if repaired || err != io.ErrUnexpectedEOF {
    95  				plog.Fatalf("read wal error (%v) and cannot be repaired", err)
    96  			}
    97  			if !wal.Repair(waldir) {
    98  				plog.Fatalf("WAL error (%v) cannot be repaired", err)
    99  			} else {
   100  				plog.Infof("repaired WAL error (%v)", err)
   101  				repaired = true
   102  			}
   103  			continue
   104  		}
   105  		break
   106  	}
   107  	var metadata pb.Metadata
   108  	pbutil.MustUnmarshal(&metadata, wmetadata)
   109  	id = types.ID(metadata.NodeID)
   110  	cid = types.ID(metadata.ClusterID)
   111  	return w, id, cid, st, ents
   112  }