@@ -64,32 +64,58 @@ PGManager::NullAsyncResult HSHomeObject::_create_pg(PGInfo&& pg_info, std::set<
64
64
auto pg_id = pg_info.id ;
65
65
if (auto lg = std::shared_lock (_pg_lock); _pg_map.end () != _pg_map.find (pg_id)) return folly::Unit ();
66
66
67
- const auto most_avail_num_chunks = chunk_selector ()->most_avail_num_chunks ();
68
67
const auto chunk_size = chunk_selector ()->get_chunk_size ();
69
68
if (pg_info.size < chunk_size) {
70
69
LOGW (" Not support to create PG which pg_size {} < chunk_size {}" , pg_info.size , chunk_size);
71
70
return folly::makeUnexpected (PGError::INVALID_ARG);
72
71
}
73
72
74
- const auto needed_num_chunks = sisl::round_down (pg_info.size , chunk_size) / chunk_size;
75
- if (needed_num_chunks > most_avail_num_chunks) {
76
- LOGW (" No enough space to create pg, pg_id {}, needed_num_chunks {}, most_avail_num_chunks {}" , pg_id,
77
- needed_num_chunks, most_avail_num_chunks);
73
+ auto const num_chunk = chunk_selector ()->select_chunks_for_pg (pg_id, pg_info.size );
74
+ if (!num_chunk.has_value ()) {
75
+ LOGW (" Failed to select chunks for pg {}" , pg_id);
78
76
return folly::makeUnexpected (PGError::NO_SPACE_LEFT);
79
77
}
80
78
81
79
pg_info.chunk_size = chunk_size;
82
80
pg_info.replica_set_uuid = boost::uuids::random_generator ()();
81
+ const auto repl_dev_group_id = pg_info.replica_set_uuid ;
83
82
return hs_repl_service ()
84
83
.create_repl_dev (pg_info.replica_set_uuid , peers)
85
84
.via (executor_)
86
85
.thenValue ([this , pg_info = std::move (pg_info)](auto && v) mutable -> PGManager::NullAsyncResult {
86
+ #ifdef _PRERELEASE
87
+ if (iomgr_flip::instance ()->test_flip (" create_pg_create_repl_dev_error" )) {
88
+ LOGW (" Simulating create repl dev error in creating pg" );
89
+ v = folly::makeUnexpected (ReplServiceError::FAILED);
90
+ }
91
+ #endif
92
+
87
93
if (v.hasError ()) { return folly::makeUnexpected (toPgError (v.error ())); }
88
94
// we will write a PGHeader across the raft group and when it is committed
89
95
// all raft members will create PGinfo and index table for this PG.
90
96
91
97
// FIXME:https://github.com/eBay/HomeObject/pull/136#discussion_r1470504271
92
98
return do_create_pg (v.value (), std::move (pg_info));
99
+ })
100
+ .thenValue ([this , pg_id, repl_dev_group_id](auto && r) -> PGManager::NullAsyncResult {
101
+ // reclaim resources if failed to create pg
102
+ if (r.hasError ()) {
103
+ bool res = chunk_selector_->return_pg_chunks_to_dev_heap (pg_id);
104
+ RELEASE_ASSERT (res, " Failed to return pg {} chunks to dev_heap" , pg_id);
105
+ // no matter if create repl dev successfully, remove it.
106
+ // if don't have repl dev, it will return ReplServiceError::SERVER_NOT_FOUND
107
+ return hs_repl_service ()
108
+ .remove_repl_dev (repl_dev_group_id)
109
+ .deferValue ([r, repl_dev_group_id](auto && e) -> PGManager::NullAsyncResult {
110
+ if (e != ReplServiceError::OK) {
111
+ LOGW (" Failed to remove repl device which group_id {}, error: {}" , repl_dev_group_id, e);
112
+ }
113
+
114
+ // still return the original error
115
+ return folly::makeUnexpected (r.error ());
116
+ });
117
+ }
118
+ return folly::Unit ();
93
119
});
94
120
}
95
121
@@ -104,6 +130,13 @@ PGManager::NullAsyncResult HSHomeObject::do_create_pg(cshared< homestore::ReplDe
104
130
req->header ()->seal ();
105
131
std::memcpy (req->header_extn (), serailized_pg_info.data (), info_size);
106
132
133
+ #ifdef _PRERELEASE
134
+ if (iomgr_flip::instance ()->test_flip (" create_pg_raft_message_error" )) {
135
+ LOGW (" Simulating raft message error in creating pg" );
136
+ return folly::makeUnexpected (PGError::UNKNOWN);
137
+ }
138
+ #endif
139
+
107
140
// replicate this create pg message to all raft members of this group
108
141
repl_dev->async_alloc_write (req->header_buf (), sisl::blob{}, sisl::sg_list{}, req);
109
142
return req->result ().deferValue ([req](auto const & e) -> PGManager::NullAsyncResult {
@@ -291,7 +324,7 @@ void HSHomeObject::mark_pg_destroyed(pg_id_t pg_id) {
291
324
auto lg = std::scoped_lock (_pg_lock);
292
325
auto iter = _pg_map.find (pg_id);
293
326
if (iter == _pg_map.end ()) {
294
- LOGW (" on pg destroy with unknown pg_id {}" , pg_id);
327
+ LOGW (" mark pg destroyed with unknown pg_id {}" , pg_id);
295
328
return ;
296
329
}
297
330
auto & pg = iter->second ;
@@ -301,8 +334,7 @@ void HSHomeObject::mark_pg_destroyed(pg_id_t pg_id) {
301
334
}
302
335
303
336
void HSHomeObject::reset_pg_chunks (pg_id_t pg_id) {
304
- bool res = chunk_selector_->reset_pg_chunks (pg_id);
305
- RELEASE_ASSERT (res, " Failed to reset all chunks in pg {}" , pg_id);
337
+ chunk_selector_->reset_pg_chunks (pg_id);
306
338
auto fut = homestore::hs ()->cp_mgr ().trigger_cp_flush (true /* force */ );
307
339
auto on_complete = [&](auto success) {
308
340
RELEASE_ASSERT (success, " Failed to trigger CP flush" );
0 commit comments