Skip to content

Commit 211c7e0

Browse files
committed
Add helpers to extract CONTRACT_CODE entries efficiently from BL.
1 parent 036c3fc commit 211c7e0

10 files changed

+129
-0
lines changed

Diff for: src/bucket/BucketSnapshot.cpp

+37
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,43 @@ LiveBucketSnapshot::scanForEviction(
313313
return Loop::INCOMPLETE;
314314
}
315315

316+
// Scans contract code entries in the bucket.
317+
Loop
318+
LiveBucketSnapshot::scanForContractCode(
319+
std::function<Loop(BucketEntry const&)> callback) const
320+
{
321+
ZoneScoped;
322+
if (isEmpty())
323+
{
324+
return Loop::INCOMPLETE;
325+
}
326+
327+
auto range = mBucket->getContractCodeRange();
328+
if (!range)
329+
{
330+
return Loop::INCOMPLETE;
331+
}
332+
333+
auto& stream = getStream();
334+
stream.seek(range->first);
335+
336+
BucketEntry be;
337+
while (stream.pos() < range->second && stream.readOne(be))
338+
{
339+
340+
if (((be.type() == LIVEENTRY || be.type() == INITENTRY) &&
341+
be.liveEntry().data.type() == CONTRACT_CODE) ||
342+
(be.type() == DEADENTRY && be.deadEntry().type() == CONTRACT_CODE))
343+
{
344+
if (callback(be) == Loop::COMPLETE)
345+
{
346+
return Loop::COMPLETE;
347+
}
348+
}
349+
}
350+
return Loop::INCOMPLETE;
351+
}
352+
316353
template <class BucketT>
317354
XDRInputFileStream&
318355
BucketSnapshotBase<BucketT>::getStream() const

Diff for: src/bucket/BucketSnapshot.h

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ class LiveBucketSnapshot : public BucketSnapshotBase<LiveBucket>
8787
std::list<EvictionResultEntry>& evictableKeys,
8888
SearchableLiveBucketListSnapshot const& bl,
8989
uint32_t ledgerVers) const;
90+
91+
// Scans contract code entries in the bucket.
92+
Loop
93+
scanForContractCode(std::function<Loop(BucketEntry const&)> callback) const;
9094
};
9195

9296
class HotArchiveBucketSnapshot : public BucketSnapshotBase<HotArchiveBucket>

Diff for: src/bucket/InMemoryIndex.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ InMemoryIndex::InMemoryIndex(BucketManager const& bm,
5959
std::streamoff lastOffset = 0;
6060
std::optional<std::streamoff> firstOffer;
6161
std::optional<std::streamoff> lastOffer;
62+
std::optional<std::streamoff> firstContractCode;
63+
std::optional<std::streamoff> lastContractCode;
6264

6365
while (in && in.readOne(be))
6466
{
@@ -108,6 +110,16 @@ InMemoryIndex::InMemoryIndex(BucketManager const& bm,
108110
lastOffer = lastOffset;
109111
}
110112

113+
// Populate contractCodeRange
114+
if (!firstContractCode && lk.type() == CONTRACT_CODE)
115+
{
116+
firstContractCode = lastOffset;
117+
}
118+
if (!lastContractCode && lk.type() > CONTRACT_CODE)
119+
{
120+
lastContractCode = lastOffset;
121+
}
122+
111123
lastOffset = in.pos();
112124
}
113125

@@ -129,5 +141,24 @@ InMemoryIndex::InMemoryIndex(BucketManager const& bm,
129141
{
130142
mOfferRange = std::nullopt;
131143
}
144+
145+
if (firstContractCode)
146+
{
147+
if (lastContractCode)
148+
{
149+
mContractCodeRange = {*firstContractCode, *lastContractCode};
150+
}
151+
// If we didn't see any entries after contract code, then the upper
152+
// bound is EOF
153+
else
154+
{
155+
mContractCodeRange = {*firstContractCode,
156+
std::numeric_limits<std::streamoff>::max()};
157+
}
158+
}
159+
else
160+
{
161+
mContractCodeRange = std::nullopt;
162+
}
132163
}
133164
}

Diff for: src/bucket/InMemoryIndex.h

+7
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class InMemoryIndex
6161
AssetPoolIDMap mAssetPoolIDMap;
6262
BucketEntryCounters mCounters{};
6363
std::optional<std::pair<std::streamoff, std::streamoff>> mOfferRange;
64+
std::optional<std::pair<std::streamoff, std::streamoff>> mContractCodeRange;
6465

6566
public:
6667
using IterT = InMemoryBucketState::IterT;
@@ -103,6 +104,12 @@ class InMemoryIndex
103104
return mOfferRange;
104105
}
105106

107+
std::optional<std::pair<std::streamoff, std::streamoff>>
108+
getContractCodeRange() const
109+
{
110+
return mContractCodeRange;
111+
}
112+
106113
#ifdef BUILD_TESTS
107114
bool
108115
operator==(InMemoryIndex const& in) const

Diff for: src/bucket/LiveBucket.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,12 @@ LiveBucket::getOfferRange() const
316316
return getIndex().getOfferRange();
317317
}
318318

319+
std::optional<std::pair<std::streamoff, std::streamoff>>
320+
LiveBucket::getContractCodeRange() const
321+
{
322+
return getIndex().getContractCodeRange();
323+
}
324+
319325
std::vector<BucketEntry>
320326
LiveBucket::convertToBucketEntry(bool useInit,
321327
std::vector<LedgerEntry> const& initEntries,

Diff for: src/bucket/LiveBucket.h

+5
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ class LiveBucket : public BucketBase<LiveBucket, LiveBucketIndex>,
9090
std::optional<std::pair<std::streamoff, std::streamoff>>
9191
getOfferRange() const;
9292

93+
// Returns [lowerBound, upperBound) of file offsets for all contract code
94+
// entries in the bucket, or std::nullopt if no contract code exists
95+
std::optional<std::pair<std::streamoff, std::streamoff>>
96+
getContractCodeRange() const;
97+
9398
// Create a fresh bucket from given vectors of init (created) and live
9499
// (updated) LedgerEntries, and dead LedgerEntryKeys. The bucket will
95100
// be sorted, hashed, and adopted in the provided BucketManager.

Diff for: src/bucket/LiveBucketIndex.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,27 @@ LiveBucketIndex::getOfferRange() const
183183
return mInMemoryIndex->getOfferRange();
184184
}
185185

186+
std::optional<std::pair<std::streamoff, std::streamoff>>
187+
LiveBucketIndex::getContractCodeRange() const
188+
{
189+
if (mDiskIndex)
190+
{
191+
// Get the smallest and largest possible contract code keys
192+
LedgerKey lowerBound(CONTRACT_CODE);
193+
lowerBound.contractCode().hash.fill(
194+
std::numeric_limits<uint8_t>::min());
195+
196+
LedgerKey upperBound(CONTRACT_CODE);
197+
upperBound.contractCode().hash.fill(
198+
std::numeric_limits<uint8_t>::max());
199+
200+
return mDiskIndex->getOffsetBounds(lowerBound, upperBound);
201+
}
202+
203+
releaseAssertOrThrow(mInMemoryIndex);
204+
return mInMemoryIndex->getContractCodeRange();
205+
}
206+
186207
uint32_t
187208
LiveBucketIndex::getPageSize() const
188209
{

Diff for: src/bucket/LiveBucketIndex.h

+3
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ class LiveBucketIndex : public NonMovableOrCopyable
9797
std::optional<std::pair<std::streamoff, std::streamoff>>
9898
getOfferRange() const;
9999

100+
std::optional<std::pair<std::streamoff, std::streamoff>>
101+
getContractCodeRange() const;
102+
100103
BucketEntryCounters const& getBucketEntryCounters() const;
101104
uint32_t getPageSize() const;
102105

Diff for: src/bucket/SearchableBucketList.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ SearchableLiveBucketListSnapshot::scanForEviction(
6464
return result;
6565
}
6666

67+
void
68+
SearchableLiveBucketListSnapshot::scanForContractCode(
69+
std::function<Loop(BucketEntry const&)> callback) const
70+
{
71+
ZoneScoped;
72+
releaseAssert(mSnapshot);
73+
auto f = [&callback](auto const& b) {
74+
return b.scanForContractCode(callback);
75+
};
76+
loopAllBuckets(f, *mSnapshot);
77+
}
78+
6779
template <class BucketT>
6880
std::optional<std::vector<typename BucketT::LoadT>>
6981
SearchableBucketListSnapshotBase<BucketT>::loadKeysInternal(

Diff for: src/bucket/SearchableBucketList.h

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class SearchableLiveBucketListSnapshot
3535
std::shared_ptr<EvictionStatistics> stats,
3636
StateArchivalSettings const& sas, uint32_t ledgerVers) const;
3737

38+
void
39+
scanForContractCode(std::function<Loop(BucketEntry const&)> callback) const;
40+
3841
friend SearchableSnapshotConstPtr
3942
BucketSnapshotManager::copySearchableLiveBucketListSnapshot() const;
4043
};

0 commit comments

Comments
 (0)