@@ -109,7 +109,7 @@ type DB struct {
109
109
lc * levelsController
110
110
vlog valueLog
111
111
writeCh chan * request
112
- flushChan chan flushTask // For flushing memtables.
112
+ flushChan chan * memTable // For flushing memtables.
113
113
closeOnce sync.Once // For closing DB only once.
114
114
115
115
blockWrites atomic.Int32
@@ -240,7 +240,7 @@ func Open(opt Options) (*DB, error) {
240
240
241
241
db := & DB {
242
242
imm : make ([]* memTable , 0 , opt .NumMemtables ),
243
- flushChan : make (chan flushTask , opt .NumMemtables ),
243
+ flushChan : make (chan * memTable , opt .NumMemtables ),
244
244
writeCh : make (chan * request , kvWriteChCapacity ),
245
245
opt : opt ,
246
246
manifest : manifestFile ,
@@ -351,11 +351,11 @@ func Open(opt Options) (*DB, error) {
351
351
352
352
db .closers .memtable = z .NewCloser (1 )
353
353
go func () {
354
- _ = db .flushMemtable (db .closers .memtable ) // Need levels controller to be up.
354
+ db .flushMemtable (db .closers .memtable ) // Need levels controller to be up.
355
355
}()
356
356
// Flush them to disk asap.
357
357
for _ , mt := range db .imm {
358
- db .flushChan <- flushTask { mt : mt }
358
+ db .flushChan <- mt
359
359
}
360
360
}
361
361
// We do increment nextTxnTs below. So, no need to do it here.
@@ -568,12 +568,12 @@ func (db *DB) close() (err error) {
568
568
} else {
569
569
db .opt .Debugf ("Flushing memtable" )
570
570
for {
571
- pushedFlushTask := func () bool {
571
+ pushedMemTable := func () bool {
572
572
db .lock .Lock ()
573
573
defer db .lock .Unlock ()
574
574
y .AssertTrue (db .mt != nil )
575
575
select {
576
- case db .flushChan <- flushTask { mt : db .mt } :
576
+ case db .flushChan <- db .mt :
577
577
db .imm = append (db .imm , db .mt ) // Flusher will attempt to remove this from s.imm.
578
578
db .mt = nil // Will segfault if we try writing!
579
579
db .opt .Debugf ("pushed to flush chan\n " )
@@ -586,7 +586,7 @@ func (db *DB) close() (err error) {
586
586
}
587
587
return false
588
588
}()
589
- if pushedFlushTask {
589
+ if pushedMemTable {
590
590
break
591
591
}
592
592
time .Sleep (10 * time .Millisecond )
@@ -826,6 +826,7 @@ func (db *DB) writeRequests(reqs []*request) error {
826
826
}
827
827
count += len (b .Entries )
828
828
var i uint64
829
+ var err error
829
830
for err = db .ensureRoomForWrite (); err == errNoRoom ; err = db .ensureRoomForWrite () {
830
831
i ++
831
832
if i % 100 == 0 {
@@ -987,7 +988,7 @@ func (db *DB) ensureRoomForWrite() error {
987
988
}
988
989
989
990
select {
990
- case db .flushChan <- flushTask { mt : db .mt } :
991
+ case db .flushChan <- db .mt :
991
992
db .opt .Debugf ("Flushing memtable, mt.size=%d size of flushChan: %d\n " ,
992
993
db .mt .sl .MemSize (), len (db .flushChan ))
993
994
// We manage to push this task. Let's modify imm.
@@ -1009,12 +1010,12 @@ func arenaSize(opt Options) int64 {
1009
1010
}
1010
1011
1011
1012
// buildL0Table builds a new table from the memtable.
1012
- func buildL0Table (ft flushTask , bopts table.Options ) * table.Builder {
1013
- iter := ft .mt .sl .NewIterator ()
1013
+ func buildL0Table (iter y.Iterator , dropPrefixes [][]byte , bopts table.Options ) * table.Builder {
1014
1014
defer iter .Close ()
1015
+
1015
1016
b := table .NewTableBuilder (bopts )
1016
- for iter .SeekToFirst (); iter .Valid (); iter .Next () {
1017
- if len (ft . dropPrefixes ) > 0 && hasAnyPrefixes (iter .Key (), ft . dropPrefixes ) {
1017
+ for iter .Rewind (); iter .Valid (); iter .Next () {
1018
+ if len (dropPrefixes ) > 0 && hasAnyPrefixes (iter .Key (), dropPrefixes ) {
1018
1019
continue
1019
1020
}
1020
1021
vs := iter .Value ()
@@ -1024,23 +1025,15 @@ func buildL0Table(ft flushTask, bopts table.Options) *table.Builder {
1024
1025
}
1025
1026
b .Add (iter .Key (), iter .Value (), vp .Len )
1026
1027
}
1027
- return b
1028
- }
1029
1028
1030
- type flushTask struct {
1031
- mt * memTable
1032
- dropPrefixes [][]byte
1029
+ return b
1033
1030
}
1034
1031
1035
- // handleFlushTask must be run serially.
1036
- func (db * DB ) handleFlushTask (ft flushTask ) error {
1037
- // There can be a scenario, when empty memtable is flushed.
1038
- if ft .mt .sl .Empty () {
1039
- return nil
1040
- }
1041
-
1032
+ // handleMemTableFlush must be run serially.
1033
+ func (db * DB ) handleMemTableFlush (mt * memTable , dropPrefixes [][]byte ) error {
1042
1034
bopts := buildTableOptions (db )
1043
- builder := buildL0Table (ft , bopts )
1035
+ itr := mt .sl .NewUniIterator (false )
1036
+ builder := buildL0Table (itr , nil , bopts )
1044
1037
defer builder .Close ()
1045
1038
1046
1039
// buildL0Table can return nil if the none of the items in the skiplist are
@@ -1069,39 +1062,39 @@ func (db *DB) handleFlushTask(ft flushTask) error {
1069
1062
return err
1070
1063
}
1071
1064
1072
- // flushMemtable must keep running until we send it an empty flushTask . If there
1073
- // are errors during handling the flush task , we'll retry indefinitely.
1074
- func (db * DB ) flushMemtable (lc * z.Closer ) error {
1065
+ // flushMemtable must keep running until we send it an empty memtable . If there
1066
+ // are errors during handling the memtable flush , we'll retry indefinitely.
1067
+ func (db * DB ) flushMemtable (lc * z.Closer ) {
1075
1068
defer lc .Done ()
1076
1069
1077
- for ft := range db .flushChan {
1078
- if ft .mt == nil {
1079
- // We close db.flushChan now, instead of sending a nil ft.mt.
1070
+ for mt := range db .flushChan {
1071
+ if mt == nil {
1080
1072
continue
1081
1073
}
1082
- for {
1083
- err := db .handleFlushTask (ft )
1084
- if err == nil {
1085
- // Update s.imm. Need a lock.
1086
- db .lock .Lock ()
1087
- // This is a single-threaded operation. ft.mt corresponds to the head of
1088
- // db.imm list. Once we flush it, we advance db.imm. The next ft.mt
1089
- // which would arrive here would match db.imm[0], because we acquire a
1090
- // lock over DB when pushing to flushChan.
1091
- // TODO: This logic is dirty AF. Any change and this could easily break.
1092
- y .AssertTrue (ft .mt == db .imm [0 ])
1093
- db .imm = db .imm [1 :]
1094
- ft .mt .DecrRef () // Return memory.
1095
- db .lock .Unlock ()
1096
1074
1097
- break
1075
+ for {
1076
+ if err := db .handleMemTableFlush (mt , nil ); err != nil {
1077
+ // Encountered error. Retry indefinitely.
1078
+ db .opt .Errorf ("error flushing memtable to disk: %v, retrying" , err )
1079
+ time .Sleep (time .Second )
1080
+ continue
1098
1081
}
1099
- // Encountered error. Retry indefinitely.
1100
- db .opt .Errorf ("Failure while flushing memtable to disk: %v. Retrying...\n " , err )
1101
- time .Sleep (time .Second )
1082
+
1083
+ // Update s.imm. Need a lock.
1084
+ db .lock .Lock ()
1085
+ // This is a single-threaded operation. mt corresponds to the head of
1086
+ // db.imm list. Once we flush it, we advance db.imm. The next mt
1087
+ // which would arrive here would match db.imm[0], because we acquire a
1088
+ // lock over DB when pushing to flushChan.
1089
+ // TODO: This logic is dirty AF. Any change and this could easily break.
1090
+ y .AssertTrue (mt == db .imm [0 ])
1091
+ db .imm = db .imm [1 :]
1092
+ mt .DecrRef () // Return memory.
1093
+ // unlock
1094
+ db .lock .Unlock ()
1095
+ break
1102
1096
}
1103
1097
}
1104
- return nil
1105
1098
}
1106
1099
1107
1100
func exists (path string ) (bool , error ) {
@@ -1521,10 +1514,10 @@ func (db *DB) startCompactions() {
1521
1514
func (db * DB ) startMemoryFlush () {
1522
1515
// Start memory fluhser.
1523
1516
if db .closers .memtable != nil {
1524
- db .flushChan = make (chan flushTask , db .opt .NumMemtables )
1517
+ db .flushChan = make (chan * memTable , db .opt .NumMemtables )
1525
1518
db .closers .memtable = z .NewCloser (1 )
1526
1519
go func () {
1527
- _ = db .flushMemtable (db .closers .memtable )
1520
+ db .flushMemtable (db .closers .memtable )
1528
1521
}()
1529
1522
}
1530
1523
}
@@ -1627,7 +1620,7 @@ func (db *DB) prepareToDrop() (func(), error) {
1627
1620
panic ("Attempting to drop data in read-only mode." )
1628
1621
}
1629
1622
// In order prepare for drop, we need to block the incoming writes and
1630
- // write it to db. Then, flush all the pending flushtask . So that, we
1623
+ // write it to db. Then, flush all the pending memtable . So that, we
1631
1624
// don't miss any entries.
1632
1625
if err := db .blockWrite (); err != nil {
1633
1626
return nil , err
@@ -1676,7 +1669,7 @@ func (db *DB) dropAll() (func(), error) {
1676
1669
if err != nil {
1677
1670
return f , err
1678
1671
}
1679
- // prepareToDrop will stop all the incomming write and flushes any pending flush tasks .
1672
+ // prepareToDrop will stop all the incomming write and flushes any pending memtables .
1680
1673
// Before we drop, we'll stop the compaction because anyways all the datas are going to
1681
1674
// be deleted.
1682
1675
db .stopCompactions ()
@@ -1758,13 +1751,8 @@ func (db *DB) DropPrefix(prefixes ...[]byte) error {
1758
1751
memtable .DecrRef ()
1759
1752
continue
1760
1753
}
1761
- task := flushTask {
1762
- mt : memtable ,
1763
- // Ensure that the head of value log gets persisted to disk.
1764
- dropPrefixes : filtered ,
1765
- }
1766
1754
db .opt .Debugf ("Flushing memtable" )
1767
- if err := db .handleFlushTask ( task ); err != nil {
1755
+ if err := db .handleMemTableFlush ( memtable , filtered ); err != nil {
1768
1756
db .opt .Errorf ("While trying to flush memtable: %v" , err )
1769
1757
return err
1770
1758
}
0 commit comments