@@ -17,6 +17,17 @@ type Batch struct {
17
17
batch * pebble.Batch
18
18
version uint64
19
19
sync bool
20
+ size int
21
+ }
22
+
23
+ const (
24
+ oneIf64Bit = ^ uint (0 ) >> 63
25
+ maxUint32OrInt = (1 << 31 )<< oneIf64Bit - 1
26
+ maxVarintLen32 = 5
27
+ )
28
+
29
+ func keyValueSize (key , value []byte ) int {
30
+ return len (key ) + len (value ) + 1 + 2 * maxVarintLen32
20
31
}
21
32
22
33
func NewBatch (storage * pebble.DB , version uint64 , sync bool ) (* Batch , error ) {
@@ -34,6 +45,7 @@ func NewBatch(storage *pebble.DB, version uint64, sync bool) (*Batch, error) {
34
45
batch : batch ,
35
46
version : version ,
36
47
sync : sync ,
48
+ size : keyValueSize ([]byte (latestVersionKey ), versionBz [:]),
37
49
}, nil
38
50
}
39
51
@@ -50,9 +62,20 @@ func (b *Batch) set(storeKey []byte, tombstone uint64, key, value []byte) error
50
62
prefixedKey := MVCCEncode (prependStoreKey (storeKey , key ), b .version )
51
63
prefixedVal := MVCCEncode (value , tombstone )
52
64
65
+ size := keyValueSize (prefixedKey , prefixedVal )
66
+ if b .size + size > maxUint32OrInt {
67
+ // 4 GB is huge, probably genesis; flush and reset
68
+ if err := b .batch .Commit (& pebble.WriteOptions {Sync : b .sync }); err != nil {
69
+ return fmt .Errorf ("max batch size exceed: failed to write PebbleDB batch: %w" , err )
70
+ }
71
+ b .batch .Reset ()
72
+ b .size = 0
73
+ }
74
+
53
75
if err := b .batch .Set (prefixedKey , prefixedVal , nil ); err != nil {
54
76
return fmt .Errorf ("failed to write PebbleDB batch: %w" , err )
55
77
}
78
+ b .size += size
56
79
57
80
return nil
58
81
}
0 commit comments