Fix MeshMS REST newsince race condition

During GET /restful/meshms/SID1/SID2/newsince/messagelist.json, if a new
message was received before the request reached the end of its message
iterator and paused, then the new message did not make it into the
output.
This commit is contained in:
Andrew Bettison 2015-06-29 14:52:29 +09:30
parent 9f15c4770c
commit abb2a39330
3 changed files with 18 additions and 2 deletions

View File

@ -188,6 +188,7 @@ typedef struct httpd_request
enum list_phase phase;
size_t rowcount;
struct meshms_message_iterator iter;
unsigned dirty;
int finished;
}
msglist;

View File

@ -785,6 +785,11 @@ void meshms_conversation_iterator_advance(struct meshms_conversation_iterator *i
enum meshms_status meshms_message_iterator_open(struct meshms_message_iterator *iter, const sid_t *me, const sid_t *them)
{
if (config.debug.meshms)
DEBUGF("iter=%p me=%s them=%s", iter,
me ? alloca_tohex_sid_t(*me) : "NULL",
them ? alloca_tohex_sid_t(*them) : "NULL"
);
enum meshms_status status;
bzero(iter, sizeof *iter);
if (meshms_failed(status = find_or_create_conv(me, them, &iter->_conv)))
@ -842,6 +847,8 @@ int meshms_message_iterator_is_open(const struct meshms_message_iterator *iter)
void meshms_message_iterator_close(struct meshms_message_iterator *iter)
{
if (config.debug.meshms)
DEBUGF("iter=%p", iter);
if (iter->_my_manifest) {
ply_read_close(&iter->_my_reader);
rhizome_manifest_free(iter->_my_manifest);

View File

@ -290,6 +290,10 @@ static HTTP_CONTENT_GENERATOR restful_meshms_messagelist_json_content;
static enum meshms_status reopen_meshms_message_iterator(httpd_request *r)
{
if (r->u.msglist.dirty) {
meshms_message_iterator_close(&r->u.msglist.iter);
r->u.msglist.dirty = 0;
}
if (!meshms_message_iterator_is_open(&r->u.msglist.iter)) {
enum meshms_status status;
if ( meshms_failed(status = meshms_message_iterator_open(&r->u.msglist.iter, &r->sid1, &r->sid2))
@ -352,9 +356,13 @@ static int restful_meshms_newsince_messagelist_json(httpd_request *r, const char
static void on_rhizome_bundle_added(httpd_request *r, rhizome_manifest *m)
{
// TODO select on sender and/or recipient fields
if (strcmp(m->service, RHIZOME_SERVICE_MESHMS2) == 0) {
http_request_resume_response(&r->http);
if ( (cmp_sid_t(&m->sender, &r->sid1) == 0 && cmp_sid_t(&m->recipient, &r->sid2) == 0)
|| (cmp_sid_t(&m->sender, &r->sid2) == 0 && cmp_sid_t(&m->recipient, &r->sid1) == 0)
) {
r->u.msglist.dirty = 1;
http_request_resume_response(&r->http);
}
}
}