Skip to content

Commit 9ffc30d

Browse files
committed
add assert for no_space_error info
1 parent 1130335 commit 9ffc30d

File tree

4 files changed

+164
-95
lines changed

4 files changed

+164
-95
lines changed

src/lib/homestore_backend/gc_manager.cpp

Lines changed: 131 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -205,79 +205,139 @@ void GCManager::pdev_gc_actor::handle_recovered_gc_task(const GCManager::gc_task
205205

206206
void GCManager::pdev_gc_actor::switch_chunks_after_data_copy(chunk_id_t move_from_chunk, chunk_id_t move_to_chunk,
207207
uint8_t priority) {
208-
// // 1 get all blob index from gc index table
209-
// std::vector< std::pair< BlobRouteByChunkKey, BlobRouteValue > > out_vector;
210-
// auto start_key = BlobRouteByChunkKey{BlobRouteByChunk(move_to_chunk, 0, 0)};
211-
// auto end_key = BlobRouteByChunkKey{BlobRouteByChunk{move_to_chunk, std::numeric_limits< uint64_t >::max(),
212-
// std::numeric_limits< uint64_t >::max()}};
213-
// homestore::BtreeQueryRequest< BlobRouteByChunkKey > query_req{homestore::BtreeKeyRange< BlobRouteByChunkKey >{
214-
// std::move(start_key), true /* inclusive */, std::move(end_key), true /* inclusive */
215-
// }};
216-
217-
// auto const ret = m_index_table->query(query_req, out_vector);
218-
// if (ret != homestore::btree_status_t::success) {
219-
// // "ret != homestore::btree_status_t::has_more" is not expetced here, since we are querying all the pbas in
220-
// one
221-
// // time.
222-
// // TODO:: handle the error case here.
223-
// RELEASE_ASSERT(false, "Failed to query blobs in index table for ret={} move_to_chunk={}", ret,
224-
// move_to_chunk);
225-
// }
226-
227-
// // 2 get pg index table
228-
// auto move_from_vchunk = m_chunk_selector->get_extend_vchunk(move_from_chunk);
229-
// RELEASE_ASSERT(move_from_vchunk->m_pg_id.has_value(), "chunk_id={} is expected to belong to a pg, but not!",
230-
// move_from_chunk);
231-
// auto pg_id = move_from_vchunk->m_pg_id.value();
232-
// auto hs_pg = m_hs_home_object->get_hs_pg(pg_id);
233-
// RELEASE_ASSERT(hs_pg, "Unknown PG for pg_id={}", pg_id);
234-
// auto pg_index_table = hs_pg->index_table_;
235-
// RELEASE_ASSERT(pg_index_table, "Index table not found for PG pg_id={}", pg_id);
236-
237-
// // 3 update pg index table according to the query result of gc index table.
238-
// // BtreeRangePutRequest only support update a range of keys to the same value, so we need to update the pg
239-
// // indextable here one by one. since the update of index table is very fast , and gc is not time sensitive, so
240-
// // for now we do this sequentially.
241-
// // TODO:: concurrently update pg index table if necessary
242-
243-
// for (const auto& [k, v] : out_vector) {
244-
// BlobRouteKey index_key{BlobRoute{k.key().shard, k.key().blob}};
245-
246-
// homestore::BtreeSinglePutRequest update_req{
247-
// &index_key, &v, homestore::btree_put_type::UPDATE, nullptr,
248-
// [](homestore::BtreeKey const& key, homestore::BtreeValue const& value_in_btree,
249-
// homestore::BtreeValue const& new_value) -> homestore::put_filter_decision {
250-
// BlobRouteValue existing_value{value_in_btree};
251-
// if (existing_value.pbas() == HSHomeObject::tombstone_pbas) {
252-
// // if the blob has been deleted and the value is tombstone,
253-
// // we should not use a valid pba to update a tombstone.
254-
// return homestore::put_filter_decision::keep;
255-
// }
256-
// return homestore::put_filter_decision::replace;
257-
// }};
258-
259-
// auto status = pg_index_table->put(update_req);
260-
// if (status != homestore::btree_status_t::success && status != homestore::btree_status_t::filtered_out) {
261-
// // TODO:: handle the error case here.
262-
// RELEASE_ASSERT(false, "can not update pg index table, pg_id={}, move_from_chunk_id={}", pg_id,
263-
// move_from_chunk);
264-
// }
265-
// }
266-
267-
// // 4 change the pg_id and vchunk_id of the move_to_chunk according to move_to_chunk
268-
// auto move_to_vchunk = m_chunk_selector->get_extend_vchunk(move_to_chunk);
269-
// move_to_vchunk->m_pg_id = move_from_vchunk->m_pg_id;
270-
// move_to_vchunk->m_v_chunk_id = move_from_vchunk->m_v_chunk_id;
271-
// move_to_vchunk->m_state =
272-
// priority == static_cast< uint8_t >(TASK_PRIORITY::NORMAL) ? ChunkState::AVAILABLE : ChunkState::INUSE;
273-
274-
// // 5 push the move_from_chunk to the reserved chunk queue and the move_to_chunk to the pg heap.
275-
// // 6 update the reserved chunk of this gc actor, metablk
276-
// // 7 update the chunk list of pg, metablk
208+
// 1 get all blob index from gc index table
209+
std::vector< std::pair< BlobRouteByChunkKey, BlobRouteValue > > out_vector;
210+
auto start_key = BlobRouteByChunkKey{BlobRouteByChunk(move_to_chunk, 0, 0)};
211+
auto end_key = BlobRouteByChunkKey{BlobRouteByChunk{move_to_chunk, std::numeric_limits< uint64_t >::max(),
212+
std::numeric_limits< uint64_t >::max()}};
213+
homestore::BtreeQueryRequest< BlobRouteByChunkKey > query_req{homestore::BtreeKeyRange< BlobRouteByChunkKey >{
214+
std::move(start_key), true /* inclusive */, std::move(end_key), true /* inclusive */
215+
}};
216+
217+
auto const ret = m_index_table->query(query_req, out_vector);
218+
if (ret != homestore::btree_status_t::success) {
219+
// "ret != homestore::btree_status_t::has_more" is not expetced here, since we are querying all the pbas in one
220+
// time.
221+
// TODO:: handle the error case here.
222+
RELEASE_ASSERT(false, "Failed to query blobs in index table for ret={} move_to_chunk={}", ret, move_to_chunk);
223+
}
224+
225+
// 2 get pg index table
226+
auto move_from_vchunk = m_chunk_selector->get_extend_vchunk(move_from_chunk);
227+
RELEASE_ASSERT(move_from_vchunk->m_pg_id.has_value(), "chunk_id={} is expected to belong to a pg, but not!",
228+
move_from_chunk);
229+
auto pg_id = move_from_vchunk->m_pg_id.value();
230+
auto hs_pg = m_hs_home_object->get_hs_pg(pg_id);
231+
RELEASE_ASSERT(hs_pg, "Unknown PG for pg_id={}", pg_id);
232+
auto pg_index_table = hs_pg->index_table_;
233+
RELEASE_ASSERT(pg_index_table, "Index table not found for PG pg_id={}", pg_id);
234+
235+
// 3 update pg index table according to the query result of gc index table.
236+
// BtreeRangePutRequest only support update a range of keys to the same value, so we need to update the pg
237+
// indextable here one by one. since the update of index table is very fast , and gc is not time sensitive, so
238+
// for now we do this sequentially.
239+
// TODO:: concurrently update pg index table if necessary
240+
241+
for (const auto& [k, v] : out_vector) {
242+
BlobRouteKey index_key{BlobRoute{k.key().shard, k.key().blob}};
243+
244+
homestore::BtreeSinglePutRequest update_req{
245+
&index_key, &v, homestore::btree_put_type::UPDATE, nullptr,
246+
[](homestore::BtreeKey const& key, homestore::BtreeValue const& value_in_btree,
247+
homestore::BtreeValue const& new_value) -> homestore::put_filter_decision {
248+
BlobRouteValue existing_value{value_in_btree};
249+
if (existing_value.pbas() == HSHomeObject::tombstone_pbas) {
250+
// if the blob has been deleted and the value is tombstone,
251+
// we should not use a valid pba to update a tombstone.
252+
return homestore::put_filter_decision::keep;
253+
}
254+
return homestore::put_filter_decision::replace;
255+
}};
256+
257+
auto status = pg_index_table->put(update_req);
258+
if (status != homestore::btree_status_t::success && status != homestore::btree_status_t::filtered_out) {
259+
// TODO:: handle the error case here.
260+
RELEASE_ASSERT(false, "can not update pg index table, pg_id={}, move_from_chunk_id={}", pg_id,
261+
move_from_chunk);
262+
}
263+
}
264+
265+
// 4 change the pg_id and vchunk_id of the move_to_chunk according to move_to_chunk
266+
auto move_to_vchunk = m_chunk_selector->get_extend_vchunk(move_to_chunk);
267+
move_to_vchunk->m_pg_id = move_from_vchunk->m_pg_id;
268+
move_to_vchunk->m_v_chunk_id = move_from_vchunk->m_v_chunk_id;
269+
move_to_vchunk->m_state =
270+
priority == static_cast< uint8_t >(TASK_PRIORITY::NORMAL) ? ChunkState::AVAILABLE : ChunkState::INUSE;
271+
272+
// TODO:
273+
// 5 push the move_from_chunk to the reserved chunk queue and the move_to_chunk to the pg heap.
274+
// 6 update the reserved chunk of this gc actor, metablk
275+
// 7 update the chunk list of pg, metablk
276+
// 8 change chunk->shard list map
277277
}
278278

279-
void GCManager::pdev_gc_actor::copy_valid_data(chunk_id_t move_from_chunk, chunk_id_t move_to_chunk) {
280-
// TODO:: implement the data copy logic here.
279+
bool GCManager::pdev_gc_actor::copy_valid_data(chunk_id_t move_from_chunk, chunk_id_t move_to_chunk) {
280+
auto move_to_chunk_total_blks = m_chunk_selector->get_extend_vchunk(move_to_chunk)->get_total_blks();
281+
auto move_to_chunk_available_blks = m_chunk_selector->get_extend_vchunk(move_to_chunk)->available_blks();
282+
RELEASE_ASSERT(move_to_chunk_total_blks == move_to_chunk_available_blks,
283+
"move_from_chunk should be empty, total_blks={}, available_blks={}, move_to_chunk_id={}",
284+
move_to_chunk_total_blks, move_to_chunk_available_blks, move_to_chunk);
285+
286+
auto shards = m_hs_home_object->get_shards_in_chunk(move_from_chunk);
287+
auto& data_service = homestore::data_service();
288+
289+
for (const auto& shard : shards) {
290+
std::vector< std::pair< BlobRouteKey, BlobRouteValue > > out_vector;
291+
auto start_key = BlobRouteKey{BlobRoute{shard_id, std::numeric_limits< uint64_t >::min()}};
292+
auto end_key = BlobRouteKey{BlobRoute{shard_id, std::numeric_limits< uint64_t >::max()}};
293+
homestore::BtreeQueryRequest< BlobRouteKey > query_req{
294+
homestore::BtreeKeyRange< BlobRouteKey >{std::move(start_key), true /* inclusive */, std::move(end_key),
295+
true /* inclusive */},
296+
homestore::BtreeQueryType::SWEEP_NON_INTRUSIVE_PAGINATION_QUERY, static_cast< uint32_t >(max_num_in_batch)};
297+
auto const status = m_index_table->query(query_req, out_vector);
298+
if (ret != homestore::btree_status_t::success && ret != homestore::btree_status_t::has_more) {
299+
LOGE("Failed to query blobs in index table for ret={} shard={} start_blob_id={}", ret, shard_id,
300+
start_blob_id);
301+
return false;
302+
}
303+
304+
if (out_vector.empty()) {
305+
LOGINFO("empty shard found in move_to_chunk, chunk_id={}, shard_id={}", move_from_chunk, shard_id);
306+
307+
// TODO::send a delete shard request to the raft channel
308+
309+
continue;
310+
}
311+
312+
// write a shard header for this shard in move_to_chunk
313+
const auto shard_sb = m_hs_home_object->_get_hs_shard()->_sb.get();
314+
auto blk_size = data_service.get_blk_size();
315+
auto shard_sb_size = sizeof(HSHomeObject::shard_info_superblk);
316+
auto header_size = sisl::round_up(sizeof(HSHomeObject::shard_info_superblk), blk_size);
317+
318+
auto haader_buf = iomanager.iobuf_alloc(blk_size, header_size);
319+
std::memset(haader_buf, 0, header_size);
320+
std::memcpy(haader_buf, shard_sb, shard_sb_size);
321+
((HSHomeObject::shard_info_superblk*)haader_buf)->info.state = ShardInfo::State::OPEN;
322+
323+
sisl::sg_list sgs;
324+
sgs.size = header_size;
325+
sgs.iovs.emplace_back(iovec{.iov_base = haader_buf, .iov_len = header_size});
326+
327+
homestore::blk_alloc_hints hints;
328+
hints.chunk_id_hint = move_to_chunk;
329+
Homestore::MultiBlkId out_blkids;
330+
331+
auto err = data_service.async_alloc_write(sgs, hints, out_blkids, false).get();
332+
if (err) {
333+
LOGINFO("empty shard found in move_to_chunk, chunk_id={}, shard_id={}", move_from_chunk, shard_id);
334+
}
335+
336+
// copy all the shard data from move_from_chunk to move_to_chunk
337+
338+
// write a shard footer to the move_to_chunk
339+
}
340+
return true;
281341
}
282342

283343
void GCManager::pdev_gc_actor::purge_reserved_chunk(chunk_id_t chunk) {

src/lib/homestore_backend/gc_manager.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ class GCManager {
171171

172172
// copy all the valid data from the move_from_chunk to move_to_chunk. valid data means those blobs that are not
173173
// tombstone in the pg index table
174-
void copy_valid_data(chunk_id_t move_from_chunk, chunk_id_t move_to_chunk);
174+
// return true if the data copy is successful, false otherwise.
175+
bool copy_valid_data(chunk_id_t move_from_chunk, chunk_id_t move_to_chunk);
175176

176177
// before we select a reserved chunk and start gc, we need:
177178
// 1 clear all the entries of this chunk in the gc index table

src/lib/homestore_backend/hs_homeobject.hpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ class HSHomeObject : public HomeObjectImpl {
6161
trace_id_t tid) const override;
6262
BlobManager::NullAsyncResult _del_blob(ShardInfo const&, blob_id_t, trace_id_t tid) override;
6363

64-
PGManager::NullAsyncResult _create_pg(PGInfo&& pg_info, std::set< peer_id_t > const& peers, trace_id_t tid) override;
64+
PGManager::NullAsyncResult _create_pg(PGInfo&& pg_info, std::set< peer_id_t > const& peers,
65+
trace_id_t tid) override;
6566
PGManager::NullAsyncResult _replace_member(pg_id_t id, peer_id_t const& old_member, PGMember const& new_member,
6667
uint32_t commit_quorum, trace_id_t tid) override;
6768

@@ -80,6 +81,9 @@ class HSHomeObject : public HomeObjectImpl {
8081
std::unordered_map< std::string, std::shared_ptr< GCBlobIndexTable > > gc_index_table_map;
8182
std::once_flag replica_restart_flag_;
8283

84+
// mapping from chunk to shard list.
85+
folly::ConcurrentHashMap< homestore::chunk_num_t, std::unordered_set< shard_id_t > > chunk_shard_map_;
86+
8387
public:
8488
#pragma pack(1)
8589
struct pg_members {
@@ -639,8 +643,9 @@ class HSHomeObject : public HomeObjectImpl {
639643
static std::string serialize_shard_info(const ShardInfo& info);
640644
void local_create_shard(ShardInfo shard_info, homestore::chunk_num_t v_chunk_id, homestore::chunk_num_t p_chunk_id,
641645
homestore::blk_count_t blk_count, trace_id_t tid = 0);
642-
void add_new_shard_to_map(ShardPtr&& shard);
646+
void add_new_shard_to_map(std::unique_ptr< HS_Shard > shard);
643647
void update_shard_in_map(const ShardInfo& shard_info);
648+
const HS_Shard* _get_hs_shard(const shard_id_t shard_id) const;
644649

645650
// recover part
646651
void register_homestore_metablk_callback();
@@ -830,6 +835,8 @@ class HSHomeObject : public HomeObjectImpl {
830835
recover_index_table(homestore::superblk< homestore::index_table_sb >&& sb);
831836
std::optional< pg_id_t > get_pg_id_with_group_id(homestore::group_id_t group_id) const;
832837

838+
const auto& get_shards_in_chunk(homestore::chunk_num_t chunk_id) const { return _shards_in_chunk_map.at(chunk_id); }
839+
833840
// Snapshot persistence related
834841
sisl::io_blob_safe get_snapshot_sb_data(homestore::group_id_t group_id);
835842
void update_snapshot_sb(homestore::group_id_t group_id, std::shared_ptr< homestore::snapshot_context > ctx);

0 commit comments

Comments
 (0)