Blame source/uds/indexSession.c

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
}