|
Packit |
b55c50 |
/*
|
|
Packit Service |
4cccae |
* %Copyright%
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
b55c50 |
* modify it under the terms of the GNU General Public License
|
|
Packit |
b55c50 |
* as published by the Free Software Foundation; either version 2
|
|
Packit |
b55c50 |
* of the License, or (at your option) any later version.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
b55c50 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
b55c50 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
b55c50 |
* GNU General Public License for more details.
|
|
Packit |
b55c50 |
*
|
|
Packit |
b55c50 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
b55c50 |
* along with this program; if not, write to the Free Software
|
|
Packit |
b55c50 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit |
b55c50 |
* 02110-1301, USA.
|
|
Packit |
b55c50 |
*
|
|
Packit Service |
4cccae |
* $Id: //eng/uds-releases/jasper/src/uds/indexSession.c#10 $
|
|
Packit |
b55c50 |
*/
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
#include "indexSession.h"
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
#include "indexCheckpoint.h"
|
|
Packit |
b55c50 |
#include "indexRouter.h"
|
|
Packit |
b55c50 |
#include "logger.h"
|
|
Packit |
b55c50 |
#include "memoryAlloc.h"
|
|
Packit |
b55c50 |
#include "requestQueue.h"
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
static void collectStats(const struct uds_index_session *indexSession,
|
|
Packit |
b55c50 |
UdsContextStats *stats)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
const SessionStats *sessionStats = &indexSession->stats;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
stats->currentTime = asTimeT(currentTime(CLOCK_REALTIME));
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
stats->postsFound = READ_ONCE(sessionStats->postsFound);
|
|
Packit |
b55c50 |
stats->inMemoryPostsFound = READ_ONCE(sessionStats->postsFoundOpenChapter);
|
|
Packit |
b55c50 |
stats->densePostsFound = READ_ONCE(sessionStats->postsFoundDense);
|
|
Packit |
b55c50 |
stats->sparsePostsFound = READ_ONCE(sessionStats->postsFoundSparse);
|
|
Packit |
b55c50 |
stats->postsNotFound = READ_ONCE(sessionStats->postsNotFound);
|
|
Packit |
b55c50 |
stats->updatesFound = READ_ONCE(sessionStats->updatesFound);
|
|
Packit |
b55c50 |
stats->updatesNotFound = READ_ONCE(sessionStats->updatesNotFound);
|
|
Packit |
b55c50 |
stats->deletionsFound = READ_ONCE(sessionStats->deletionsFound);
|
|
Packit |
b55c50 |
stats->deletionsNotFound = READ_ONCE(sessionStats->deletionsNotFound);
|
|
Packit |
b55c50 |
stats->queriesFound = READ_ONCE(sessionStats->queriesFound);
|
|
Packit |
b55c50 |
stats->queriesNotFound = READ_ONCE(sessionStats->queriesNotFound);
|
|
Packit |
b55c50 |
stats->requests = READ_ONCE(sessionStats->requests);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
static void handleCallbacks(Request *request)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
if (request->status == UDS_SUCCESS) {
|
|
Packit |
b55c50 |
// Measure the turnaround time of this request and include that time,
|
|
Packit |
b55c50 |
// along with the rest of the request, in the context's StatCounters.
|
|
Packit |
b55c50 |
updateRequestContextStats(request);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
if (request->callback != NULL) {
|
|
Packit |
b55c50 |
// The request has specified its own callback and does not expect to be
|
|
Packit |
b55c50 |
// freed.
|
|
Packit |
b55c50 |
struct uds_index_session *indexSession = request->session;
|
|
Packit |
b55c50 |
request->found = (request->location != LOC_UNAVAILABLE);
|
|
Packit |
b55c50 |
request->callback((UdsRequest *) request);
|
|
Packit |
b55c50 |
// We do this release after the callback because of the contract of the
|
|
Packit |
b55c50 |
// udsFlushIndexSession method.
|
|
Packit |
b55c50 |
releaseIndexSession(indexSession);
|
|
Packit |
b55c50 |
return;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
// Should not get here, because this is either a control message or it has a
|
|
Packit |
b55c50 |
// callback method.
|
|
Packit |
b55c50 |
freeRequest(request);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int checkIndexSession(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
unsigned int state = indexSession->state;
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
if (state == IS_FLAG_LOADED) {
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
} else if (state & IS_FLAG_DISABLED) {
|
|
Packit |
b55c50 |
return UDS_DISABLED;
|
|
Packit |
b55c50 |
} else if ((state & IS_FLAG_LOADING)
|
|
Packit |
b55c50 |
|| (state & IS_FLAG_SUSPENDED)
|
|
Packit |
b55c50 |
|| (state & IS_FLAG_WAITING)) {
|
|
Packit |
b55c50 |
return UDS_SUSPENDED;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
return UDS_NO_INDEXSESSION;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int getIndexSession(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
indexSession->requestCount++;
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
int result = checkIndexSession(indexSession);
|
|
Packit |
b55c50 |
if (result != UDS_SUCCESS) {
|
|
Packit |
b55c50 |
releaseIndexSession(indexSession);
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
void releaseIndexSession(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
if (--indexSession->requestCount == 0) {
|
|
Packit |
b55c50 |
broadcastCond(&indexSession->requestCond);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int startLoadingIndexSession(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
int result;
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
if (indexSession->state & IS_FLAG_SUSPENDED) {
|
|
Packit |
b55c50 |
result = UDS_SUSPENDED;
|
|
Packit |
b55c50 |
} else if (indexSession->state != 0) {
|
|
Packit |
b55c50 |
result = UDS_INDEXSESSION_IN_USE;
|
|
Packit |
b55c50 |
} else {
|
|
Packit |
b55c50 |
indexSession->state |= IS_FLAG_LOADING;
|
|
Packit |
b55c50 |
result = UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
void finishLoadingIndexSession(struct uds_index_session *indexSession,
|
|
Packit |
b55c50 |
int result)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
indexSession->state &= ~IS_FLAG_LOADING;
|
|
Packit |
b55c50 |
if (result == UDS_SUCCESS) {
|
|
Packit |
b55c50 |
indexSession->state |= IS_FLAG_LOADED;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
broadcastCond(&indexSession->requestCond);
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
void disableIndexSession(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
indexSession->state |= IS_FLAG_DISABLED;
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int makeEmptyIndexSession(struct uds_index_session **indexSessionPtr)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
struct uds_index_session *session;
|
|
Packit |
b55c50 |
int result = ALLOCATE(1, struct uds_index_session, __func__, &session);
|
|
Packit |
b55c50 |
if (result != UDS_SUCCESS) {
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
result = initMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
if (result != UDS_SUCCESS) {
|
|
Packit |
b55c50 |
FREE(session);
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
result = initCond(&session->requestCond);
|
|
Packit |
b55c50 |
if (result != UDS_SUCCESS) {
|
|
Packit |
b55c50 |
destroyMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
FREE(session);
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
result = initMutex(&session->loadContext.mutex);
|
|
Packit |
b55c50 |
if (result != UDS_SUCCESS) {
|
|
Packit |
b55c50 |
destroyCond(&session->requestCond);
|
|
Packit |
b55c50 |
destroyMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
FREE(session);
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
result = initCond(&session->loadContext.cond);
|
|
Packit |
b55c50 |
if (result != UDS_SUCCESS) {
|
|
Packit |
b55c50 |
destroyMutex(&session->loadContext.mutex);
|
|
Packit |
b55c50 |
destroyCond(&session->requestCond);
|
|
Packit |
b55c50 |
destroyMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
FREE(session);
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
result = makeRequestQueue("callbackW", &handleCallbacks,
|
|
Packit |
b55c50 |
&session->callbackQueue);
|
|
Packit |
b55c50 |
if (result != UDS_SUCCESS) {
|
|
Packit |
b55c50 |
destroyCond(&session->loadContext.cond);
|
|
Packit |
b55c50 |
destroyMutex(&session->loadContext.mutex);
|
|
Packit |
b55c50 |
destroyCond(&session->requestCond);
|
|
Packit |
b55c50 |
destroyMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
FREE(session);
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
*indexSessionPtr = session;
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int udsSuspendIndexSession(struct uds_index_session *session, bool save)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
int result;
|
|
Packit |
b55c50 |
bool saveIndex = false;
|
|
Packit |
b55c50 |
bool suspendIndex = false;
|
|
Packit |
b55c50 |
lockMutex(&session->requestMutex);
|
|
Packit Service |
4cccae |
// Wait for any pending close operation to complete.
|
|
Packit Service |
4cccae |
while (session->state & IS_FLAG_CLOSING) {
|
|
Packit Service |
4cccae |
waitCond(&session->requestCond, &session->requestMutex);
|
|
Packit Service |
4cccae |
}
|
|
Packit Service |
4cccae |
if ((session->state & IS_FLAG_WAITING)
|
|
Packit Service |
4cccae |
|| (session->state & IS_FLAG_DESTROYING)) {
|
|
Packit |
b55c50 |
result = EBUSY;
|
|
Packit |
b55c50 |
} else if (session->state & IS_FLAG_SUSPENDED) {
|
|
Packit |
b55c50 |
result = UDS_SUCCESS;
|
|
Packit Service |
4cccae |
} else if (session->state & IS_FLAG_LOADING) {
|
|
Packit Service |
4cccae |
session->state |= IS_FLAG_WAITING;
|
|
Packit Service |
4cccae |
suspendIndex = true;
|
|
Packit Service |
4cccae |
result = UDS_SUCCESS;
|
|
Packit Service |
4cccae |
} else if (!(session->state & IS_FLAG_LOADED)) {
|
|
Packit |
b55c50 |
session->state |= IS_FLAG_SUSPENDED;
|
|
Packit |
b55c50 |
broadcastCond(&session->requestCond);
|
|
Packit |
b55c50 |
result = UDS_SUCCESS;
|
|
Packit |
b55c50 |
} else {
|
|
Packit Service |
4cccae |
saveIndex = save;
|
|
Packit Service |
4cccae |
if (saveIndex) {
|
|
Packit Service |
4cccae |
session->state |= IS_FLAG_WAITING;
|
|
Packit Service |
4cccae |
} else {
|
|
Packit Service |
4cccae |
session->state |= IS_FLAG_SUSPENDED;
|
|
Packit Service |
4cccae |
broadcastCond(&session->requestCond);
|
|
Packit Service |
4cccae |
}
|
|
Packit |
b55c50 |
result = UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
unlockMutex(&session->requestMutex);
|
|
Packit Service |
4cccae |
|
|
Packit Service |
4cccae |
if (!saveIndex && !suspendIndex) {
|
|
Packit Service |
4cccae |
return result;
|
|
Packit Service |
4cccae |
}
|
|
Packit Service |
4cccae |
|
|
Packit |
b55c50 |
if (saveIndex) {
|
|
Packit |
b55c50 |
result = udsSaveIndex(session);
|
|
Packit Service |
4cccae |
lockMutex(&session->requestMutex);
|
|
Packit Service |
4cccae |
session->state &= ~IS_FLAG_WAITING;
|
|
Packit Service |
4cccae |
session->state |= IS_FLAG_SUSPENDED;
|
|
Packit Service |
4cccae |
broadcastCond(&session->requestCond);
|
|
Packit Service |
4cccae |
unlockMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
lockMutex(&session->loadContext.mutex);
|
|
Packit |
b55c50 |
switch (session->loadContext.status) {
|
|
Packit |
b55c50 |
case INDEX_OPENING:
|
|
Packit |
b55c50 |
session->loadContext.status = INDEX_SUSPENDING;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
// Wait until the index indicates that it is not replaying.
|
|
Packit |
b55c50 |
while ((session->loadContext.status != INDEX_SUSPENDED)
|
|
Packit |
b55c50 |
&& (session->loadContext.status != INDEX_READY)) {
|
|
Packit |
b55c50 |
waitCond(&session->loadContext.cond,
|
|
Packit |
b55c50 |
&session->loadContext.mutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
break;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
case INDEX_READY:
|
|
Packit |
b55c50 |
// Index load does not need to be suspended.
|
|
Packit |
b55c50 |
break;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
case INDEX_SUSPENDED:
|
|
Packit |
b55c50 |
case INDEX_SUSPENDING:
|
|
Packit |
b55c50 |
case INDEX_FREEING:
|
|
Packit |
b55c50 |
default:
|
|
Packit |
b55c50 |
// These cases should not happen.
|
|
Packit |
b55c50 |
ASSERT_LOG_ONLY(false, "Bad load context state %u",
|
|
Packit |
b55c50 |
session->loadContext.status);
|
|
Packit |
b55c50 |
break;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
unlockMutex(&session->loadContext.mutex);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
lockMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
session->state &= ~IS_FLAG_WAITING;
|
|
Packit |
b55c50 |
session->state |= IS_FLAG_SUSPENDED;
|
|
Packit |
b55c50 |
broadcastCond(&session->requestCond);
|
|
Packit |
b55c50 |
unlockMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int udsResumeIndexSession(struct uds_index_session *session)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
lockMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
if (session->state & IS_FLAG_WAITING) {
|
|
Packit |
b55c50 |
unlockMutex(&session->requestMutex);
|
|
Packit Service |
4cccae |
return EBUSY;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit Service |
4cccae |
/* If not suspended, just succeed */
|
|
Packit |
b55c50 |
if (!(session->state & IS_FLAG_SUSPENDED)) {
|
|
Packit |
b55c50 |
unlockMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
if (!(session->state & IS_FLAG_LOADING)) {
|
|
Packit |
b55c50 |
session->state &= ~IS_FLAG_SUSPENDED;
|
|
Packit |
b55c50 |
unlockMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
session->state |= IS_FLAG_WAITING;
|
|
Packit |
b55c50 |
unlockMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
lockMutex(&session->loadContext.mutex);
|
|
Packit |
b55c50 |
switch (session->loadContext.status) {
|
|
Packit |
b55c50 |
case INDEX_SUSPENDED:
|
|
Packit |
b55c50 |
session->loadContext.status = INDEX_OPENING;
|
|
Packit |
b55c50 |
// Notify the index to start replaying again.
|
|
Packit |
b55c50 |
broadcastCond(&session->loadContext.cond);
|
|
Packit |
b55c50 |
break;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
case INDEX_READY:
|
|
Packit |
b55c50 |
// There is no index rebuild to resume.
|
|
Packit |
b55c50 |
break;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
case INDEX_OPENING:
|
|
Packit |
b55c50 |
case INDEX_SUSPENDING:
|
|
Packit |
b55c50 |
case INDEX_FREEING:
|
|
Packit |
b55c50 |
default:
|
|
Packit |
b55c50 |
// These cases should not happen; do nothing.
|
|
Packit |
b55c50 |
ASSERT_LOG_ONLY(false, "Bad load context state %u",
|
|
Packit |
b55c50 |
session->loadContext.status);
|
|
Packit |
b55c50 |
break;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
unlockMutex(&session->loadContext.mutex);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
lockMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
session->state &= ~IS_FLAG_WAITING;
|
|
Packit |
b55c50 |
session->state &= ~IS_FLAG_SUSPENDED;
|
|
Packit |
b55c50 |
broadcastCond(&session->requestCond);
|
|
Packit |
b55c50 |
unlockMutex(&session->requestMutex);
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
static void waitForNoRequestsInProgress(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
while (indexSession->requestCount > 0) {
|
|
Packit |
b55c50 |
waitCond(&indexSession->requestCond, &indexSession->requestMutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int saveAndFreeIndex(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
int result = UDS_SUCCESS;
|
|
Packit |
b55c50 |
IndexRouter *router = indexSession->router;
|
|
Packit |
b55c50 |
if (router != NULL) {
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
bool suspended = (indexSession->state & IS_FLAG_SUSPENDED);
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
if (!suspended) {
|
|
Packit |
b55c50 |
result = saveIndexRouter(router);
|
|
Packit |
b55c50 |
if (result != UDS_SUCCESS) {
|
|
Packit |
b55c50 |
logWarningWithStringError(result, "ignoring error from saveIndexRouter");
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
freeIndexRouter(router);
|
|
Packit |
b55c50 |
indexSession->router = NULL;
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
// Reset all index state that happens to be in the index session, so it
|
|
Packit |
b55c50 |
// doesn't affect any future index.
|
|
Packit |
b55c50 |
lockMutex(&indexSession->loadContext.mutex);
|
|
Packit |
b55c50 |
indexSession->loadContext.status = INDEX_OPENING;
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->loadContext.mutex);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
// Only the suspend bit will remain relevant.
|
|
Packit |
b55c50 |
indexSession->state &= IS_FLAG_SUSPENDED;
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
logDebug("Closed index");
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int udsCloseIndex(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit Service |
4cccae |
|
|
Packit Service |
4cccae |
// Wait for any pending suspend, resume or close operations to complete.
|
|
Packit Service |
4cccae |
while ((indexSession->state & IS_FLAG_WAITING)
|
|
Packit Service |
4cccae |
|| (indexSession->state & IS_FLAG_CLOSING)) {
|
|
Packit |
b55c50 |
waitCond(&indexSession->requestCond, &indexSession->requestMutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
int result = UDS_SUCCESS;
|
|
Packit |
b55c50 |
if (indexSession->state & IS_FLAG_SUSPENDED) {
|
|
Packit |
b55c50 |
result = UDS_SUSPENDED;
|
|
Packit Service |
4cccae |
} else if ((indexSession->state & IS_FLAG_DESTROYING)
|
|
Packit Service |
4cccae |
|| !(indexSession->state & IS_FLAG_LOADED)) {
|
|
Packit Service |
4cccae |
// The index doesn't exist, hasn't finished loading, or is being destroyed.
|
|
Packit |
b55c50 |
result = UDS_NO_INDEXSESSION;
|
|
Packit Service |
4cccae |
} else {
|
|
Packit Service |
4cccae |
indexSession->state |= IS_FLAG_CLOSING;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
if (result != UDS_SUCCESS) {
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
logDebug("Closing index");
|
|
Packit |
b55c50 |
waitForNoRequestsInProgress(indexSession);
|
|
Packit Service |
4cccae |
result = saveAndFreeIndex(indexSession);
|
|
Packit Service |
4cccae |
|
|
Packit Service |
4cccae |
lockMutex(&indexSession->requestMutex);
|
|
Packit Service |
4cccae |
indexSession->state &= ~IS_FLAG_CLOSING;
|
|
Packit Service |
4cccae |
broadcastCond(&indexSession->requestCond);
|
|
Packit Service |
4cccae |
unlockMutex(&indexSession->requestMutex);
|
|
Packit Service |
4cccae |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int udsDestroyIndexSession(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
logDebug("Destroying index session");
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
bool loadPending = false;
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
|
|
Packit Service |
4cccae |
// Wait for any pending suspend, resume, or close operations to complete.
|
|
Packit Service |
4cccae |
while ((indexSession->state & IS_FLAG_WAITING)
|
|
Packit Service |
4cccae |
|| (indexSession->state & IS_FLAG_CLOSING)) {
|
|
Packit |
b55c50 |
waitCond(&indexSession->requestCond, &indexSession->requestMutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit Service |
4cccae |
if (indexSession->state & IS_FLAG_DESTROYING) {
|
|
Packit Service |
4cccae |
unlockMutex(&indexSession->requestMutex);
|
|
Packit Service |
4cccae |
return EBUSY;
|
|
Packit Service |
4cccae |
}
|
|
Packit Service |
4cccae |
|
|
Packit Service |
4cccae |
indexSession->state |= IS_FLAG_DESTROYING;
|
|
Packit |
b55c50 |
loadPending = ((indexSession->state & IS_FLAG_LOADING)
|
|
Packit |
b55c50 |
&& (indexSession->state & IS_FLAG_SUSPENDED));
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
if (loadPending) {
|
|
Packit |
b55c50 |
// Tell the index to terminate the rebuild.
|
|
Packit |
b55c50 |
lockMutex(&indexSession->loadContext.mutex);
|
|
Packit |
b55c50 |
if (indexSession->loadContext.status == INDEX_SUSPENDED) {
|
|
Packit |
b55c50 |
indexSession->loadContext.status = INDEX_FREEING;
|
|
Packit |
b55c50 |
broadcastCond(&indexSession->loadContext.cond);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->loadContext.mutex);
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
// Wait until the load exits before proceeding.
|
|
Packit |
b55c50 |
lockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
while (indexSession->state & IS_FLAG_LOADING) {
|
|
Packit |
b55c50 |
waitCond(&indexSession->requestCond, &indexSession->requestMutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
unlockMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
waitForNoRequestsInProgress(indexSession);
|
|
Packit |
b55c50 |
int result = saveAndFreeIndex(indexSession);
|
|
Packit |
b55c50 |
requestQueueFinish(indexSession->callbackQueue);
|
|
Packit |
b55c50 |
indexSession->callbackQueue = NULL;
|
|
Packit |
b55c50 |
destroyCond(&indexSession->loadContext.cond);
|
|
Packit |
b55c50 |
destroyMutex(&indexSession->loadContext.mutex);
|
|
Packit |
b55c50 |
destroyCond(&indexSession->requestCond);
|
|
Packit |
b55c50 |
destroyMutex(&indexSession->requestMutex);
|
|
Packit |
b55c50 |
logDebug("Destroyed index session");
|
|
Packit |
b55c50 |
FREE(indexSession);
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int udsFlushIndexSession(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
waitForNoRequestsInProgress(indexSession);
|
|
Packit |
b55c50 |
// Wait until any open chapter writes are complete
|
|
Packit |
b55c50 |
waitForIdleIndexRouter(indexSession->router);
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int udsSaveIndex(struct uds_index_session *indexSession)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
waitForNoRequestsInProgress(indexSession);
|
|
Packit |
b55c50 |
// saveIndexRouter waits for open chapter writes to complete
|
|
Packit |
b55c50 |
return saveIndexRouter(indexSession->router);
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int udsSetCheckpointFrequency(struct uds_index_session *indexSession,
|
|
Packit |
b55c50 |
unsigned int frequency)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
setIndexCheckpointFrequency(indexSession->router->index->checkpoint,
|
|
Packit |
b55c50 |
frequency);
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int udsGetIndexConfiguration(struct uds_index_session *indexSession,
|
|
Packit |
b55c50 |
UdsConfiguration *conf)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
if (conf == NULL) {
|
|
Packit |
b55c50 |
return logErrorWithStringError(UDS_CONF_PTR_REQUIRED,
|
|
Packit |
b55c50 |
"received a NULL config pointer");
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
int result = ALLOCATE(1, struct udsConfiguration, __func__, conf);
|
|
Packit |
b55c50 |
if (result == UDS_SUCCESS) {
|
|
Packit |
b55c50 |
**conf = indexSession->userConfig;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
return result;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int udsGetIndexStats(struct uds_index_session *indexSession,
|
|
Packit |
b55c50 |
UdsIndexStats *stats)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
if (stats == NULL) {
|
|
Packit |
b55c50 |
return logErrorWithStringError(UDS_INDEX_STATS_PTR_REQUIRED,
|
|
Packit |
b55c50 |
"received a NULL index stats pointer");
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
getIndexStats(indexSession->router->index, stats);
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
|
|
Packit |
b55c50 |
/**********************************************************************/
|
|
Packit |
b55c50 |
int udsGetIndexSessionStats(struct uds_index_session *indexSession,
|
|
Packit |
b55c50 |
UdsContextStats *stats)
|
|
Packit |
b55c50 |
{
|
|
Packit |
b55c50 |
if (stats == NULL) {
|
|
Packit |
b55c50 |
return logWarningWithStringError(UDS_CONTEXT_STATS_PTR_REQUIRED,
|
|
Packit |
b55c50 |
"received a NULL context stats pointer");
|
|
Packit |
b55c50 |
}
|
|
Packit |
b55c50 |
collectStats(indexSession, stats);
|
|
Packit |
b55c50 |
return UDS_SUCCESS;
|
|
Packit |
b55c50 |
}
|