enum index_session_flag_bit {
IS_FLAG_BIT_START = 8, /* The session has started loading an index but not completed it. */
IS_FLAG_BIT_LOADING = IS_FLAG_BIT_START, /* The session has loaded an index, which can handle requests. */
IS_FLAG_BIT_LOADED, /* The session's index has been permanently disabled. */
IS_FLAG_BIT_DISABLED, /* The session's index is suspended. */
IS_FLAG_BIT_SUSPENDED, /* The session is handling some index state change. */
IS_FLAG_BIT_WAITING, /* The session's index is closing and draining requests. */
IS_FLAG_BIT_CLOSING, /* The session is being destroyed and is draining requests. */
IS_FLAG_BIT_DESTROYING,
};
/* Release a reference to an index session. */ staticvoid release_index_session(struct uds_index_session *index_session)
{
mutex_lock(&index_session->request_mutex); if (--index_session->request_count == 0)
uds_broadcast_cond(&index_session->request_cond);
mutex_unlock(&index_session->request_mutex);
}
/* *Acquireareferencetotheindexsessionforanasynchronousindexrequest.Thereferencemust *eventuallybereleasedwithacorrespondingcalltorelease_index_session().
*/ staticint get_index_session(struct uds_index_session *index_session)
{ unsignedint state; int result = UDS_SUCCESS;
mutex_lock(&index_session->request_mutex);
index_session->request_count++;
state = index_session->state;
mutex_unlock(&index_session->request_mutex);
if (state == IS_FLAG_LOADED) { return UDS_SUCCESS;
} elseif (state & IS_FLAG_DISABLED) {
result = UDS_DISABLED;
} elseif ((state & IS_FLAG_LOADING) ||
(state & IS_FLAG_SUSPENDED) ||
(state & IS_FLAG_WAITING)) {
result = -EBUSY;
} else {
result = UDS_NO_INDEX;
}
switch (request->type) { case UDS_DELETE: case UDS_POST: case UDS_QUERY: case UDS_QUERY_NO_UPDATE: case UDS_UPDATE: break; default:
vdo_log_error("received invalid callback type"); return -EINVAL;
}
/* Reset all internal fields before processing. */
memset(&request->internal, 0, sizeof(request->internal));
result = get_index_session(request->session); if (result != UDS_SUCCESS) return result;
case UDS_UPDATE: if (request->found)
count_once(&session_stats->updates_found); else
count_once(&session_stats->updates_not_found); break;
case UDS_DELETE: if (request->found)
count_once(&session_stats->deletions_found); else
count_once(&session_stats->deletions_not_found); break;
case UDS_QUERY: case UDS_QUERY_NO_UPDATE: if (request->found)
count_once(&session_stats->queries_found); else
count_once(&session_stats->queries_not_found); break;
/* Wait until the index indicates that it is not replaying. */ while ((session->load_context.status != INDEX_SUSPENDED) &&
(session->load_context.status != INDEX_READY)) {
uds_wait_cond(&session->load_context.cond,
&session->load_context.mutex);
}
break;
case INDEX_READY: /* Index load does not need to be suspended. */ break;
case INDEX_SUSPENDED: case INDEX_SUSPENDING: case INDEX_FREEING: default: /* These cases should not happen. */
VDO_ASSERT_LOG_ONLY(false, "Bad load context state %u",
session->load_context.status); break;
}
mutex_unlock(&session->load_context.mutex);
}
/* *Suspendindexoperation,drainingallcurrentindexrequestsandpreventingnewindexrequests *fromstarting.Optionallysavesallindexdatabeforereturning.
*/ int uds_suspend_index_session(struct uds_index_session *session, bool save)
{ int result = UDS_SUCCESS; bool no_work = false; bool rebuilding = false;
/* Wait for any current index state change to complete. */
mutex_lock(&session->request_mutex); while (session->state & IS_FLAG_CLOSING)
uds_wait_cond(&session->request_cond, &session->request_mutex);
/* *Resumeindexoperationafterbeingsuspended.Iftheindexissuspendedandthesuppliedblock *devicediffersfromthecurrentbackingstore,theindexwillstartusingthenewbackingstore.
*/ int uds_resume_index_session(struct uds_index_session *session, struct block_device *bdev)
{ int result = UDS_SUCCESS; bool no_work = false; bool resume_replay = false;
mutex_lock(&session->request_mutex); if (session->state & IS_FLAG_WAITING) {
vdo_log_info("Index session is already changing state");
no_work = true;
result = -EBUSY;
} elseif (!(session->state & IS_FLAG_SUSPENDED)) { /* If not suspended, just succeed. */
no_work = true;
result = UDS_SUCCESS;
} else {
session->state |= IS_FLAG_WAITING; if (session->state & IS_FLAG_LOADING)
resume_replay = true;
}
mutex_unlock(&session->request_mutex);
if (no_work) return result;
if ((session->index != NULL) && (bdev != session->parameters.bdev)) {
result = replace_device(session, bdev); if (result != UDS_SUCCESS) {
mutex_lock(&session->request_mutex);
session->state &= ~IS_FLAG_WAITING;
uds_broadcast_cond(&session->request_cond);
mutex_unlock(&session->request_mutex); return uds_status_to_errno(result);
}
}
if (resume_replay) {
mutex_lock(&session->load_context.mutex); switch (session->load_context.status) { case INDEX_SUSPENDED:
session->load_context.status = INDEX_OPENING; /* Notify the index to start replaying again. */
uds_broadcast_cond(&session->load_context.cond); break;
case INDEX_READY: /* There is no index rebuild to resume. */ break;
case INDEX_OPENING: case INDEX_SUSPENDING: case INDEX_FREEING: default: /* These cases should not happen; do nothing. */
VDO_ASSERT_LOG_ONLY(false, "Bad load context state %u",
session->load_context.status); break;
}
mutex_unlock(&session->load_context.mutex);
}
if (!suspended) {
result = uds_save_index(index); if (result != UDS_SUCCESS)
vdo_log_warning_strerror(result, "ignoring error from save_index");
}
uds_free_index(index);
index_session->index = NULL;
mutex_lock(&index_session->request_mutex); /* Only the suspend bit will remain relevant. */
index_session->state &= IS_FLAG_SUSPENDED;
mutex_unlock(&index_session->request_mutex);
return result;
}
/* Save and close the current index. */ int uds_close_index(struct uds_index_session *index_session)
{ int result = UDS_SUCCESS;
/* Wait for any current index state change to complete. */
mutex_lock(&index_session->request_mutex); while ((index_session->state & IS_FLAG_WAITING) ||
(index_session->state & IS_FLAG_CLOSING)) {
uds_wait_cond(&index_session->request_cond,
&index_session->request_mutex);
}
if (index_session->state & IS_FLAG_SUSPENDED) {
vdo_log_info("Index session is suspended");
result = -EBUSY;
} elseif ((index_session->state & IS_FLAG_DESTROYING) ||
!(index_session->state & IS_FLAG_LOADED)) { /* The index doesn't exist, hasn't finished loading, or is being destroyed. */
result = UDS_NO_INDEX;
} else {
index_session->state |= IS_FLAG_CLOSING;
}
mutex_unlock(&index_session->request_mutex); if (result != UDS_SUCCESS) return uds_status_to_errno(result);
vdo_log_debug("Closing index");
wait_for_no_requests_in_progress(index_session);
result = save_and_free_index(index_session);
vdo_log_debug("Closed index");
/* This will save and close an open index before destroying the session. */ int uds_destroy_index_session(struct uds_index_session *index_session)
{ int result; bool load_pending = false;
vdo_log_debug("Destroying index session");
/* Wait for any current index state change to complete. */
mutex_lock(&index_session->request_mutex); while ((index_session->state & IS_FLAG_WAITING) ||
(index_session->state & IS_FLAG_CLOSING)) {
uds_wait_cond(&index_session->request_cond,
&index_session->request_mutex);
}
if (index_session->state & IS_FLAG_DESTROYING) {
mutex_unlock(&index_session->request_mutex);
vdo_log_info("Index session is already closing"); return -EBUSY;
}
if (load_pending) { /* Tell the index to terminate the rebuild. */
mutex_lock(&index_session->load_context.mutex); if (index_session->load_context.status == INDEX_SUSPENDED) {
index_session->load_context.status = INDEX_FREEING;
uds_broadcast_cond(&index_session->load_context.cond);
}
mutex_unlock(&index_session->load_context.mutex);
/* Wait until the load exits before proceeding. */
mutex_lock(&index_session->request_mutex); while (index_session->state & IS_FLAG_LOADING) {
uds_wait_cond(&index_session->request_cond,
&index_session->request_mutex);
}
mutex_unlock(&index_session->request_mutex);
}
wait_for_no_requests_in_progress(index_session);
result = save_and_free_index(index_session);
uds_request_queue_finish(index_session->callback_queue);
index_session->callback_queue = NULL;
vdo_log_debug("Destroyed index session");
vdo_free(index_session); return uds_status_to_errno(result);
}
/* Wait until all callbacks for index operations are complete. */ int uds_flush_index_session(struct uds_index_session *index_session)
{
wait_for_no_requests_in_progress(index_session);
uds_wait_for_idle_index(index_session->index); return UDS_SUCCESS;
}
/* Statistics collection is intended to be thread-safe. */ staticvoid collect_stats(conststruct uds_index_session *index_session, struct uds_index_stats *stats)
{ conststruct session_stats *session_stats = &index_session->stats;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.