1 module hunt.raft.Logunstable; 2 3 import hunt.raft.Msg; 4 5 import hunt.logging; 6 7 import std.experimental.allocator; 8 import std.format; 9 10 class unstable 11 { 12 Snapshot* _snap; 13 Entry[] _entries; 14 ulong _offset; 15 16 bool maybeFirstIndex(out ulong index) 17 { 18 if(_snap != null) 19 { 20 index = _snap.Metadata.Index + 1; 21 return true; 22 } 23 index = 0; 24 return false; 25 } 26 27 bool maybeLastIndex(out ulong index) 28 { 29 if(_entries.length != 0) 30 { 31 index = _offset + _entries.length - 1; 32 return true; 33 } 34 35 if(_snap != null) 36 { 37 index = _snap.Metadata.Index; 38 return true; 39 } 40 41 index = 0; 42 return false; 43 } 44 45 46 bool maybeTerm(ulong i , out ulong term) 47 { 48 if( i < _offset) 49 { 50 if(_snap == null) 51 { 52 term = 0; 53 return false; 54 } 55 56 if(_snap.Metadata.Index == i) 57 { 58 term = _snap.Metadata.Term; 59 return true; 60 } 61 62 term = 0; 63 return false; 64 } 65 66 ulong last = 0; 67 if(!maybeLastIndex(last)) 68 { 69 term = 0; 70 return false; 71 } 72 73 if(i > last) 74 { 75 term = 0; 76 return false; 77 } 78 79 term = _entries[cast(uint)(i - _offset)].Term; 80 return true; 81 } 82 83 void stableTo(ulong i , ulong t) 84 { 85 ulong gt = 0; 86 if(!maybeTerm(i , gt)) 87 return; 88 89 if( gt == t && i >= _offset) 90 { 91 _entries = _entries[ cast(uint)(i + 1 - _offset) .. $ ]; 92 _offset = i + 1; 93 shrinkEntriesArray(); 94 } 95 } 96 97 void shrinkEntriesArray() 98 { 99 if(_entries.length == 0) 100 { 101 return; 102 } 103 else if( _entries.capacity > _entries.length) 104 { 105 _entries = _entries.dup; 106 } 107 } 108 109 110 void stableSnapTo(ulong i) { 111 if (_snap != null && _snap.Metadata.Index == i) { 112 _snap = null; 113 } 114 } 115 116 void restore(Snapshot s) 117 { 118 _offset = s.Metadata.Index + 1; 119 _entries.length = 0; 120 _snap = theAllocator.make!Snapshot(s); 121 } 122 123 void truncateAndAppend(Entry[] ents) 124 { 125 auto after = ents[0].Index; 126 if(after == _offset + _entries.length) 127 { 128 _entries ~= ents; 129 } 130 else if(after <= _offset) 131 { 132 logInfo("replace the unstable entries from index " , after); 133 _entries = ents; 134 _offset = after; 135 } 136 else{ 137 logInfo("truncate the unstable entries before index " , after); 138 _entries = slice(_offset , after); 139 _entries ~= ents; 140 } 141 } 142 143 144 Entry[] slice(ulong lo , ulong hi) 145 { 146 mustCheckOutOfBounds(lo , hi); 147 return _entries[cast(uint)(lo - _offset) .. cast(uint)(hi - _offset)]; 148 } 149 150 void mustCheckOutOfBounds(ulong lo , ulong hi) 151 { 152 if( lo > hi) 153 { 154 logError(format("invalid unstable.slice %d > %d", lo, hi)); 155 } 156 157 auto upper = _offset + _entries.length; 158 if( lo < _offset || hi > upper) 159 { 160 logError(format("unstable.slice[%d,%d) out of bound [%d,%d]", lo, hi, 161 _offset, upper)); 162 } 163 } 164 }