Repository navigation
fix init rreq - #817
fix init rreq#817
Conversation
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #817 +/- ##
==========================================
- Coverage 56.51% 55.24% -1.27%
==========================================
Files 108 110 +2
Lines 10300 13278 +2978
Branches 1402 1934 +532
==========================================
+ Hits 5821 7336 +1515
- Misses 3894 5096 +1202
- Partials 585 846 +261 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
3fef832 to
a8d02de
Compare
a8d02de to
2f0e74d
Compare
|
Thank you very much for your fix! I am considering whether we might encounter a similar issue when the follower saves push data before raft channel here: https://github.com/eBay/HomeStore/blob/master/src/lib/replication/repl_dev/raft_repl_dev.cpp#L942 |
@Besroy yes, but after this PR is merged, in applier_create_req , when init_req_ctx , we will also do a deep copy for the header. so this will not be a issue. |
There was a problem hiding this comment.
The intent of the fix is good. However it is very tricky to follow as the whole repl_ctx_t is all ptr based, for data, journal_buf, and every other field. Why the header need special cares....
The logic flow strarts from
- we want to use
init_req_ctxso that the quience state get horned for EGC. - The
init_req_ctxcreates rreq, we want to save it into the map - The buffer referenced is a local buffer, which can be released.
- We need a deep copy of header, technically other fields need deep-copy as well, just we probabaly dont access them.
I would suggest break the flow from 2 or 3,
option 1: can we not save the rreq returned by init_req_ctx into map? Then later it will be recreated by using the journal buf.
option 2: similar to async_alloc_write etc, can we ensure the header_buf is live till the proposal committed ? i.e wait till the rreq is committed.
need @yuwmao 's input regarding wheter we should wait for step 3 completed before starting step 4. Also IIUC the step 4 (add member) wait till committed, that implies step 3 is commiited, then till the point of setp 3 committed the header is valid, why we are hitting issues here?
but for leader , it will be different. the key point is we need to propose_to_raft after the linked data is successfully written, and from journal we can recover header ,key, but can not allocate local blks as that in follower. we have to do it before propose_to_raft.
this will involve additional user side logic to achieve this, not user friendly and likely lead to memory leak if not carefully handle this. so , on my end, i prefer not to do this , it better to do the deep copy by ourselves.
yes, you are right, I think we need handle not only header, but also do a deep copy for key. for the journal_buf, in follower, a move if used, which will move the ownership of the resource to rreq literally. need a double check |
|
The async_alloc_wrie is already working fine as the caller (HO ) will not relase the buffer. Now the problem is only for replcae member. Can we focuse on fixing these APIs as a fix, instead of a major API refactoring that assuming caller can release everything after Previously the replace member works fine as it doesnt insert the rreq into map at all and it magically works as it go through the applier_create_req on leader. This behavior is wired I agree. |
|
Based on the business logic of replace member, it is likely the option 2 is naturally reached. |
|
this error will affect all the apis that involves header, including start_replace_member/complete_replace_member and propose_truncate_boundary. (and potentially affect the apis that involves key in the future) let me put more details here. previously( before commit id c5d067f), for the above three log-only(no data written) and header-involved and apis, we create rreq for each api call. but this created rreq is only used as an input parameter of however, fortunately,the log entry is a shared_ptr, and we put it into the log cache when appending log, and can ensure the key and value blob is not dangling until the corresponding log entry is evicted. so , theoretically, if handle_commit of a rreq is executed before the log entry is evicted, then everything will go well. but we made some changes recently and the behavior changes for leader. now, the rreq is created and inserted into req_map before propose_to_raft. so , for the above three apis, the header and key blob in rreq will definitely become dangling at leader(unless the caller can ensure they are valid).
I got your point, but I think we should thoroughly address this issue, it is not only about a specific api, it is more about the rreq mechanism |
|
Lets put solution aside and get a solid problem statement, Any buffer given to rreq, including header/key/data, is volatile, meaning, rreq will NOT do any deep copy but relies on the owner of the buffer to sustain till the EOL of the rreq. On follower,
|
|
Talked with @JacksonYao287 offline, replace_member related message header do need deep copy and the solution after commit id c5d067f looks good to me. |
2f0e74d to
cb51ae3
Compare
|
I set the behavior the same as before for non-async_alloc_write apis. let`s change this behavior later using a separate PR |
we should do a deep copy for the user header , otherwise if the input user_header is freed after the call is returned, then m_header will become a dangling blob(the pointer in it is a dangling pointer).
previously, we do not create and add rreq in to m_repl_key_req_map before propose_to_raft. the rreq is created and inserted into rreq when applier_create_req, where we created the rreq from the raft log entry, and the the in-memory log entry is available when the rreq#header is used, so the shallow copy works.
but now we create and add rreq in to m_repl_key_req_map before propose_to_raft.
so for follower , it works well since it is still created in applier_create_req
but for leader, the rreq , where the header blob is destroyed after we propose_to_raft. so the header of the rreq in m_repl_key_req_map will become a dangling blob.