@@ -205,79 +205,139 @@ void GCManager::pdev_gc_actor::handle_recovered_gc_task(const GCManager::gc_task
205
205
206
206
void GCManager::pdev_gc_actor::switch_chunks_after_data_copy (chunk_id_t move_from_chunk, chunk_id_t move_to_chunk,
207
207
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
277
277
}
278
278
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 ;
281
341
}
282
342
283
343
void GCManager::pdev_gc_actor::purge_reserved_chunk (chunk_id_t chunk) {
0 commit comments