1 module neton.snap.SnapShotter; 2 3 import std.stdio; 4 import std.file; 5 import std.path; 6 import std.array; 7 import std.format; 8 9 // import protocol.Msg; 10 import hunt.util.Serialize; 11 import hunt.logging; 12 import std.algorithm.sorting; 13 14 // import raft.Node; 15 import hunt.raft; 16 17 const string snapSuffix = ".snap"; 18 19 const string ErrNoSnapshot = "snap: no available snapshot"; 20 const string ErrEmptySnapshot = "snap: empty snapshot"; 21 const string ErrCRCMismatch = "snap: crc mismatch"; 22 23 // struct SnapData { 24 // string data; 25 // } 26 27 class Snapshotter 28 { 29 string _dir; 30 31 struct snapName 32 { 33 int term; 34 int index; 35 } 36 37 this(string dir) 38 { 39 _dir = dir; 40 } 41 42 void SaveSnap(Snapshot snapshot) 43 { 44 if (IsEmptySnap(snapshot)) 45 return; 46 auto writer = appender!string(); 47 formattedWrite(writer, "%s/%s-%s%s", _dir, snapshot.Metadata.Term, 48 snapshot.Metadata.Index, snapSuffix); 49 logInfo("savesnap file name : ", writer.data); 50 auto b = serialize(snapshot); 51 auto file = File(writer.data, "wb"); 52 file.rawWrite(b); 53 file.close(); 54 55 auto snaps = snapNames(); 56 foreach (snap; snaps) 57 { 58 auto filepath = _dir ~ "/" ~ snap; 59 if (filepath != writer.data) 60 { 61 remove(filepath); 62 } 63 } 64 } 65 66 Snapshot loadSnap() 67 { 68 Snapshot snapshot; 69 string lastName = getLastSnapName(); 70 if (lastName is null) 71 { 72 logInfo("-------- no snap shot info "); 73 return snapshot; 74 } 75 auto file = File(lastName, "rb"); 76 byte[] content; 77 byte[] data = new byte[1024]; 78 while (!file.eof()) 79 { 80 content ~= file.rawRead(data); 81 } 82 file.close(); 83 snapshot = unserialize!Snapshot(content); 84 return snapshot; 85 } 86 87 string[] snapNames() 88 { 89 string[] names; 90 91 foreach (string name; dirEntries(_dir, SpanMode.shallow)) 92 { 93 names ~= std.path.baseName(name); 94 } 95 return names; 96 } 97 98 string getLastSnapName() 99 { 100 string[] names = snapNames(); 101 if (names.length == 0) 102 return string.init; 103 snapName[] snap; 104 foreach (string name; names) 105 { 106 int term, index; 107 formattedRead(name, "%s-%s.snap", &term, &index); 108 109 snap ~= snapName(term, index); 110 } 111 112 multiSort!("a.term > b.term", "a.index > b.index")(snap); 113 logInfo("last snap shot ,term : ", snap[0].term, " index : ", snap[0].index); 114 auto lastName = appender!string(); 115 formattedWrite(lastName, "%s/%s-%s%s", _dir, snap[0].term, snap[0].index, snapSuffix); 116 return lastName.data; 117 } 118 }