github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/others/qdb/index.go (about)

     1  package qdb
     2  
     3  import (
     4  	"os"
     5  	"io/ioutil"
     6  )
     7  
     8  
     9  type QdbIndex struct {
    10  	db *DB
    11  	IdxFilePath string
    12  	file *os.File
    13  	DatfileIndex int
    14  	VersionSequence uint32
    15  	MaxDatfileSequence uint32
    16  
    17  	Index map[KeyType] *oneIdx
    18  
    19  	DiskSpaceNeeded uint64
    20  	ExtraSpaceUsed uint64
    21  }
    22  
    23  func NewDBidx(db *DB, recs uint) (idx *QdbIndex) {
    24  	idx = new(QdbIndex)
    25  	idx.db = db
    26  	idx.IdxFilePath = db.Dir+"qdbidx."
    27  	if recs==0 {
    28  		idx.Index = make(map[KeyType] *oneIdx)
    29  	} else {
    30  		idx.Index = make(map[KeyType] *oneIdx, recs)
    31  	}
    32  	used := make(map[uint32]bool, 10)
    33  	idx.loaddat(used)
    34  	idx.loadlog(used)
    35  	idx.db.cleanupold(used)
    36  	return
    37  }
    38  
    39  
    40  func (idx *QdbIndex) load(walk QdbWalkFunction) {
    41  	dats := make(map[uint32] []byte)
    42  	idx.browse(func(k KeyType, v *oneIdx) bool {
    43  		if walk!=nil || (v.flags&NO_CACHE)==0 {
    44  			dat := dats[v.DataSeq]
    45  			if dat == nil {
    46  				dat, _ = ioutil.ReadFile(idx.db.seq2fn(v.DataSeq))
    47  				if dat==nil {
    48  					println("Database corrupt - missing file:", idx.db.seq2fn(v.DataSeq))
    49  					os.Exit(1)
    50  				}
    51  				dats[v.DataSeq] = dat
    52  			}
    53  			v.SetData(dat[v.datpos:v.datpos+v.datlen])
    54  			if walk!=nil {
    55  				res := walk(k, v.Slice())
    56  				v.aply_browsing_flags(res)
    57  				v.freerec()
    58  			}
    59  		}
    60  		return true
    61  	})
    62  }
    63  
    64  
    65  func (idx *QdbIndex) size() int {
    66  	return len(idx.Index)
    67  }
    68  
    69  
    70  func (idx *QdbIndex) get(k KeyType) *oneIdx {
    71  	return idx.Index[k]
    72  }
    73  
    74  
    75  func (idx *QdbIndex) memput(k KeyType, rec *oneIdx) {
    76  	if prv, ok := idx.Index[k]; ok {
    77  		prv.FreeData()
    78  		dif := uint64(24+prv.datlen)
    79  		if !idx.db.VolatileMode {
    80  			idx.ExtraSpaceUsed += dif
    81  			idx.DiskSpaceNeeded -= dif
    82  		}
    83  	}
    84  	idx.Index[k] = rec
    85  
    86  	if !idx.db.VolatileMode {
    87  		idx.DiskSpaceNeeded += uint64(24+rec.datlen)
    88  	}
    89  	if rec.DataSeq>idx.MaxDatfileSequence {
    90  		idx.MaxDatfileSequence = rec.DataSeq
    91  	}
    92  }
    93  
    94  
    95  func (idx *QdbIndex) memdel(k KeyType) {
    96  	if cur, ok := idx.Index[k]; ok {
    97  		cur.FreeData()
    98  		dif := uint64(12+cur.datlen)
    99  		if !idx.db.VolatileMode {
   100  			idx.ExtraSpaceUsed += dif
   101  			idx.DiskSpaceNeeded -= dif
   102  		}
   103  		delete(idx.Index, k)
   104  	}
   105  }
   106  
   107  func (idx *QdbIndex) put(k KeyType, rec *oneIdx) {
   108  	idx.memput(k, rec)
   109  	if idx.db.VolatileMode {
   110  		return
   111  	}
   112  	idx.addtolog(nil, k, rec)
   113  }
   114  
   115  
   116  func (idx *QdbIndex) del(k KeyType) {
   117  	idx.memdel(k)
   118  	if idx.db.VolatileMode {
   119  		return
   120  	}
   121  	idx.deltolog(nil, k)
   122  }
   123  
   124  
   125  func (idx *QdbIndex) browse(walk func(key KeyType, idx *oneIdx) bool) {
   126  	for k, v := range idx.Index {
   127  		if !walk(k, v) {
   128  			break
   129  		}
   130  	}
   131  }
   132  
   133  func (idx *QdbIndex) close() {
   134  	if idx.file!= nil {
   135  		idx.file.Close()
   136  		idx.file = nil
   137  	}
   138  	idx.Index = nil
   139  }