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  }