Skip to content

Commit 15de490

Browse files
Fenchao Dumeta-codesync[bot]
authored andcommitted
Refactor GenericPieces to inherit from GenericPiecesBase
Summary: **Context** Multi range support requires same piecewise logic but the request can contain non-contiguous ranges. Refactor `GenericPieces`, so that we can implement a "multi range" piece iteration class based on `GenericPiecesBase`. **Change** - Isolate the generic piece related variables / methods into a base class `GenericPiecesBase`. - Keep request and piece iteration related logic within `GenericPieces`. Reviewed By: tang-jianfeng Differential Revision: D88178507 fbshipit-source-id: 96b306739d44995bae098bd960572dd2fd1adcc7
1 parent 8ea534a commit 15de490

File tree

4 files changed

+226
-146
lines changed

4 files changed

+226
-146
lines changed

cachelib/common/piecewise/GenericPieces.cpp

Lines changed: 5 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,8 @@
1616

1717
#include "cachelib/common/piecewise/GenericPieces.h"
1818

19-
#include <folly/Conv.h>
20-
#include <folly/String.h>
2119
#include <folly/logging/xlog.h>
2220

23-
#include <vector>
24-
2521
namespace facebook {
2622
namespace cachelib {
2723

@@ -30,20 +26,11 @@ GenericPieces::GenericPieces(const std::string& baseKey,
3026
uint64_t piecesPerGroup,
3127
uint64_t fullBodyLen,
3228
const RequestRange* range)
33-
: baseKey_(baseKey),
34-
pieceSize_(pieceSize),
35-
numPiecesPerGroup_(piecesPerGroup),
36-
fullBodyLen_(fullBodyLen) {
37-
XCHECK(fullBodyLen > 0);
38-
39-
numPiecesTotal_ = calculateNumPiecesTotal(fullBodyLen_, pieceSize_);
40-
41-
// Figure out the first and last bytes/pieces we need to fetch
42-
requestedStartByte_ = 0;
43-
requestedEndByte_ = fullBodyLen_ - 1;
44-
startPieceIndex_ = 0;
45-
endPieceIndex_ = numPiecesTotal_ - 1;
46-
29+
: GenericPiecesBase(baseKey, pieceSize, piecesPerGroup, fullBodyLen),
30+
requestedStartByte_{0},
31+
requestedEndByte_{fullBodyLen - 1},
32+
startPieceIndex_{0},
33+
endPieceIndex_{numPiecesTotal_ - 1} {
4734
if (range) {
4835
resetFromRequestRange(*range);
4936
}
@@ -70,65 +57,10 @@ void GenericPieces::resetFromRequestRange(const RequestRange& range) {
7057
firstByteOffsetToFetch_ = startPieceIndex_ * pieceSize_;
7158
}
7259

73-
std::string GenericPieces::escapeCacheKey(const std::string& key) {
74-
std::vector<folly::StringPiece> parts;
75-
folly::split(kCachePieceSeparator, key, parts);
76-
if (parts.size() == 1) {
77-
return key;
78-
}
79-
std::string escapeSeparator =
80-
folly::to<std::string>(kCachePieceSeparator, kCachePieceSeparator);
81-
82-
std::string ret;
83-
folly::join(escapeSeparator, parts, ret);
84-
return ret;
85-
}
86-
8760
uint64_t GenericPieces::getTargetNumPieces() const {
8861
XDCHECK_GE(endPieceIndex_, startPieceIndex_);
8962
return (endPieceIndex_ - startPieceIndex_) + 1;
9063
}
9164

92-
std::string GenericPieces::createPieceHeaderKey(const std::string& baseKey,
93-
uint64_t versionID) {
94-
return folly::to<std::string>(
95-
baseKey, kCachePieceSeparator, "header-", versionID);
96-
}
97-
98-
std::string GenericPieces::createPieceKey(const std::string& baseKey,
99-
size_t pieceNum,
100-
uint64_t piecesPerGroup,
101-
uint64_t versionID) {
102-
uint64_t groupNum = 0;
103-
if (piecesPerGroup > 0) {
104-
groupNum = pieceNum / piecesPerGroup;
105-
}
106-
if (groupNum == 0) {
107-
return folly::to<std::string>(
108-
baseKey, kCachePieceSeparator, "body-", versionID, "-", pieceNum);
109-
} else {
110-
return folly::to<std::string>(baseKey,
111-
kCacheGroupSeparator,
112-
groupNum,
113-
kCachePieceSeparator,
114-
"body-",
115-
versionID,
116-
"-",
117-
pieceNum);
118-
}
119-
}
120-
121-
folly::StringPiece GenericPieces::getBaseKey(folly::StringPiece key) {
122-
auto found = key.find(kCacheGroupSeparator);
123-
if (found == folly::StringPiece::npos) {
124-
found = key.find(kCachePieceSeparator);
125-
}
126-
127-
if (found != folly::StringPiece::npos) {
128-
return key.subpiece(0, found);
129-
}
130-
return key;
131-
}
132-
13365
} // namespace cachelib
13466
} // namespace facebook

cachelib/common/piecewise/GenericPieces.h

Lines changed: 4 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,22 @@
1616

1717
#pragma once
1818

19-
#include <folly/io/IOBuf.h>
20-
#include <folly/json/dynamic.h>
2119
#include <folly/logging/xlog.h>
2220

23-
#include <memory>
2421
#include <string>
25-
#include <unordered_map>
2622

23+
#include "cachelib/common/piecewise/GenericPiecesBase.h"
2724
#include "cachelib/common/piecewise/RequestRange.h"
2825

2926
namespace facebook {
3027
namespace cachelib {
3128

32-
const std::string kCacheGroupSeparator = "|@|";
33-
const std::string kCachePieceSeparator = "|#|";
34-
3529
/**
3630
* A content can be split and stored in multiple pieces in cache. The class
3731
* provides the utility to map content object to pieces.
3832
*
3933
*/
40-
class GenericPieces {
34+
class GenericPieces : public GenericPiecesBase {
4135
public:
4236
/**
4337
* @param baseKey: base key of the request. we will generate piece key from
@@ -57,12 +51,6 @@ class GenericPieces {
5751

5852
void resetFromRequestRange(const RequestRange& range);
5953

60-
/**
61-
* We fetch one piece at a time and keep track of that piece
62-
* number here.
63-
*/
64-
uint64_t getCurFetchingPieceIndex() const { return curFetchingPieceIndex_; }
65-
6654
bool morePiecesToFetch() const {
6755
return curFetchingPieceIndex_ < endPieceIndex_;
6856
}
@@ -92,9 +80,6 @@ class GenericPieces {
9280
return getLastByteOffsetOfLastPiece() - getFirstByteOffsetOfCurPiece() + 1;
9381
}
9482

95-
uint64_t getPieceSize() const { return pieceSize_; }
96-
uint64_t getPiecesPerGroup() const { return numPiecesPerGroup_; }
97-
9883
bool isPieceWithinBound(uint64_t pieceIndex) const {
9984
return pieceIndex <= endPieceIndex_;
10085
}
@@ -143,18 +128,11 @@ class GenericPieces {
143128
return (requestedEndByte_ - requestedStartByte_ + 1);
144129
}
145130

146-
/**
147-
* Returns the body-length of the *full* blob (e.g. if there is a
148-
* 1000000-byte blob and 6400 bytes are requested in a range request, this
149-
* will still return 1000000)
150-
*/
151-
uint64_t getFullBodyLength() const { return fullBodyLen_; }
152131
uint64_t getStartPieceIndex() const { return startPieceIndex_; }
153132
[[nodiscard]] uint64_t getStartPieceOffset() const {
154133
return startPieceIndex_ * pieceSize_;
155134
}
156135
uint64_t getEndPieceIndex() const { return endPieceIndex_; }
157-
uint64_t getNumPiecesTotal() const { return numPiecesTotal_; }
158136
uint64_t getRequestedStartByte() const { return requestedStartByte_; }
159137
uint64_t getRequestedEndByte() const { return requestedEndByte_; }
160138
uint64_t getFirstByteOffsetToFetch() const { return firstByteOffsetToFetch_; }
@@ -164,61 +142,14 @@ class GenericPieces {
164142
*/
165143
uint64_t getTargetNumPieces() const;
166144

167-
/**
168-
* We use "|#|" as the separator between the actual cachekey and meta
169-
* key information (Is it a header? Is it a piece? Which piece?) So
170-
* we want to make sure this separator is escaped in the main key. Do this
171-
* by doubling it whenever we see it. If we ever see the single separator
172-
* string by itself, we know it's actually the separator.
173-
*/
174-
static std::string escapeCacheKey(const std::string& key);
175-
176-
/**
177-
* Get the basekey from the given pieceKey (full key). The returned value
178-
* shares the same lifetime as the passed in pieceKey.
179-
*/
180-
static folly::StringPiece getBaseKey(folly::StringPiece pieceKey);
181-
182-
/**
183-
* @param versionID: unique identifer of the content's version, e.g.,
184-
* hash of the content.
185-
*/
186-
static std::string createPieceHeaderKey(const std::string& baseKey,
187-
uint64_t versionID = 0);
188-
189-
/**
190-
* Keys used to store each piece of the response. We include the pieceSize
191-
* in the key in case we change pieceSize at some point, so we can
192-
* distinguish between the different values.
193-
*/
194-
static std::string createPieceKey(const std::string& baseKey,
195-
size_t pieceNum,
196-
uint64_t piecesPerGroup,
197-
uint64_t versionID = 0);
198-
199-
static uint64_t calculateNumPiecesTotal(const uint64_t fullBodyLen,
200-
const uint64_t pieceSize) {
201-
return ((fullBodyLen - 1) / pieceSize) + 1;
202-
}
203-
204145
protected:
205-
std::string baseKey_;
206-
uint64_t pieceSize_;
207-
uint64_t numPiecesPerGroup_;
208-
uint64_t fullBodyLen_;
209-
210-
uint64_t curFetchingPieceIndex_;
211-
212-
// Calculated values
213-
// Total number of pieces for the full content
214-
uint64_t numPiecesTotal_;
215146
// Start byte of the request content (or range)
216147
uint64_t requestedStartByte_;
217148
// End byte of the request content (or range)
218149
uint64_t requestedEndByte_;
219-
// Start piece index of he request content (or range)
150+
// Start piece index of the request content (or range)
220151
uint64_t startPieceIndex_;
221-
// End piece index of he request content (or range)
152+
// End piece index of the request content (or range)
222153
uint64_t endPieceIndex_;
223154
// Starting byte offset of the first piece
224155
uint64_t firstByteOffsetToFetch_;
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "cachelib/common/piecewise/GenericPiecesBase.h"
18+
19+
#include <folly/Conv.h>
20+
#include <folly/String.h>
21+
#include <folly/logging/xlog.h>
22+
23+
#include <vector>
24+
25+
namespace facebook {
26+
namespace cachelib {
27+
28+
const std::string kCacheGroupSeparator = "|@|";
29+
const std::string kCachePieceSeparator = "|#|";
30+
31+
GenericPiecesBase::GenericPiecesBase(const std::string& baseKey,
32+
uint64_t pieceSize,
33+
uint64_t piecesPerGroup,
34+
uint64_t fullBodyLen)
35+
: baseKey_{baseKey},
36+
pieceSize_{pieceSize},
37+
numPiecesPerGroup_{piecesPerGroup},
38+
fullBodyLen_{fullBodyLen} {
39+
XCHECK(fullBodyLen > 0);
40+
numPiecesTotal_ = calculateNumPiecesTotal(fullBodyLen_, pieceSize_);
41+
}
42+
43+
std::string GenericPiecesBase::escapeCacheKey(const std::string& key) {
44+
std::vector<folly::StringPiece> parts;
45+
folly::split(kCachePieceSeparator, key, parts);
46+
if (parts.size() == 1) {
47+
return key;
48+
}
49+
std::string escapeSeparator =
50+
folly::to<std::string>(kCachePieceSeparator, kCachePieceSeparator);
51+
52+
std::string ret;
53+
folly::join(escapeSeparator, parts, ret);
54+
return ret;
55+
}
56+
57+
std::string GenericPiecesBase::createPieceHeaderKey(const std::string& baseKey,
58+
uint64_t versionID) {
59+
return folly::to<std::string>(
60+
baseKey, kCachePieceSeparator, "header-", versionID);
61+
}
62+
63+
std::string GenericPiecesBase::createPieceKey(const std::string& baseKey,
64+
size_t pieceNum,
65+
uint64_t piecesPerGroup,
66+
uint64_t versionID) {
67+
uint64_t groupNum = 0;
68+
if (piecesPerGroup > 0) {
69+
groupNum = pieceNum / piecesPerGroup;
70+
}
71+
if (groupNum == 0) {
72+
return folly::to<std::string>(
73+
baseKey, kCachePieceSeparator, "body-", versionID, "-", pieceNum);
74+
} else {
75+
return folly::to<std::string>(baseKey,
76+
kCacheGroupSeparator,
77+
groupNum,
78+
kCachePieceSeparator,
79+
"body-",
80+
versionID,
81+
"-",
82+
pieceNum);
83+
}
84+
}
85+
86+
folly::StringPiece GenericPiecesBase::getBaseKey(folly::StringPiece key) {
87+
auto found = key.find(kCacheGroupSeparator);
88+
if (found == folly::StringPiece::npos) {
89+
found = key.find(kCachePieceSeparator);
90+
}
91+
92+
if (found != folly::StringPiece::npos) {
93+
return key.subpiece(0, found);
94+
}
95+
return key;
96+
}
97+
98+
} // namespace cachelib
99+
} // namespace facebook

0 commit comments

Comments
 (0)