Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
905a723f
Unverified
Commit
905a723f
authored
Mar 21, 2023
by
s7v7nislands
Committed by
GitHub
Mar 21, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core/rawdb: use atomic int added in go1.19 (#26935)
parent
8a9a73c9
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
90 additions
and
100 deletions
+90
-100
chain_freezer.go
core/rawdb/chain_freezer.go
+11
-13
chain_iterator.go
core/rawdb/chain_iterator.go
+3
-2
database.go
core/rawdb/database.go
+3
-4
freezer.go
core/rawdb/freezer.go
+25
-28
freezer_batch.go
core/rawdb/freezer_batch.go
+2
-3
freezer_table.go
core/rawdb/freezer_table.go
+25
-28
freezer_table_test.go
core/rawdb/freezer_table_test.go
+19
-20
freezer_test.go
core/rawdb/freezer_test.go
+2
-2
No files found.
core/rawdb/chain_freezer.go
View file @
905a723f
...
...
@@ -43,10 +43,7 @@ const (
// The background thread will keep moving ancient chain segments from key-value
// database to flat files for saving space on live database.
type
chainFreezer
struct
{
// WARNING: The `threshold` field is accessed atomically. On 32 bit platforms, only
// 64-bit aligned fields can be atomic. The struct is guaranteed to be so aligned,
// so take advantage of that (https://golang.org/pkg/sync/atomic/#pkg-note-BUG).
threshold
uint64
// Number of recent blocks not to freeze (params.FullImmutabilityThreshold apart from tests)
threshold
atomic
.
Uint64
// Number of recent blocks not to freeze (params.FullImmutabilityThreshold apart from tests)
*
Freezer
quit
chan
struct
{}
...
...
@@ -60,12 +57,13 @@ func newChainFreezer(datadir string, namespace string, readonly bool) (*chainFre
if
err
!=
nil
{
return
nil
,
err
}
return
&
chainFreezer
{
Freezer
:
freezer
,
threshold
:
params
.
FullImmutabilityThreshold
,
quit
:
make
(
chan
struct
{}),
trigger
:
make
(
chan
chan
struct
{}),
},
nil
cf
:=
chainFreezer
{
Freezer
:
freezer
,
quit
:
make
(
chan
struct
{}),
trigger
:
make
(
chan
chan
struct
{}),
}
cf
.
threshold
.
Store
(
params
.
FullImmutabilityThreshold
)
return
&
cf
,
nil
}
// Close closes the chain freezer instance and terminates the background thread.
...
...
@@ -124,8 +122,8 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
continue
}
number
:=
ReadHeaderNumber
(
nfdb
,
hash
)
threshold
:=
atomic
.
LoadUint64
(
&
f
.
threshold
)
frozen
:=
atomic
.
LoadUint64
(
&
f
.
frozen
)
threshold
:=
f
.
threshold
.
Load
(
)
frozen
:=
f
.
frozen
.
Load
(
)
switch
{
case
number
==
nil
:
log
.
Error
(
"Current full block number unavailable"
,
"hash"
,
hash
)
...
...
@@ -186,7 +184,7 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
// Wipe out side chains also and track dangling side chains
var
dangling
[]
common
.
Hash
frozen
=
atomic
.
LoadUint64
(
&
f
.
frozen
)
// Needs reload after during freezeRange
frozen
=
f
.
frozen
.
Load
(
)
// Needs reload after during freezeRange
for
number
:=
first
;
number
<
frozen
;
number
++
{
// Always keep the genesis block in active database
if
number
!=
0
{
...
...
core/rawdb/chain_iterator.go
View file @
905a723f
...
...
@@ -132,11 +132,12 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
}
}
// process runs in parallel
nThreadsAlive
:=
int32
(
threads
)
var
nThreadsAlive
atomic
.
Int32
nThreadsAlive
.
Store
(
int32
(
threads
))
process
:=
func
()
{
defer
func
()
{
// Last processor closes the result channel
if
atomic
.
AddInt32
(
&
nThreadsAlive
,
-
1
)
==
0
{
if
nThreadsAlive
.
Add
(
-
1
)
==
0
{
close
(
hashesCh
)
}
}()
...
...
core/rawdb/database.go
View file @
905a723f
...
...
@@ -24,7 +24,6 @@ import (
"path"
"path/filepath"
"strings"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -72,9 +71,9 @@ func (frdb *freezerdb) Freeze(threshold uint64) error {
}
// Set the freezer threshold to a temporary value
defer
func
(
old
uint64
)
{
atomic
.
StoreUint64
(
&
frdb
.
AncientStore
.
(
*
chainFreezer
)
.
threshold
,
old
)
}(
atomic
.
LoadUint64
(
&
frdb
.
AncientStore
.
(
*
chainFreezer
)
.
threshold
))
atomic
.
StoreUint64
(
&
frdb
.
AncientStore
.
(
*
chainFreezer
)
.
threshold
,
threshold
)
frdb
.
AncientStore
.
(
*
chainFreezer
)
.
threshold
.
Store
(
old
)
}(
frdb
.
AncientStore
.
(
*
chainFreezer
)
.
threshold
.
Load
(
))
frdb
.
AncientStore
.
(
*
chainFreezer
)
.
threshold
.
Store
(
threshold
)
// Trigger a freeze cycle and block until it's done
trigger
:=
make
(
chan
struct
{},
1
)
...
...
core/rawdb/freezer.go
View file @
905a723f
...
...
@@ -62,11 +62,8 @@ const freezerTableSize = 2 * 1000 * 1000 * 1000
// reserving it for go-ethereum. This would also reduce the memory requirements
// of Geth, and thus also GC overhead.
type
Freezer
struct
{
// WARNING: The `frozen` and `tail` fields are accessed atomically. On 32 bit platforms, only
// 64-bit aligned fields can be atomic. The struct is guaranteed to be so aligned,
// so take advantage of that (https://golang.org/pkg/sync/atomic/#pkg-note-BUG).
frozen
uint64
// Number of blocks already frozen
tail
uint64
// Number of the first stored item in the freezer
frozen
atomic
.
Uint64
// Number of blocks already frozen
tail
atomic
.
Uint64
// Number of the first stored item in the freezer
// This lock synchronizes writers and the truncate operation, as well as
// the "atomic" (batched) read operations.
...
...
@@ -212,12 +209,12 @@ func (f *Freezer) AncientRange(kind string, start, count, maxBytes uint64) ([][]
// Ancients returns the length of the frozen items.
func
(
f
*
Freezer
)
Ancients
()
(
uint64
,
error
)
{
return
atomic
.
LoadUint64
(
&
f
.
frozen
),
nil
return
f
.
frozen
.
Load
(
),
nil
}
// Tail returns the number of first stored item in the freezer.
func
(
f
*
Freezer
)
Tail
()
(
uint64
,
error
)
{
return
atomic
.
LoadUint64
(
&
f
.
tail
),
nil
return
f
.
tail
.
Load
(
),
nil
}
// AncientSize returns the ancient size of the specified category.
...
...
@@ -251,7 +248,7 @@ func (f *Freezer) ModifyAncients(fn func(ethdb.AncientWriteOp) error) (writeSize
defer
f
.
writeLock
.
Unlock
()
// Roll back all tables to the starting position in case of error.
prevItem
:=
atomic
.
LoadUint64
(
&
f
.
frozen
)
prevItem
:=
f
.
frozen
.
Load
(
)
defer
func
()
{
if
err
!=
nil
{
// The write operation has failed. Go back to the previous item position.
...
...
@@ -272,7 +269,7 @@ func (f *Freezer) ModifyAncients(fn func(ethdb.AncientWriteOp) error) (writeSize
if
err
!=
nil
{
return
0
,
err
}
atomic
.
StoreUint64
(
&
f
.
frozen
,
item
)
f
.
frozen
.
Store
(
item
)
return
writeSize
,
nil
}
...
...
@@ -284,7 +281,7 @@ func (f *Freezer) TruncateHead(items uint64) error {
f
.
writeLock
.
Lock
()
defer
f
.
writeLock
.
Unlock
()
if
atomic
.
LoadUint64
(
&
f
.
frozen
)
<=
items
{
if
f
.
frozen
.
Load
(
)
<=
items
{
return
nil
}
for
_
,
table
:=
range
f
.
tables
{
...
...
@@ -292,7 +289,7 @@ func (f *Freezer) TruncateHead(items uint64) error {
return
err
}
}
atomic
.
StoreUint64
(
&
f
.
frozen
,
items
)
f
.
frozen
.
Store
(
items
)
return
nil
}
...
...
@@ -304,7 +301,7 @@ func (f *Freezer) TruncateTail(tail uint64) error {
f
.
writeLock
.
Lock
()
defer
f
.
writeLock
.
Unlock
()
if
atomic
.
LoadUint64
(
&
f
.
tail
)
>=
tail
{
if
f
.
tail
.
Load
(
)
>=
tail
{
return
nil
}
for
_
,
table
:=
range
f
.
tables
{
...
...
@@ -312,7 +309,7 @@ func (f *Freezer) TruncateTail(tail uint64) error {
return
err
}
}
atomic
.
StoreUint64
(
&
f
.
tail
,
tail
)
f
.
tail
.
Store
(
tail
)
return
nil
}
...
...
@@ -343,22 +340,22 @@ func (f *Freezer) validate() error {
)
// Hack to get boundary of any table
for
kind
,
table
:=
range
f
.
tables
{
head
=
atomic
.
LoadUint64
(
&
table
.
items
)
tail
=
atomic
.
LoadUint64
(
&
table
.
itemHidden
)
head
=
table
.
items
.
Load
(
)
tail
=
table
.
itemHidden
.
Load
(
)
name
=
kind
break
}
// Now check every table against those boundaries.
for
kind
,
table
:=
range
f
.
tables
{
if
head
!=
atomic
.
LoadUint64
(
&
table
.
items
)
{
return
fmt
.
Errorf
(
"freezer tables %s and %s have differing head: %d != %d"
,
kind
,
name
,
atomic
.
LoadUint64
(
&
table
.
items
),
head
)
if
head
!=
table
.
items
.
Load
(
)
{
return
fmt
.
Errorf
(
"freezer tables %s and %s have differing head: %d != %d"
,
kind
,
name
,
table
.
items
.
Load
(
),
head
)
}
if
tail
!=
atomic
.
LoadUint64
(
&
table
.
itemHidden
)
{
return
fmt
.
Errorf
(
"freezer tables %s and %s have differing tail: %d != %d"
,
kind
,
name
,
atomic
.
LoadUint64
(
&
table
.
itemHidden
),
tail
)
if
tail
!=
table
.
itemHidden
.
Load
(
)
{
return
fmt
.
Errorf
(
"freezer tables %s and %s have differing tail: %d != %d"
,
kind
,
name
,
table
.
itemHidden
.
Load
(
),
tail
)
}
}
atomic
.
StoreUint64
(
&
f
.
frozen
,
head
)
atomic
.
StoreUint64
(
&
f
.
tail
,
tail
)
f
.
frozen
.
Store
(
head
)
f
.
tail
.
Store
(
tail
)
return
nil
}
...
...
@@ -369,11 +366,11 @@ func (f *Freezer) repair() error {
tail
=
uint64
(
0
)
)
for
_
,
table
:=
range
f
.
tables
{
items
:=
atomic
.
LoadUint64
(
&
table
.
items
)
items
:=
table
.
items
.
Load
(
)
if
head
>
items
{
head
=
items
}
hidden
:=
atomic
.
LoadUint64
(
&
table
.
itemHidden
)
hidden
:=
table
.
itemHidden
.
Load
(
)
if
hidden
>
tail
{
tail
=
hidden
}
...
...
@@ -386,8 +383,8 @@ func (f *Freezer) repair() error {
return
err
}
}
atomic
.
StoreUint64
(
&
f
.
frozen
,
head
)
atomic
.
StoreUint64
(
&
f
.
tail
,
tail
)
f
.
frozen
.
Store
(
head
)
f
.
tail
.
Store
(
tail
)
return
nil
}
...
...
@@ -413,7 +410,7 @@ func (f *Freezer) MigrateTable(kind string, convert convertLegacyFn) error {
// and that error will be returned.
forEach
:=
func
(
t
*
freezerTable
,
offset
uint64
,
fn
func
(
uint64
,
[]
byte
)
error
)
error
{
var
(
items
=
atomic
.
LoadUint64
(
&
t
.
items
)
items
=
t
.
items
.
Load
(
)
batchSize
=
uint64
(
1024
)
maxBytes
=
uint64
(
1024
*
1024
)
)
...
...
@@ -436,7 +433,7 @@ func (f *Freezer) MigrateTable(kind string, convert convertLegacyFn) error {
}
// TODO(s1na): This is a sanity-check since as of now no process does tail-deletion. But the migration
// process assumes no deletion at tail and needs to be modified to account for that.
if
table
.
itemOffset
>
0
||
table
.
itemHidden
>
0
{
if
table
.
itemOffset
.
Load
()
>
0
||
table
.
itemHidden
.
Load
()
>
0
{
return
fmt
.
Errorf
(
"migration not supported for tail-deleted freezers"
)
}
ancientsPath
:=
filepath
.
Dir
(
table
.
index
.
Name
())
...
...
@@ -452,7 +449,7 @@ func (f *Freezer) MigrateTable(kind string, convert convertLegacyFn) error {
out
[]
byte
start
=
time
.
Now
()
logged
=
time
.
Now
()
offset
=
newTable
.
items
offset
=
newTable
.
items
.
Load
()
)
if
offset
>
0
{
log
.
Info
(
"found previous migration attempt"
,
"migrated"
,
offset
)
...
...
core/rawdb/freezer_batch.go
View file @
905a723f
...
...
@@ -18,7 +18,6 @@ package rawdb
import
(
"fmt"
"sync/atomic"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/rlp"
...
...
@@ -107,7 +106,7 @@ func (t *freezerTable) newBatch() *freezerTableBatch {
func
(
batch
*
freezerTableBatch
)
reset
()
{
batch
.
dataBuffer
=
batch
.
dataBuffer
[
:
0
]
batch
.
indexBuffer
=
batch
.
indexBuffer
[
:
0
]
batch
.
curItem
=
atomic
.
LoadUint64
(
&
batch
.
t
.
items
)
batch
.
curItem
=
batch
.
t
.
items
.
Load
(
)
batch
.
totalBytes
=
0
}
...
...
@@ -201,7 +200,7 @@ func (batch *freezerTableBatch) commit() error {
// Update headBytes of table.
batch
.
t
.
headBytes
+=
dataSize
atomic
.
StoreUint64
(
&
batch
.
t
.
items
,
batch
.
curItem
)
batch
.
t
.
items
.
Store
(
batch
.
curItem
)
// Update metrics.
batch
.
t
.
sizeGauge
.
Inc
(
dataSize
+
indexSize
)
...
...
core/rawdb/freezer_table.go
View file @
905a723f
...
...
@@ -88,18 +88,15 @@ func (i *indexEntry) bounds(end *indexEntry) (startOffset, endOffset, fileId uin
// It consists of a data file (snappy encoded arbitrary data blobs) and an indexEntry
// file (uncompressed 64 bit indices into the data file).
type
freezerTable
struct
{
// WARNING: The `items` field is accessed atomically. On 32 bit platforms, only
// 64-bit aligned fields can be atomic. The struct is guaranteed to be so aligned,
// so take advantage of that (https://golang.org/pkg/sync/atomic/#pkg-note-BUG).
items
uint64
// Number of items stored in the table (including items removed from tail)
itemOffset
uint64
// Number of items removed from the table
items
atomic
.
Uint64
// Number of items stored in the table (including items removed from tail)
itemOffset
atomic
.
Uint64
// Number of items removed from the table
// itemHidden is the number of items marked as deleted. Tail deletion is
// only supported at file level which means the actual deletion will be
// delayed until the entire data file is marked as deleted. Before that
// these items will be hidden to prevent being visited again. The value
// should never be lower than itemOffset.
itemHidden
u
int64
itemHidden
atomic
.
U
int64
noCompression
bool
// if true, disables snappy compression. Note: does not work retroactively
readonly
bool
...
...
@@ -241,14 +238,14 @@ func (t *freezerTable) repair() error {
// which is not enough in theory but enough in practice.
// TODO: use uint64 to represent total removed items.
t
.
tailId
=
firstIndex
.
filenum
t
.
itemOffset
=
uint64
(
firstIndex
.
offset
)
t
.
itemOffset
.
Store
(
uint64
(
firstIndex
.
offset
)
)
// Load metadata from the file
meta
,
err
:=
loadMetadata
(
t
.
meta
,
t
.
itemOffset
)
meta
,
err
:=
loadMetadata
(
t
.
meta
,
t
.
itemOffset
.
Load
()
)
if
err
!=
nil
{
return
err
}
t
.
itemHidden
=
meta
.
VirtualTail
t
.
itemHidden
.
Store
(
meta
.
VirtualTail
)
// Read the last index, use the default value in case the freezer is empty
if
offsetsSize
==
indexEntrySize
{
...
...
@@ -331,7 +328,7 @@ func (t *freezerTable) repair() error {
}
}
// Update the item and byte counters and return
t
.
items
=
t
.
itemOffset
+
uint64
(
offsetsSize
/
indexEntrySize
-
1
)
// last indexEntry points to the end of the data file
t
.
items
.
Store
(
t
.
itemOffset
.
Load
()
+
uint64
(
offsetsSize
/
indexEntrySize
-
1
)
)
// last indexEntry points to the end of the data file
t
.
headBytes
=
contentSize
t
.
headId
=
lastIndex
.
filenum
...
...
@@ -346,9 +343,9 @@ func (t *freezerTable) repair() error {
return
err
}
if
verbose
{
t
.
logger
.
Info
(
"Chain freezer table opened"
,
"items"
,
t
.
items
,
"size"
,
t
.
headBytes
)
t
.
logger
.
Info
(
"Chain freezer table opened"
,
"items"
,
t
.
items
.
Load
()
,
"size"
,
t
.
headBytes
)
}
else
{
t
.
logger
.
Debug
(
"Chain freezer table opened"
,
"items"
,
t
.
items
,
"size"
,
common
.
StorageSize
(
t
.
headBytes
))
t
.
logger
.
Debug
(
"Chain freezer table opened"
,
"items"
,
t
.
items
.
Load
()
,
"size"
,
common
.
StorageSize
(
t
.
headBytes
))
}
return
nil
}
...
...
@@ -382,11 +379,11 @@ func (t *freezerTable) truncateHead(items uint64) error {
defer
t
.
lock
.
Unlock
()
// Ensure the given truncate target falls in the correct range
existing
:=
atomic
.
LoadUint64
(
&
t
.
items
)
existing
:=
t
.
items
.
Load
(
)
if
existing
<=
items
{
return
nil
}
if
items
<
atomic
.
LoadUint64
(
&
t
.
itemHidden
)
{
if
items
<
t
.
itemHidden
.
Load
(
)
{
return
errors
.
New
(
"truncation below tail"
)
}
// We need to truncate, save the old size for metrics tracking
...
...
@@ -403,7 +400,7 @@ func (t *freezerTable) truncateHead(items uint64) error {
// Truncate the index file first, the tail position is also considered
// when calculating the new freezer table length.
length
:=
items
-
atomic
.
LoadUint64
(
&
t
.
itemOffset
)
length
:=
items
-
t
.
itemOffset
.
Load
(
)
if
err
:=
truncateFreezerFile
(
t
.
index
,
int64
(
length
+
1
)
*
indexEntrySize
);
err
!=
nil
{
return
err
}
...
...
@@ -438,7 +435,7 @@ func (t *freezerTable) truncateHead(items uint64) error {
}
// All data files truncated, set internal counters and return
t
.
headBytes
=
int64
(
expected
.
offset
)
atomic
.
StoreUint64
(
&
t
.
items
,
items
)
t
.
items
.
Store
(
items
)
// Retrieve the new size and update the total size counter
newSize
,
err
:=
t
.
sizeNolock
()
...
...
@@ -455,10 +452,10 @@ func (t *freezerTable) truncateTail(items uint64) error {
defer
t
.
lock
.
Unlock
()
// Ensure the given truncate target falls in the correct range
if
atomic
.
LoadUint64
(
&
t
.
itemHidden
)
>=
items
{
if
t
.
itemHidden
.
Load
(
)
>=
items
{
return
nil
}
if
atomic
.
LoadUint64
(
&
t
.
items
)
<
items
{
if
t
.
items
.
Load
(
)
<
items
{
return
errors
.
New
(
"truncation above head"
)
}
// Load the new tail index by the given new tail position
...
...
@@ -466,10 +463,10 @@ func (t *freezerTable) truncateTail(items uint64) error {
newTailId
uint32
buffer
=
make
([]
byte
,
indexEntrySize
)
)
if
atomic
.
LoadUint64
(
&
t
.
items
)
==
items
{
if
t
.
items
.
Load
(
)
==
items
{
newTailId
=
t
.
headId
}
else
{
offset
:=
items
-
atomic
.
LoadUint64
(
&
t
.
itemOffset
)
offset
:=
items
-
t
.
itemOffset
.
Load
(
)
if
_
,
err
:=
t
.
index
.
ReadAt
(
buffer
,
int64
((
offset
+
1
)
*
indexEntrySize
));
err
!=
nil
{
return
err
}
...
...
@@ -478,7 +475,7 @@ func (t *freezerTable) truncateTail(items uint64) error {
newTailId
=
newTail
.
filenum
}
// Update the virtual tail marker and hidden these entries in table.
atomic
.
StoreUint64
(
&
t
.
itemHidden
,
items
)
t
.
itemHidden
.
Store
(
items
)
if
err
:=
writeMetadata
(
t
.
meta
,
newMetadata
(
items
));
err
!=
nil
{
return
err
}
...
...
@@ -501,7 +498,7 @@ func (t *freezerTable) truncateTail(items uint64) error {
// Count how many items can be deleted from the file.
var
(
newDeleted
=
items
deleted
=
atomic
.
LoadUint64
(
&
t
.
itemOffset
)
deleted
=
t
.
itemOffset
.
Load
(
)
)
for
current
:=
items
-
1
;
current
>=
deleted
;
current
-=
1
{
if
_
,
err
:=
t
.
index
.
ReadAt
(
buffer
,
int64
((
current
-
deleted
+
1
)
*
indexEntrySize
));
err
!=
nil
{
...
...
@@ -541,7 +538,7 @@ func (t *freezerTable) truncateTail(items uint64) error {
}
// Release any files before the current tail
t
.
tailId
=
newTailId
atomic
.
StoreUint64
(
&
t
.
itemOffset
,
newDeleted
)
t
.
itemOffset
.
Store
(
newDeleted
)
t
.
releaseFilesBefore
(
t
.
tailId
,
true
)
// Retrieve the new size and update the total size counter
...
...
@@ -654,7 +651,7 @@ func (t *freezerTable) releaseFilesBefore(num uint32, remove bool) {
// it will return error.
func
(
t
*
freezerTable
)
getIndices
(
from
,
count
uint64
)
([]
*
indexEntry
,
error
)
{
// Apply the table-offset
from
=
from
-
t
.
itemOffset
from
=
from
-
t
.
itemOffset
.
Load
()
// For reading N items, we need N+1 indices.
buffer
:=
make
([]
byte
,
(
count
+
1
)
*
indexEntrySize
)
if
_
,
err
:=
t
.
index
.
ReadAt
(
buffer
,
int64
(
from
*
indexEntrySize
));
err
!=
nil
{
...
...
@@ -744,8 +741,8 @@ func (t *freezerTable) retrieveItems(start, count, maxBytes uint64) ([]byte, []i
return
nil
,
nil
,
errClosed
}
var
(
items
=
atomic
.
LoadUint64
(
&
t
.
items
)
// the total items(head + 1)
hidden
=
atomic
.
LoadUint64
(
&
t
.
itemHidden
)
// the number of hidden items
items
=
t
.
items
.
Load
(
)
// the total items(head + 1)
hidden
=
t
.
itemHidden
.
Load
(
)
// the number of hidden items
)
// Ensure the start is written, not deleted from the tail, and that the
// caller actually wants something
...
...
@@ -832,7 +829,7 @@ func (t *freezerTable) retrieveItems(start, count, maxBytes uint64) ([]byte, []i
// has returns an indicator whether the specified number data is still accessible
// in the freezer table.
func
(
t
*
freezerTable
)
has
(
number
uint64
)
bool
{
return
atomic
.
LoadUint64
(
&
t
.
items
)
>
number
&&
atomic
.
LoadUint64
(
&
t
.
itemHidden
)
<=
number
return
t
.
items
.
Load
()
>
number
&&
t
.
itemHidden
.
Load
(
)
<=
number
}
// size returns the total data size in the freezer table.
...
...
@@ -922,7 +919,7 @@ func (t *freezerTable) dumpIndex(w io.Writer, start, stop int64) {
return
}
fmt
.
Fprintf
(
w
,
"Version %d count %d, deleted %d, hidden %d
\n
"
,
meta
.
Version
,
atomic
.
LoadUint64
(
&
t
.
items
),
atomic
.
LoadUint64
(
&
t
.
itemOffset
),
atomic
.
LoadUint64
(
&
t
.
itemHidden
))
t
.
items
.
Load
(),
t
.
itemOffset
.
Load
(),
t
.
itemHidden
.
Load
(
))
buf
:=
make
([]
byte
,
indexEntrySize
)
...
...
core/rawdb/freezer_table_test.go
View file @
905a723f
...
...
@@ -24,7 +24,6 @@ import (
"os"
"path/filepath"
"reflect"
"sync/atomic"
"testing"
"testing/quick"
...
...
@@ -191,7 +190,7 @@ func TestFreezerRepairDanglingHeadLarge(t *testing.T) {
writeChunks
(
t
,
f
,
255
,
15
)
// The last item should be there
if
_
,
err
=
f
.
Retrieve
(
f
.
items
-
1
);
err
!=
nil
{
if
_
,
err
=
f
.
Retrieve
(
f
.
items
.
Load
()
-
1
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
f
.
Close
()
...
...
@@ -317,7 +316,7 @@ func TestFreezerRepairDanglingIndex(t *testing.T) {
writeChunks
(
t
,
f
,
9
,
15
)
// The last item should be there
if
_
,
err
=
f
.
Retrieve
(
f
.
items
-
1
);
err
!=
nil
{
if
_
,
err
=
f
.
Retrieve
(
f
.
items
.
Load
()
-
1
);
err
!=
nil
{
f
.
Close
()
t
.
Fatal
(
err
)
}
...
...
@@ -350,8 +349,8 @@ func TestFreezerRepairDanglingIndex(t *testing.T) {
t
.
Fatal
(
err
)
}
defer
f
.
Close
()
if
f
.
items
!=
7
{
t
.
Fatalf
(
"expected %d items, got %d"
,
7
,
f
.
items
)
if
f
.
items
.
Load
()
!=
7
{
t
.
Fatalf
(
"expected %d items, got %d"
,
7
,
f
.
items
.
Load
()
)
}
if
err
:=
assertFileSize
(
fileToCrop
,
15
);
err
!=
nil
{
t
.
Fatal
(
err
)
...
...
@@ -374,7 +373,7 @@ func TestFreezerTruncate(t *testing.T) {
writeChunks
(
t
,
f
,
30
,
15
)
// The last item should be there
if
_
,
err
=
f
.
Retrieve
(
f
.
items
-
1
);
err
!=
nil
{
if
_
,
err
=
f
.
Retrieve
(
f
.
items
.
Load
()
-
1
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
f
.
Close
()
...
...
@@ -388,8 +387,8 @@ func TestFreezerTruncate(t *testing.T) {
}
defer
f
.
Close
()
f
.
truncateHead
(
10
)
// 150 bytes
if
f
.
items
!=
10
{
t
.
Fatalf
(
"expected %d items, got %d"
,
10
,
f
.
items
)
if
f
.
items
.
Load
()
!=
10
{
t
.
Fatalf
(
"expected %d items, got %d"
,
10
,
f
.
items
.
Load
()
)
}
// 45, 45, 45, 15 -- bytes should be 15
if
f
.
headBytes
!=
15
{
...
...
@@ -444,9 +443,9 @@ func TestFreezerRepairFirstFile(t *testing.T) {
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
f
.
items
!=
1
{
if
f
.
items
.
Load
()
!=
1
{
f
.
Close
()
t
.
Fatalf
(
"expected %d items, got %d"
,
0
,
f
.
items
)
t
.
Fatalf
(
"expected %d items, got %d"
,
0
,
f
.
items
.
Load
()
)
}
// Write 40 bytes
...
...
@@ -483,7 +482,7 @@ func TestFreezerReadAndTruncate(t *testing.T) {
writeChunks
(
t
,
f
,
30
,
15
)
// The last item should be there
if
_
,
err
=
f
.
Retrieve
(
f
.
items
-
1
);
err
!=
nil
{
if
_
,
err
=
f
.
Retrieve
(
f
.
items
.
Load
()
-
1
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
f
.
Close
()
...
...
@@ -495,9 +494,9 @@ func TestFreezerReadAndTruncate(t *testing.T) {
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
f
.
items
!=
30
{
if
f
.
items
.
Load
()
!=
30
{
f
.
Close
()
t
.
Fatalf
(
"expected %d items, got %d"
,
0
,
f
.
items
)
t
.
Fatalf
(
"expected %d items, got %d"
,
0
,
f
.
items
.
Load
()
)
}
for
y
:=
byte
(
0
);
y
<
30
;
y
++
{
f
.
Retrieve
(
uint64
(
y
))
...
...
@@ -1210,13 +1209,13 @@ func runRandTest(rt randTest) bool {
rt
[
i
]
.
err
=
fmt
.
Errorf
(
"failed to reload table %v"
,
err
)
}
case
opCheckAll
:
tail
:=
atomic
.
LoadUint64
(
&
f
.
itemHidden
)
head
:=
atomic
.
LoadUint64
(
&
f
.
items
)
tail
:=
f
.
itemHidden
.
Load
(
)
head
:=
f
.
items
.
Load
(
)
if
tail
==
head
{
continue
}
got
,
err
:=
f
.
RetrieveItems
(
atomic
.
LoadUint64
(
&
f
.
itemHidden
),
head
-
tail
,
100000
)
got
,
err
:=
f
.
RetrieveItems
(
f
.
itemHidden
.
Load
(
),
head
-
tail
,
100000
)
if
err
!=
nil
{
rt
[
i
]
.
err
=
err
}
else
{
...
...
@@ -1238,7 +1237,7 @@ func runRandTest(rt randTest) bool {
if
len
(
step
.
items
)
==
0
{
continue
}
tail
:=
atomic
.
LoadUint64
(
&
f
.
itemHidden
)
tail
:=
f
.
itemHidden
.
Load
(
)
for
i
:=
0
;
i
<
len
(
step
.
items
);
i
++
{
blobs
=
append
(
blobs
,
values
[
step
.
items
[
i
]
-
tail
])
}
...
...
@@ -1254,7 +1253,7 @@ func runRandTest(rt randTest) bool {
case
opTruncateHead
:
f
.
truncateHead
(
step
.
target
)
length
:=
atomic
.
LoadUint64
(
&
f
.
items
)
-
atomic
.
LoadUint64
(
&
f
.
itemHidden
)
length
:=
f
.
items
.
Load
()
-
f
.
itemHidden
.
Load
(
)
values
=
values
[
:
length
]
case
opTruncateHeadAll
:
...
...
@@ -1262,10 +1261,10 @@ func runRandTest(rt randTest) bool {
values
=
nil
case
opTruncateTail
:
prev
:=
atomic
.
LoadUint64
(
&
f
.
itemHidden
)
prev
:=
f
.
itemHidden
.
Load
(
)
f
.
truncateTail
(
step
.
target
)
truncated
:=
atomic
.
LoadUint64
(
&
f
.
itemHidden
)
-
prev
truncated
:=
f
.
itemHidden
.
Load
(
)
-
prev
values
=
values
[
truncated
:
]
case
opTruncateTailAll
:
...
...
core/rawdb/freezer_test.go
View file @
905a723f
...
...
@@ -267,10 +267,10 @@ func TestFreezerReadonlyValidate(t *testing.T) {
bBatch
:=
f
.
tables
[
"b"
]
.
newBatch
()
require
.
NoError
(
t
,
bBatch
.
AppendRaw
(
0
,
item
))
require
.
NoError
(
t
,
bBatch
.
commit
())
if
f
.
tables
[
"a"
]
.
items
!=
3
{
if
f
.
tables
[
"a"
]
.
items
.
Load
()
!=
3
{
t
.
Fatalf
(
"unexpected number of items in table"
)
}
if
f
.
tables
[
"b"
]
.
items
!=
1
{
if
f
.
tables
[
"b"
]
.
items
.
Load
()
!=
1
{
t
.
Fatalf
(
"unexpected number of items in table"
)
}
require
.
NoError
(
t
,
f
.
Close
())
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment