github.com/cilium/statedb@v0.3.2/deletetracker.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package statedb 5 6 import ( 7 "sync/atomic" 8 9 "github.com/cilium/statedb/index" 10 ) 11 12 type deleteTracker[Obj any] struct { 13 db *DB 14 trackerName string 15 table Table[Obj] 16 17 // revision is the last observed revision. Starts out at zero 18 // in which case the garbage collector will not care about this 19 // tracker when considering which objects to delete. 20 revision atomic.Uint64 21 } 22 23 // setRevision is called to set the starting low watermark when 24 // this deletion tracker is inserted into the table. 25 func (dt *deleteTracker[Obj]) setRevision(rev uint64) { 26 dt.revision.Store(rev) 27 } 28 29 // getRevision is called by the graveyard garbage collector to 30 // compute the global low watermark. 31 func (dt *deleteTracker[Obj]) getRevision() uint64 { 32 return dt.revision.Load() 33 } 34 35 // Deleted returns an iterator for deleted objects in this table starting from 36 // 'minRevision'. The deleted objects are not garbage-collected unless 'Mark' is 37 // called! 38 func (dt *deleteTracker[Obj]) deleted(txn *txn, minRevision Revision) Iterator[Obj] { 39 indexEntry := txn.root[dt.table.tablePos()].indexes[GraveyardRevisionIndexPos] 40 indexTxn := indexReadTxn{indexEntry.tree, indexEntry.unique} 41 iter := indexTxn.LowerBound(index.Uint64(minRevision)) 42 return &iterator[Obj]{iter} 43 } 44 45 // Mark the revision up to which deleted objects have been processed. This sets 46 // the low watermark for deleted object garbage collection. 47 func (dt *deleteTracker[Obj]) mark(upTo Revision) { 48 // Store the new low watermark and trigger a round of garbage collection. 49 dt.revision.Store(upTo) 50 select { 51 case dt.db.gcTrigger <- struct{}{}: 52 default: 53 } 54 } 55 56 func (dt *deleteTracker[Obj]) close() { 57 if dt.db == nil { 58 return 59 } 60 61 // Remove the delete tracker from the table. 62 txn := dt.db.WriteTxn(dt.table).getTxn() 63 dt.db = nil 64 db := txn.db 65 table := txn.modifiedTables[dt.table.tablePos()] 66 if table == nil { 67 panic("BUG: Table missing from write transaction") 68 } 69 _, _, table.deleteTrackers = table.deleteTrackers.Delete([]byte(dt.trackerName)) 70 txn.Commit() 71 72 db.metrics.DeleteTrackerCount(dt.table.Name(), table.deleteTrackers.Len()) 73 74 // Trigger garbage collection without this delete tracker to garbage 75 // collect any deleted objects that may not have been consumed. 76 select { 77 case db.gcTrigger <- struct{}{}: 78 default: 79 } 80 81 } 82 83 var closedWatchChannel = func() <-chan struct{} { 84 ch := make(chan struct{}) 85 close(ch) 86 return ch 87 }()