Blame source/uds/indexComponent.c

Packit Service 310c69
/*
Packit Service 310c69
 * Copyright (c) 2020 Red Hat, Inc.
Packit Service 310c69
 *
Packit Service 310c69
 * This program is free software; you can redistribute it and/or
Packit Service 310c69
 * modify it under the terms of the GNU General Public License
Packit Service 310c69
 * as published by the Free Software Foundation; either version 2
Packit Service 310c69
 * of the License, or (at your option) any later version.
Packit Service 310c69
 * 
Packit Service 310c69
 * This program is distributed in the hope that it will be useful,
Packit Service 310c69
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 310c69
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 310c69
 * GNU General Public License for more details.
Packit Service 310c69
 * 
Packit Service 310c69
 * You should have received a copy of the GNU General Public License
Packit Service 310c69
 * along with this program; if not, write to the Free Software
Packit Service 310c69
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 310c69
 * 02110-1301, USA. 
Packit Service 310c69
 *
Packit Service 310c69
 * $Id: //eng/uds-releases/jasper/src/uds/indexComponent.c#8 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#include "indexComponent.h"
Packit Service 310c69
Packit Service 310c69
#include "compiler.h"
Packit Service 310c69
#include "errors.h"
Packit Service 310c69
#include "indexLayout.h"
Packit Service 310c69
#include "indexState.h"
Packit Service 310c69
#include "logger.h"
Packit Service 310c69
#include "memoryAlloc.h"
Packit Service 310c69
#include "permassert.h"
Packit Service 310c69
#include "typeDefs.h"
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int makeIndexComponent(IndexState                *state,
Packit Service 310c69
                       const IndexComponentInfo  *info,
Packit Service 310c69
                       unsigned int               zoneCount,
Packit Service 310c69
                       void                      *data,
Packit Service 310c69
                       void                      *context,
Packit Service 310c69
                       IndexComponent           **componentPtr)
Packit Service 310c69
{
Packit Service 310c69
  if ((info == NULL) || (info->name == NULL)) {
Packit Service 310c69
    return logErrorWithStringError(UDS_INVALID_ARGUMENT,
Packit Service 310c69
                                   "invalid component or directory specified");
Packit Service 310c69
  }
Packit Service 310c69
  if (info->loader == NULL) {
Packit Service 310c69
    return logErrorWithStringError(UDS_INVALID_ARGUMENT,
Packit Service 310c69
                                   "no .loader function specified "
Packit Service 310c69
                                   "for component %s",
Packit Service 310c69
                                   info->name);
Packit Service 310c69
  }
Packit Service 310c69
  if ((info->saver == NULL) && (info->incremental == NULL)) {
Packit Service 310c69
    return logErrorWithStringError(UDS_INVALID_ARGUMENT,
Packit Service 310c69
                                   "neither .saver function nor .incremental "
Packit Service 310c69
                                   "function specified for component %s",
Packit Service 310c69
                                   info->name);
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  IndexComponent *component = NULL;
Packit Service 310c69
  int result = ALLOCATE(1, IndexComponent, "index component", &component);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  component->componentData = data;
Packit Service 310c69
  component->context       = context;
Packit Service 310c69
  component->info          = info;
Packit Service 310c69
  component->numZones      = info->multiZone ? zoneCount : 1;
Packit Service 310c69
  component->state         = state;
Packit Service 310c69
  component->writeZones    = NULL;
Packit Service 310c69
  *componentPtr = component;
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
static void freeWriteZones(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  if (component->writeZones != NULL) {
Packit Service 310c69
    unsigned int z;
Packit Service 310c69
    for (z = 0; z < component->numZones; ++z) {
Packit Service 310c69
      WriteZone *wz = component->writeZones[z];
Packit Service 310c69
      if (wz == NULL) {
Packit Service 310c69
        continue;
Packit Service 310c69
      }
Packit Service 310c69
      freeBufferedWriter(wz->writer);
Packit Service 310c69
      FREE(wz);
Packit Service 310c69
    }
Packit Service 310c69
    FREE(component->writeZones);
Packit Service 310c69
    component->writeZones = NULL;
Packit Service 310c69
  }
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
void freeIndexComponent(IndexComponent **componentPtr)
Packit Service 310c69
{
Packit Service 310c69
  if (componentPtr == NULL) {
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
  IndexComponent *component = *componentPtr;
Packit Service 310c69
  if (component == NULL) {
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
  *componentPtr = NULL;
Packit Service 310c69
Packit Service 310c69
  freeWriteZones(component);
Packit Service 310c69
  FREE(component);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Destroy, deallocate, and expunge a read portal.
Packit Service 310c69
 *
Packit Service 310c69
 * @param readPortal     the readzone array
Packit Service 310c69
 **/
Packit Service 310c69
static void freeReadPortal(ReadPortal *readPortal)
Packit Service 310c69
{
Packit Service 310c69
  if (readPortal == NULL) {
Packit Service 310c69
    return;
Packit Service 310c69
  }
Packit Service 310c69
  unsigned int z;
Packit Service 310c69
  for (z = 0; z < readPortal->zones; ++z) {
Packit Service 310c69
    if (readPortal->readers[z] != NULL) {
Packit Service 310c69
      freeBufferedReader(readPortal->readers[z]);
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  FREE(readPortal->readers);
Packit Service 310c69
  FREE(readPortal);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int getBufferedReaderForPortal(ReadPortal      *portal,
Packit Service 310c69
                               unsigned int     part,
Packit Service 310c69
                               BufferedReader **readerPtr)
Packit Service 310c69
{
Packit Service 310c69
  if (part >= portal->zones) {
Packit Service 310c69
    return logErrorWithStringError(UDS_INVALID_ARGUMENT,
Packit Service 310c69
                                   "%s: cannot access zone %u of %u",
Packit Service 310c69
                                   __func__, part, portal->zones);
Packit Service 310c69
  }
Packit Service 310c69
  IndexComponent *component = portal->component;
Packit Service 310c69
  if (component->info->ioStorage && (portal->readers[part] == NULL)) {
Packit Service 310c69
    int result = openStateBufferedReader(component->state,
Packit Service 310c69
                                         component->info->kind, part,
Packit Service 310c69
                                         &portal->readers[part]);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      return logErrorWithStringError(result,
Packit Service 310c69
                                     "%s: cannot make buffered reader "
Packit Service 310c69
                                     "for zone %u", __func__, part);
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  *readerPtr = portal->readers[part];
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int readIndexComponent(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  ReadPortal *portal;
Packit Service 310c69
  int result = ALLOCATE(1, ReadPortal, "index component read portal", &portal);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  int readZones = component->state->loadZones;
Packit Service 310c69
  result = ALLOCATE(readZones, BufferedReader *, "read zone buffered readers",
Packit Service 310c69
                    &portal->readers);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    FREE(portal);
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  portal->component = component;
Packit Service 310c69
  portal->zones = readZones;
Packit Service 310c69
  result = (*component->info->loader)(portal);
Packit Service 310c69
  freeReadPortal(portal);
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Determine the writeZone structure for the specified component and zone.
Packit Service 310c69
 *
Packit Service 310c69
 * @param [in]  component      the index component
Packit Service 310c69
 * @param [in]  zone           the zone number
Packit Service 310c69
 * @param [out] writeZonePtr   the resulting write zone instance
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
static int resolveWriteZone(const IndexComponent  *component,
Packit Service 310c69
                            unsigned int           zone,
Packit Service 310c69
                            WriteZone            **writeZonePtr)
Packit Service 310c69
{
Packit Service 310c69
  int result = ASSERT(writeZonePtr != NULL,
Packit Service 310c69
                      "output parameter is null");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if (component->writeZones == NULL) {
Packit Service 310c69
    return logErrorWithStringError(UDS_BAD_STATE,
Packit Service 310c69
                                   "cannot resolve index component write zone:"
Packit Service 310c69
                                   " not allocated");
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if (zone >= component->numZones) {
Packit Service 310c69
    return logErrorWithStringError(UDS_INVALID_ARGUMENT,
Packit Service 310c69
                                   "cannot resolve index component write zone:"
Packit Service 310c69
                                   " zone out of range");
Packit Service 310c69
  }
Packit Service 310c69
  *writeZonePtr = component->writeZones[zone];
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Non-incremental save function used to emulate a regular save
Packit Service 310c69
 * using an incremental save function as a basis.
Packit Service 310c69
 *
Packit Service 310c69
 * @param component    the index component
Packit Service 310c69
 * @param writer       the buffered writer
Packit Service 310c69
 * @param zone         the zone number
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
static int indexComponentSaverIncrementalWrapper(IndexComponent *component,
Packit Service 310c69
                                                 BufferedWriter *writer,
Packit Service 310c69
                                                 unsigned int    zone)
Packit Service 310c69
{
Packit Service 310c69
  IncrementalWriter incrFunc  = component->info->incremental;
Packit Service 310c69
  bool              completed = false;
Packit Service 310c69
Packit Service 310c69
  int result = (*incrFunc)(component, writer, zone, IWC_START, &completed);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if (!completed) {
Packit Service 310c69
    result = (*incrFunc)(component, writer, zone, IWC_FINISH, &completed);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = flushBufferedWriter(writer);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Specify that writing to a specific zone file has finished.
Packit Service 310c69
 *
Packit Service 310c69
 * If a syncer has been registered with the index component, the file
Packit Service 310c69
 * descriptor will be enqueued upon it for fsyncing and closing.
Packit Service 310c69
 * If not, or if the enqueue fails, the file will be fsynced and closed
Packit Service 310c69
 * immediately.
Packit Service 310c69
 *
Packit Service 310c69
 * @param writeZone    the index component write zone
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
static int doneWithZone(WriteZone *writeZone)
Packit Service 310c69
{
Packit Service 310c69
  const IndexComponent *component = writeZone->component;
Packit Service 310c69
  if (writeZone->writer != NULL) {
Packit Service 310c69
    int result = flushBufferedWriter(writeZone->writer);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      return logErrorWithStringError(result,
Packit Service 310c69
                                     "cannot flush buffered writer for "
Packit Service 310c69
                                     "%s component (zone %u)",
Packit Service 310c69
                                     component->info->name, writeZone->zone);
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Construct the array of WriteZone instances for this component.
Packit Service 310c69
 *
Packit Service 310c69
 * @param component    the index component
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 *
Packit Service 310c69
 * If this is a multizone component, each zone will be fully defined,
Packit Service 310c69
 * otherwise zone 0 stands in for the single state file.
Packit Service 310c69
 **/
Packit Service 310c69
static int makeWriteZones(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  unsigned int z;
Packit Service 310c69
  if (component->writeZones != NULL) {
Packit Service 310c69
    // just reinitialize states
Packit Service 310c69
    for (z = 0; z < component->numZones; ++z) {
Packit Service 310c69
      WriteZone *wz = component->writeZones[z];
Packit Service 310c69
      wz->phase = IWC_IDLE;
Packit Service 310c69
    }
Packit Service 310c69
    return UDS_SUCCESS;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  int result = ALLOCATE(component->numZones, WriteZone *,
Packit Service 310c69
                        "index component write zones", &component->writeZones);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  for (z = 0; z < component->numZones; ++z) {
Packit Service 310c69
    result = ALLOCATE(1, WriteZone, "plain write zone",
Packit Service 310c69
                      &component->writeZones[z]);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      freeWriteZones(component);
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
    *component->writeZones[z] = (WriteZone) {
Packit Service 310c69
      .component = component,
Packit Service 310c69
      .phase     = IWC_IDLE,
Packit Service 310c69
      .zone      = z,
Packit Service 310c69
    };
Packit Service 310c69
  }
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
static int openBufferedWriters(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  int result = UDS_SUCCESS;
Packit Service 310c69
  WriteZone **wzp;
Packit Service 310c69
  for (wzp = component->writeZones;
Packit Service 310c69
       wzp < component->writeZones + component->numZones;
Packit Service 310c69
       ++wzp) {
Packit Service 310c69
    WriteZone *wz = *wzp;
Packit Service 310c69
    wz->phase = IWC_START;
Packit Service 310c69
Packit Service 310c69
    result = ASSERT(wz->writer == NULL, "write zone writer already exists");
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
Packit Service 310c69
    if (component->info->ioStorage) {
Packit Service 310c69
      int result = openStateBufferedWriter(component->state,
Packit Service 310c69
                                           component->info->kind, wz->zone,
Packit Service 310c69
                                           &wz->writer);
Packit Service 310c69
      if (result != UDS_SUCCESS) {
Packit Service 310c69
        return result;
Packit Service 310c69
      }
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
static int startIndexComponentSave(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  int result = makeWriteZones(component);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = openBufferedWriters(component);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int startIndexComponentIncrementalSave(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  return startIndexComponentSave(component);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int writeIndexComponent(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  Saver saver = component->info->saver;
Packit Service 310c69
  if ((saver == NULL) && (component->info->incremental != NULL)) {
Packit Service 310c69
    saver = indexComponentSaverIncrementalWrapper;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  int result = startIndexComponentSave(component);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  unsigned int z;
Packit Service 310c69
  for (z = 0; z < component->numZones; ++z) {
Packit Service 310c69
    WriteZone *writeZone = component->writeZones[z];
Packit Service 310c69
Packit Service 310c69
    result = (*saver)(component, writeZone->writer, z);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      break;
Packit Service 310c69
    }
Packit Service 310c69
Packit Service 310c69
    result = doneWithZone(writeZone);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      break;
Packit Service 310c69
    }
Packit Service 310c69
Packit Service 310c69
    freeBufferedWriter(writeZone->writer);
Packit Service 310c69
    writeZone->writer = NULL;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    freeWriteZones(component);
Packit Service 310c69
    return logErrorWithStringError(result, "index component write failed");
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Close a specific buffered writer in a component write zone.
Packit Service 310c69
 *
Packit Service 310c69
 * @param writeZone    the write zone
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 *
Packit Service 310c69
 * @note closing a buffered writer causes its file descriptor to be
Packit Service 310c69
 *       passed to doneWithZone
Packit Service 310c69
 **/
Packit Service 310c69
static int closeBufferedWriter(WriteZone *writeZone)
Packit Service 310c69
{
Packit Service 310c69
  if (writeZone->writer == NULL) {
Packit Service 310c69
    return UDS_SUCCESS;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  int result = doneWithZone(writeZone);
Packit Service 310c69
  freeBufferedWriter(writeZone->writer);
Packit Service 310c69
  writeZone->writer = NULL;
Packit Service 310c69
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Faux incremental saver function for index components which only define
Packit Service 310c69
 * a simple saver.  Conforms to IncrementalWriter signature.
Packit Service 310c69
 *
Packit Service 310c69
 * @param [in]  component      the index component
Packit Service 310c69
 * @param [in]  writer         the buffered writer that does the output
Packit Service 310c69
 * @param [in]  zone           the zone number
Packit Service 310c69
 * @param [in]  command        the incremental writer command
Packit Service 310c69
 * @param [out] completed      if non-NULL, set to whether the save is complete
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 *
Packit Service 310c69
 * @note This wrapper always calls the non-incremental saver when
Packit Service 310c69
 *       the IWC_START command is issued, and always reports that
Packit Service 310c69
 *       the save is complete unless the saver failed.
Packit Service 310c69
 **/
Packit Service 310c69
static int wrapSaverAsIncremental(IndexComponent           *component,
Packit Service 310c69
                                  BufferedWriter           *writer,
Packit Service 310c69
                                  unsigned int              zone,
Packit Service 310c69
                                  IncrementalWriterCommand  command,
Packit Service 310c69
                                  bool                     *completed)
Packit Service 310c69
{
Packit Service 310c69
  int result = UDS_SUCCESS;
Packit Service 310c69
Packit Service 310c69
  if ((command >= IWC_START) && (command <= IWC_FINISH)) {
Packit Service 310c69
    result = (*component->info->saver)(component, writer, zone);
Packit Service 310c69
    if ((result == UDS_SUCCESS) && (writer != NULL)) {
Packit Service 310c69
      noteBufferedWriterUsed(writer);
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  if ((result == UDS_SUCCESS) && (completed != NULL)) {
Packit Service 310c69
    *completed = true;
Packit Service 310c69
  }
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Return the appropriate incremental writer function depending on
Packit Service 310c69
 * the component's type and whether this is the first zone.
Packit Service 310c69
 *
Packit Service 310c69
 * @param component    the index component
Packit Service 310c69
 *
Packit Service 310c69
 * @return the correct IncrementalWriter function to use, or
Packit Service 310c69
 *         NULL signifying no progress can be made at this time.
Packit Service 310c69
 **/
Packit Service 310c69
static IncrementalWriter getIncrementalWriter(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  IncrementalWriter incrFunc = component->info->incremental;
Packit Service 310c69
Packit Service 310c69
  if (incrFunc == NULL) {
Packit Service 310c69
    incrFunc = &wrapSaverAsIncremental;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return incrFunc;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int performIndexComponentZoneSave(IndexComponent   *component,
Packit Service 310c69
                                  unsigned int      zone,
Packit Service 310c69
                                  CompletionStatus *completed)
Packit Service 310c69
{
Packit Service 310c69
  CompletionStatus comp = CS_NOT_COMPLETED;
Packit Service 310c69
Packit Service 310c69
  WriteZone *wz = NULL;
Packit Service 310c69
  int result = resolveWriteZone(component, zone, &wz;;
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if (wz->phase == IWC_IDLE) {
Packit Service 310c69
    comp = CS_COMPLETED_PREVIOUSLY;
Packit Service 310c69
  } else if (wz->phase == IWC_DONE) {
Packit Service 310c69
    comp = CS_JUST_COMPLETED;
Packit Service 310c69
    wz->phase = IWC_IDLE;
Packit Service 310c69
  } else if (!component->info->chapterSync) {
Packit Service 310c69
    bool done = false;
Packit Service 310c69
    IncrementalWriter incrFunc = getIncrementalWriter(component);
Packit Service 310c69
    int result = (*incrFunc)(component, wz->writer, zone, wz->phase, &done);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      if (wz->phase == IWC_ABORT) {
Packit Service 310c69
        wz->phase = IWC_IDLE;
Packit Service 310c69
      } else {
Packit Service 310c69
        wz->phase = IWC_ABORT;
Packit Service 310c69
      }
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
    if (done) {
Packit Service 310c69
      comp = CS_JUST_COMPLETED;
Packit Service 310c69
      wz->phase = IWC_IDLE;
Packit Service 310c69
    } else if (wz->phase == IWC_START) {
Packit Service 310c69
      wz->phase = IWC_CONTINUE;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if (completed != NULL) {
Packit Service 310c69
    *completed = comp;
Packit Service 310c69
  }
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int performIndexComponentChapterWriterSave(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  WriteZone *wz = NULL;
Packit Service 310c69
  int result = resolveWriteZone(component, 0, &wz;;
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if ((wz->phase != IWC_IDLE) && (wz->phase != IWC_DONE)) {
Packit Service 310c69
    bool done = false;
Packit Service 310c69
    IncrementalWriter incrFunc = getIncrementalWriter(component);
Packit Service 310c69
    int result = ASSERT(incrFunc != NULL, "no writer function");
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
    result = (*incrFunc)(component, wz->writer, 0, wz->phase, &done);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      if (wz->phase == IWC_ABORT) {
Packit Service 310c69
        wz->phase = IWC_IDLE;
Packit Service 310c69
      } else {
Packit Service 310c69
        wz->phase = IWC_ABORT;
Packit Service 310c69
      }
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
    if (done) {
Packit Service 310c69
      wz->phase = IWC_DONE;
Packit Service 310c69
    } else if (wz->phase == IWC_START) {
Packit Service 310c69
      wz->phase = IWC_CONTINUE;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int finishIndexComponentZoneSave(IndexComponent   *component,
Packit Service 310c69
                                 unsigned int      zone,
Packit Service 310c69
                                 CompletionStatus *completed)
Packit Service 310c69
{
Packit Service 310c69
  WriteZone *wz = NULL;
Packit Service 310c69
  int result = resolveWriteZone(component, zone, &wz;;
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  CompletionStatus comp;
Packit Service 310c69
  switch (wz->phase) {
Packit Service 310c69
    case IWC_IDLE:
Packit Service 310c69
      comp = CS_COMPLETED_PREVIOUSLY;
Packit Service 310c69
      break;
Packit Service 310c69
Packit Service 310c69
    case IWC_DONE:
Packit Service 310c69
      comp = CS_JUST_COMPLETED;
Packit Service 310c69
      break;
Packit Service 310c69
Packit Service 310c69
    default:
Packit Service 310c69
      comp = CS_NOT_COMPLETED;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  IncrementalWriter incrFunc = getIncrementalWriter(component);
Packit Service 310c69
  if ((wz->phase >= IWC_START) && (wz->phase < IWC_ABORT)) {
Packit Service 310c69
    bool done = false;
Packit Service 310c69
    int result = (*incrFunc)(component, wz->writer, zone, IWC_FINISH, &done);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      wz->phase = IWC_ABORT;
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
    if (!done) {
Packit Service 310c69
      logWarning("finish incremental save did not complete for %s zone %u",
Packit Service 310c69
                 component->info->name, zone);
Packit Service 310c69
      return UDS_CHECKPOINT_INCOMPLETE;
Packit Service 310c69
    }
Packit Service 310c69
    wz->phase = IWC_IDLE;
Packit Service 310c69
    comp = CS_JUST_COMPLETED;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if (completed != NULL) {
Packit Service 310c69
    *completed = comp;
Packit Service 310c69
  }
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int finishIndexComponentIncrementalSave(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  unsigned int zone;
Packit Service 310c69
  for (zone = 0; zone < component->numZones; ++zone) {
Packit Service 310c69
    WriteZone *wz = component->writeZones[zone];
Packit Service 310c69
    IncrementalWriter incrFunc = getIncrementalWriter(component);
Packit Service 310c69
    if ((wz->phase != IWC_IDLE) && (wz->phase != IWC_DONE)) {
Packit Service 310c69
      // Note: this is only safe if no other threads are currently processing
Packit Service 310c69
      // this particular index
Packit Service 310c69
      bool done = false;
Packit Service 310c69
      int result = (*incrFunc)(component, wz->writer, zone, IWC_FINISH, &done);
Packit Service 310c69
      if (result != UDS_SUCCESS) {
Packit Service 310c69
        return result;
Packit Service 310c69
      }
Packit Service 310c69
      if (!done) {
Packit Service 310c69
        logWarning("finishing incremental save did not complete for %s zone %u",
Packit Service 310c69
                   component->info->name, zone);
Packit Service 310c69
        return UDS_UNEXPECTED_RESULT;
Packit Service 310c69
      }
Packit Service 310c69
      wz->phase = IWC_IDLE;
Packit Service 310c69
    }
Packit Service 310c69
Packit Service 310c69
    if ((wz->writer != NULL) && !wasBufferedWriterUsed(wz->writer)) {
Packit Service 310c69
      return logErrorWithStringError(UDS_CHECKPOINT_INCOMPLETE,
Packit Service 310c69
                                     "component %s zone %u did not get written",
Packit Service 310c69
                                     component->info->name, zone);
Packit Service 310c69
    }
Packit Service 310c69
Packit Service 310c69
    int result = closeBufferedWriter(wz);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int abortIndexComponentZoneSave(IndexComponent   *component,
Packit Service 310c69
                                unsigned int      zone,
Packit Service 310c69
                                CompletionStatus *status)
Packit Service 310c69
{
Packit Service 310c69
  WriteZone *wz = NULL;
Packit Service 310c69
  int result = resolveWriteZone(component, zone, &wz;;
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  CompletionStatus comp = CS_COMPLETED_PREVIOUSLY;
Packit Service 310c69
Packit Service 310c69
  IncrementalWriter incrFunc = getIncrementalWriter(component);
Packit Service 310c69
  if ((wz->phase != IWC_IDLE) && (wz->phase != IWC_DONE)) {
Packit Service 310c69
    result = (*incrFunc)(component, wz->writer, zone, IWC_ABORT, NULL);
Packit Service 310c69
    wz->phase = IWC_IDLE;
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
    comp = CS_JUST_COMPLETED;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if (status != NULL) {
Packit Service 310c69
    *status = comp;
Packit Service 310c69
  }
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int abortIndexComponentIncrementalSave(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  int result = UDS_SUCCESS;
Packit Service 310c69
  unsigned int zone;
Packit Service 310c69
  for (zone = 0; zone < component->numZones; ++zone) {
Packit Service 310c69
    WriteZone *wz = component->writeZones[zone];
Packit Service 310c69
    IncrementalWriter incrFunc = getIncrementalWriter(component);
Packit Service 310c69
    if ((wz->phase != IWC_IDLE) && (wz->phase != IWC_DONE)) {
Packit Service 310c69
      // Note: this is only safe if no other threads are currently processing
Packit Service 310c69
      // this particular index
Packit Service 310c69
      result = (*incrFunc)(component, wz->writer, zone, IWC_ABORT, NULL);
Packit Service 310c69
      wz->phase = IWC_IDLE;
Packit Service 310c69
      if (result != UDS_SUCCESS) {
Packit Service 310c69
        return result;
Packit Service 310c69
      }
Packit Service 310c69
    }
Packit Service 310c69
Packit Service 310c69
    int result = closeBufferedWriter(wz);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/*****************************************************************************/
Packit Service 310c69
int discardIndexComponent(IndexComponent *component)
Packit Service 310c69
{
Packit Service 310c69
  if (!component->info->ioStorage) {
Packit Service 310c69
    return UDS_INVALID_ARGUMENT;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  unsigned int numZones = 0;
Packit Service 310c69
  unsigned int saveSlot = 0;
Packit Service 310c69
  int result = findLatestIndexSaveSlot(component->state->layout, &numZones,
Packit Service 310c69
                                       &saveSlot);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  unsigned int oldSaveSlot = component->state->saveSlot;
Packit Service 310c69
  component->state->saveSlot = saveSlot;
Packit Service 310c69
Packit Service 310c69
  unsigned int z;
Packit Service 310c69
  for (z = 0; z < numZones; ++z) {
Packit Service 310c69
    BufferedWriter *writer;
Packit Service 310c69
    int result = openStateBufferedWriter(component->state,
Packit Service 310c69
                                         component->info->kind, z, &writer);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      break;
Packit Service 310c69
    }
Packit Service 310c69
    result = writeZerosToBufferedWriter(writer, UDS_BLOCK_SIZE);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      break;
Packit Service 310c69
    }
Packit Service 310c69
    result = flushBufferedWriter(writer);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      break;
Packit Service 310c69
    }
Packit Service 310c69
    freeBufferedWriter(writer);
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  component->state->saveSlot = oldSaveSlot;
Packit Service 310c69
  return result;
Packit Service 310c69
}