@@ -493,7 +493,9 @@ func (vlog *valueLog) iterate(lf *logFile, offset uint32, fn logEntry) (uint32,
493
493
}
494
494
495
495
func (vlog * valueLog ) rewrite (f * logFile , tr trace.Trace ) error {
496
- maxFid := atomic .LoadUint32 (& vlog .maxFid )
496
+ vlog .filesLock .RLock ()
497
+ maxFid := vlog .maxFid
498
+ vlog .filesLock .RUnlock ()
497
499
y .AssertTruef (uint32 (f .fid ) < maxFid , "fid to move: %d. Current max fid: %d" , f .fid , maxFid )
498
500
tr .LazyPrintf ("Rewriting fid: %d" , f .fid )
499
501
@@ -808,10 +810,9 @@ func (vlog *valueLog) dropAll() (int, error) {
808
810
}
809
811
810
812
vlog .db .opt .Infof ("Value logs deleted. Creating value log file: 0" )
811
- if _ , err := vlog .createVlogFile (0 ); err != nil {
813
+ if _ , err := vlog .createVlogFile (0 ); err != nil { // Called while writes are stopped.
812
814
return count , err
813
815
}
814
- atomic .StoreUint32 (& vlog .maxFid , 0 )
815
816
return count , nil
816
817
}
817
818
@@ -832,12 +833,12 @@ type valueLog struct {
832
833
// guards our view of which files exist, which to be deleted, how many active iterators
833
834
filesLock sync.RWMutex
834
835
filesMap map [uint32 ]* logFile
836
+ maxFid uint32
835
837
filesToBeDeleted []uint32
836
838
// A refcount of iterators -- when this hits zero, we can delete the filesToBeDeleted.
837
839
numActiveIterators int32
838
840
839
841
db * DB
840
- maxFid uint32 // accessed via atomics.
841
842
writableLogOffset uint32 // read by read, written by write. Must access via atomics.
842
843
numEntriesWritten uint32
843
844
opt Options
@@ -1005,6 +1006,7 @@ func (vlog *valueLog) createVlogFile(fid uint32) (*logFile, error) {
1005
1006
1006
1007
vlog .filesLock .Lock ()
1007
1008
vlog .filesMap [fid ] = lf
1009
+ vlog .maxFid = fid
1008
1010
vlog .filesLock .Unlock ()
1009
1011
1010
1012
return lf , nil
@@ -1155,12 +1157,12 @@ func (vlog *valueLog) open(db *DB, ptr valuePointer, replayFn logEntry) error {
1155
1157
// plain text mode or vice versa. A single vlog file can't have both
1156
1158
// encrypted entries and plain text entries.
1157
1159
if last .encryptionEnabled () != vlog .db .shouldEncrypt () {
1158
- newid := atomic . AddUint32 ( & vlog .maxFid , 1 )
1160
+ newid := vlog .maxFid + 1
1159
1161
_ , err := vlog .createVlogFile (newid )
1160
1162
if err != nil {
1161
1163
return y .Wrapf (err , "Error while creating log file %d in valueLog.open" , newid )
1162
1164
}
1163
- last , ok = vlog .filesMap [vlog . maxFid ]
1165
+ last , ok = vlog .filesMap [newid ]
1164
1166
y .AssertTrue (ok )
1165
1167
}
1166
1168
lastOffset , err := last .fd .Seek (0 , io .SeekEnd )
@@ -1222,7 +1224,7 @@ func (vlog *valueLog) Close() error {
1222
1224
err = munmapErr
1223
1225
}
1224
1226
1225
- maxFid := atomic . LoadUint32 ( & vlog .maxFid )
1227
+ maxFid := vlog .maxFid
1226
1228
if ! vlog .opt .ReadOnly && id == maxFid {
1227
1229
// truncate writable log file to correct offset.
1228
1230
if truncErr := f .fd .Truncate (
@@ -1320,7 +1322,7 @@ func (vlog *valueLog) sync(fid uint32) error {
1320
1322
}
1321
1323
1322
1324
vlog .filesLock .RLock ()
1323
- maxFid := atomic . LoadUint32 ( & vlog .maxFid )
1325
+ maxFid := vlog .maxFid
1324
1326
// During replay it is possible to get sync call with fid less than maxFid.
1325
1327
// Because older file has already been synced, we can return from here.
1326
1328
if fid < maxFid || len (vlog .filesMap ) == 0 {
@@ -1353,7 +1355,7 @@ func (vlog *valueLog) write(reqs []*request) error {
1353
1355
return nil
1354
1356
}
1355
1357
vlog .filesLock .RLock ()
1356
- maxFid := atomic . LoadUint32 ( & vlog .maxFid )
1358
+ maxFid := vlog .maxFid
1357
1359
curlf := vlog .filesMap [maxFid ]
1358
1360
vlog .filesLock .RUnlock ()
1359
1361
@@ -1385,7 +1387,7 @@ func (vlog *valueLog) write(reqs []*request) error {
1385
1387
return err
1386
1388
}
1387
1389
1388
- newid := atomic . AddUint32 ( & vlog .maxFid , 1 )
1390
+ newid := vlog .maxFid + 1
1389
1391
y .AssertTruef (newid > 0 , "newid has overflown uint32: %v" , newid )
1390
1392
newlf , err := vlog .createVlogFile (newid )
1391
1393
if err != nil {
@@ -1446,28 +1448,33 @@ func (vlog *valueLog) write(reqs []*request) error {
1446
1448
1447
1449
// Gets the logFile and acquires and RLock() for the mmap. You must call RUnlock on the file
1448
1450
// (if non-nil)
1449
- func (vlog * valueLog ) getFileRLocked (fid uint32 ) (* logFile , error ) {
1451
+ func (vlog * valueLog ) getFileRLocked (vp valuePointer ) (* logFile , error ) {
1450
1452
vlog .filesLock .RLock ()
1451
1453
defer vlog .filesLock .RUnlock ()
1452
- ret , ok := vlog .filesMap [fid ]
1454
+ ret , ok := vlog .filesMap [vp . Fid ]
1453
1455
if ! ok {
1454
1456
// log file has gone away, will need to retry the operation.
1455
1457
return nil , ErrRetry
1456
1458
}
1459
+
1460
+ // Check for valid offset if we are reading from writable log.
1461
+ maxFid := vlog .maxFid
1462
+ if vp .Fid == maxFid {
1463
+ currentOffset := vlog .woffset ()
1464
+ if vp .Offset >= currentOffset {
1465
+ return nil , errors .Errorf (
1466
+ "Invalid value pointer offset: %d greater than current offset: %d" ,
1467
+ vp .Offset , currentOffset )
1468
+ }
1469
+ }
1470
+
1457
1471
ret .lock .RLock ()
1458
1472
return ret , nil
1459
1473
}
1460
1474
1461
1475
// Read reads the value log at a given location.
1462
1476
// TODO: Make this read private.
1463
1477
func (vlog * valueLog ) Read (vp valuePointer , s * y.Slice ) ([]byte , func (), error ) {
1464
- // Check for valid offset if we are reading from writable log.
1465
- maxFid := atomic .LoadUint32 (& vlog .maxFid )
1466
- if vp .Fid == maxFid && vp .Offset >= vlog .woffset () {
1467
- return nil , nil , errors .Errorf (
1468
- "Invalid value pointer offset: %d greater than current offset: %d" ,
1469
- vp .Offset , vlog .woffset ())
1470
- }
1471
1478
buf , lf , err := vlog .readValueBytes (vp , s )
1472
1479
// log file is locked so, decide whether to lock immediately or let the caller to
1473
1480
// unlock it, after caller uses it.
@@ -1517,10 +1524,11 @@ func (vlog *valueLog) getUnlockCallback(lf *logFile) func() {
1517
1524
// readValueBytes return vlog entry slice and read locked log file. Caller should take care of
1518
1525
// logFile unlocking.
1519
1526
func (vlog * valueLog ) readValueBytes (vp valuePointer , s * y.Slice ) ([]byte , * logFile , error ) {
1520
- lf , err := vlog .getFileRLocked (vp . Fid )
1527
+ lf , err := vlog .getFileRLocked (vp )
1521
1528
if err != nil {
1522
1529
return nil , nil , err
1523
1530
}
1531
+
1524
1532
buf , err := lf .read (vp , s )
1525
1533
return buf , lf , err
1526
1534
}
0 commit comments