github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/core/blockstm/status.go (about) 1 package blockstm 2 3 import ( 4 "fmt" 5 "sort" 6 ) 7 8 func makeStatusManager(numTasks int) (t taskStatusManager) { 9 t.pending = make([]int, numTasks) 10 for i := 0; i < numTasks; i++ { 11 t.pending[i] = i 12 } 13 14 t.dependency = make(map[int]map[int]bool, numTasks) 15 t.blocker = make(map[int]map[int]bool, numTasks) 16 17 for i := 0; i < numTasks; i++ { 18 t.blocker[i] = make(map[int]bool) 19 } 20 21 return 22 } 23 24 type taskStatusManager struct { 25 pending []int 26 inProgress []int 27 complete []int 28 dependency map[int]map[int]bool 29 blocker map[int]map[int]bool 30 } 31 32 func insertInList(l []int, v int) []int { 33 if len(l) == 0 || v > l[len(l)-1] { 34 return append(l, v) 35 } else { 36 x := sort.SearchInts(l, v) 37 if x < len(l) && l[x] == v { 38 // already in list 39 return l 40 } 41 a := append(l[:x+1], l[x:]...) 42 a[x] = v 43 return a 44 } 45 } 46 47 func (m *taskStatusManager) takeNextPending() int { 48 if len(m.pending) == 0 { 49 return -1 50 } 51 52 x := m.pending[0] 53 m.pending = m.pending[1:] 54 m.inProgress = insertInList(m.inProgress, x) 55 56 return x 57 } 58 59 func hasNoGap(l []int) bool { 60 return l[0]+len(l) == l[len(l)-1]+1 61 } 62 63 func (m taskStatusManager) maxAllComplete() int { 64 if len(m.complete) == 0 || m.complete[0] != 0 { 65 return -1 66 } else if m.complete[len(m.complete)-1] == len(m.complete)-1 { 67 return m.complete[len(m.complete)-1] 68 } else { 69 for i := len(m.complete) - 2; i >= 0; i-- { 70 if hasNoGap(m.complete[:i+1]) { 71 return m.complete[i] 72 } 73 } 74 } 75 76 return -1 77 } 78 79 func (m *taskStatusManager) pushPending(tx int) { 80 m.pending = insertInList(m.pending, tx) 81 } 82 83 func removeFromList(l []int, v int, expect bool) []int { 84 x := sort.SearchInts(l, v) 85 if x == -1 || l[x] != v { 86 if expect { 87 panic(fmt.Errorf("should not happen - element expected in list")) 88 } 89 90 return l 91 } 92 93 switch x { 94 case 0: 95 return l[1:] 96 case len(l) - 1: 97 return l[:len(l)-1] 98 default: 99 return append(l[:x], l[x+1:]...) 100 } 101 } 102 103 func (m *taskStatusManager) markComplete(tx int) { 104 m.inProgress = removeFromList(m.inProgress, tx, true) 105 m.complete = insertInList(m.complete, tx) 106 } 107 108 func (m *taskStatusManager) minPending() int { 109 if len(m.pending) == 0 { 110 return -1 111 } else { 112 return m.pending[0] 113 } 114 } 115 116 func (m *taskStatusManager) countComplete() int { 117 return len(m.complete) 118 } 119 120 func (m *taskStatusManager) addDependencies(blocker int, dependent int) bool { 121 if blocker < 0 || blocker >= dependent { 122 return false 123 } 124 125 curblockers := m.blocker[dependent] 126 127 if m.checkComplete(blocker) { 128 // Blocker has already completed 129 delete(curblockers, blocker) 130 131 return len(curblockers) > 0 132 } 133 134 if _, ok := m.dependency[blocker]; !ok { 135 m.dependency[blocker] = make(map[int]bool) 136 } 137 138 m.dependency[blocker][dependent] = true 139 curblockers[blocker] = true 140 141 return true 142 } 143 144 func (m *taskStatusManager) isBlocked(tx int) bool { 145 return len(m.blocker[tx]) > 0 146 } 147 148 func (m *taskStatusManager) removeDependency(tx int) { 149 if deps, ok := m.dependency[tx]; ok && len(deps) > 0 { 150 for k := range deps { 151 delete(m.blocker[k], tx) 152 153 if len(m.blocker[k]) == 0 { 154 if !m.checkComplete(k) && !m.checkPending(k) && !m.checkInProgress(k) { 155 m.pushPending(k) 156 } 157 } 158 } 159 160 delete(m.dependency, tx) 161 } 162 } 163 164 func (m *taskStatusManager) clearInProgress(tx int) { 165 m.inProgress = removeFromList(m.inProgress, tx, true) 166 } 167 168 func (m *taskStatusManager) checkInProgress(tx int) bool { 169 x := sort.SearchInts(m.inProgress, tx) 170 if x < len(m.inProgress) && m.inProgress[x] == tx { 171 return true 172 } 173 174 return false 175 } 176 177 func (m *taskStatusManager) checkPending(tx int) bool { 178 x := sort.SearchInts(m.pending, tx) 179 if x < len(m.pending) && m.pending[x] == tx { 180 return true 181 } 182 183 return false 184 } 185 186 func (m *taskStatusManager) checkComplete(tx int) bool { 187 x := sort.SearchInts(m.complete, tx) 188 if x < len(m.complete) && m.complete[x] == tx { 189 return true 190 } 191 192 return false 193 } 194 195 // getRevalidationRange: this range will be all tasks from tx (inclusive) that are not currently in progress up to the 196 // 197 // 'all complete' limit 198 func (m *taskStatusManager) getRevalidationRange(txFrom int) (ret []int) { 199 max := m.maxAllComplete() // haven't learned to trust compilers :) 200 for x := txFrom; x <= max; x++ { 201 if !m.checkInProgress(x) { 202 ret = append(ret, x) 203 } 204 } 205 206 return 207 } 208 209 func (m *taskStatusManager) pushPendingSet(set []int) { 210 for _, v := range set { 211 if m.checkComplete(v) { 212 m.clearComplete(v) 213 } 214 215 m.pushPending(v) 216 } 217 } 218 219 func (m *taskStatusManager) clearComplete(tx int) { 220 m.complete = removeFromList(m.complete, tx, false) 221 } 222 223 func (m *taskStatusManager) clearPending(tx int) { 224 m.pending = removeFromList(m.pending, tx, false) 225 }