Blame source/uds/masterIndex006.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/masterIndex006.c#2 $
Packit Service 310c69
 */
Packit Service 310c69
#include "masterIndex006.h"
Packit Service 310c69
Packit Service 310c69
#include "buffer.h"
Packit Service 310c69
#include "compiler.h"
Packit Service 310c69
#include "errors.h"
Packit Service 310c69
#include "hashUtils.h"
Packit Service 310c69
#include "logger.h"
Packit Service 310c69
#include "masterIndex005.h"
Packit Service 310c69
#include "memoryAlloc.h"
Packit Service 310c69
#include "permassert.h"
Packit Service 310c69
#include "threads.h"
Packit Service 310c69
#include "uds.h"
Packit Service 310c69
Packit Service 310c69
/*
Packit Service 310c69
 * The master index is a kept as a wrapper around 2 master index
Packit Service 310c69
 * implementations, one for dense chapters and one for sparse chapters.
Packit Service 310c69
 * Methods will be routed to one or the other, or both, depending on the
Packit Service 310c69
 * method and data passed in.
Packit Service 310c69
 *
Packit Service 310c69
 * The master index is divided into zones, and in normal operation there is
Packit Service 310c69
 * one thread operating on each zone.  Any operation that operates on all
Packit Service 310c69
 * the zones needs to do its operation at a safe point that ensures that
Packit Service 310c69
 * only one thread is operating on the master index.
Packit Service 310c69
 *
Packit Service 310c69
 * The only multithreaded operation supported by the sparse master index is
Packit Service 310c69
 * the lookupMasterIndexName() method.  It is called by the thread that
Packit Service 310c69
 * assigns an index request to the proper zone, and needs to do a master
Packit Service 310c69
 * index query for sampled chunk names.  The zone mutexes are used to make
Packit Service 310c69
 * this lookup operation safe.
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
typedef struct __attribute__((aligned(CACHE_LINE_BYTES))) masterIndexZone {
Packit Service 310c69
  Mutex hookMutex;          // Protects the sampled index in this zone
Packit Service 310c69
} MasterIndexZone;
Packit Service 310c69
Packit Service 310c69
typedef struct {
Packit Service 310c69
  MasterIndex      common;           // Common master index methods
Packit Service 310c69
  unsigned int     sparseSampleRate; // The sparse sample rate
Packit Service 310c69
  unsigned int     numZones;         // The number of zones
Packit Service 310c69
  MasterIndex     *miNonHook;        // The non-hook index
Packit Service 310c69
  MasterIndex     *miHook;           // The hook index == sample index
Packit Service 310c69
  MasterIndexZone *masterZones;      // The zones
Packit Service 310c69
} MasterIndex6;
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Determine whether a given chunk name is a hook.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex    The master index
Packit Service 310c69
 * @param name           The block name
Packit Service 310c69
 *
Packit Service 310c69
 * @return whether to use as sample
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE bool isMasterIndexSample_006(const MasterIndex  *masterIndex,
Packit Service 310c69
                                           const UdsChunkName *name)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  return (extractSamplingBytes(name) % mi6->sparseSampleRate) == 0;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Get the subindex for the given chunk name
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex    The master index
Packit Service 310c69
 * @param name           The block name
Packit Service 310c69
 *
Packit Service 310c69
 * @return the subindex
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE MasterIndex *getSubIndex(const MasterIndex *masterIndex,
Packit Service 310c69
                                       const UdsChunkName *name)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  return (isMasterIndexSample_006(masterIndex, name)
Packit Service 310c69
          ? mi6->miHook
Packit Service 310c69
          : mi6->miNonHook);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Terminate and clean up the master index
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex The master index to terminate
Packit Service 310c69
 **/
Packit Service 310c69
static void freeMasterIndex_006(MasterIndex *masterIndex)
Packit Service 310c69
{
Packit Service 310c69
  if (masterIndex != NULL) {
Packit Service 310c69
    MasterIndex6 *mi6 = container_of(masterIndex, MasterIndex6, common);
Packit Service 310c69
    if (mi6->masterZones != NULL) {
Packit Service 310c69
      unsigned int zone;
Packit Service 310c69
      for (zone = 0; zone < mi6->numZones; zone++) {
Packit Service 310c69
        destroyMutex(&mi6->masterZones[zone].hookMutex);
Packit Service 310c69
      }
Packit Service 310c69
      FREE(mi6->masterZones);
Packit Service 310c69
      mi6->masterZones = NULL;
Packit Service 310c69
    }
Packit Service 310c69
    if (mi6->miNonHook != NULL) {
Packit Service 310c69
      freeMasterIndex(mi6->miNonHook);
Packit Service 310c69
      mi6->miNonHook = NULL;
Packit Service 310c69
    }
Packit Service 310c69
    if (mi6->miHook != NULL) {
Packit Service 310c69
      freeMasterIndex(mi6->miHook);
Packit Service 310c69
      mi6->miHook = NULL;
Packit Service 310c69
    }
Packit Service 310c69
    FREE(masterIndex);
Packit Service 310c69
  }
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Constants and structures for the saved master index file.  "MI6" is for
Packit Service 310c69
 * masterIndex006, and "-XXXX" is a number to increment when the format of
Packit Service 310c69
 * the data changes.
Packit Service 310c69
 **/
Packit Service 310c69
enum { MAGIC_SIZE = 8 };
Packit Service 310c69
static const char MAGIC_MI_START[] = "MI6-0001";
Packit Service 310c69
Packit Service 310c69
struct mi006_data {
Packit Service 310c69
  char         magic[MAGIC_SIZE]; // MAGIC_MI_START
Packit Service 310c69
  unsigned int sparseSampleRate;
Packit Service 310c69
};
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Set the tag value used when saving and/or restoring a master index.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex  The master index
Packit Service 310c69
 * @param tag          The tag value
Packit Service 310c69
 **/
Packit Service 310c69
static void setMasterIndexTag_006(MasterIndex *masterIndex
Packit Service 310c69
                                  __attribute__((unused)),
Packit Service 310c69
                                  byte tag __attribute__((unused)))
Packit Service 310c69
{
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static int encodeMasterIndexHeader(Buffer *buffer, struct mi006_data *header)
Packit Service 310c69
{
Packit Service 310c69
  int result = putBytes(buffer, MAGIC_SIZE, MAGIC_MI_START);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  result = putUInt32LEIntoBuffer(buffer, header->sparseSampleRate);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  result = ASSERT_LOG_ONLY(contentLength(buffer) == sizeof(struct mi006_data),
Packit Service 310c69
                           "%zu bytes of config written, of %zu expected",
Packit Service 310c69
                           contentLength(buffer), sizeof(struct mi006_data));
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Start saving a master index to a buffered output stream.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex     The master index
Packit Service 310c69
 * @param zoneNumber      The number of the zone to save
Packit Service 310c69
 * @param bufferedWriter  The index state component being written
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS on success, or an error code on failure
Packit Service 310c69
 **/
Packit Service 310c69
static int startSavingMasterIndex_006(const MasterIndex *masterIndex,
Packit Service 310c69
                                      unsigned int zoneNumber,
Packit Service 310c69
                                      BufferedWriter *bufferedWriter)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  Buffer *buffer;
Packit Service 310c69
  int result = makeBuffer(sizeof(struct mi006_data), &buffer);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  struct mi006_data header;
Packit Service 310c69
  memset(&header, 0, sizeof(header));
Packit Service 310c69
  memcpy(header.magic, MAGIC_MI_START, MAGIC_SIZE);
Packit Service 310c69
  header.sparseSampleRate = mi6->sparseSampleRate;
Packit Service 310c69
  result = encodeMasterIndexHeader(buffer, &header);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    freeBuffer(&buffer);
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  result = writeToBufferedWriter(bufferedWriter, getBufferContents(buffer),
Packit Service 310c69
                                 contentLength(buffer));
Packit Service 310c69
  freeBuffer(&buffer);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    logWarningWithStringError(result, "failed to write master index header");
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = startSavingMasterIndex(mi6->miNonHook, zoneNumber, bufferedWriter);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = startSavingMasterIndex(mi6->miHook, zoneNumber, bufferedWriter);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Have all the data been written while saving a master index to an output
Packit Service 310c69
 * stream?  If the answer is yes, it is still necessary to call
Packit Service 310c69
 * finishSavingMasterIndex(), which will return quickly.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex  The master index
Packit Service 310c69
 * @param zoneNumber   The number of the zone to save
Packit Service 310c69
 *
Packit Service 310c69
 * @return true if all the data are written
Packit Service 310c69
 **/
Packit Service 310c69
static bool isSavingMasterIndexDone_006(const MasterIndex *masterIndex,
Packit Service 310c69
                                        unsigned int zoneNumber)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  return (isSavingMasterIndexDone(mi6->miNonHook, zoneNumber)
Packit Service 310c69
          && isSavingMasterIndexDone(mi6->miHook, zoneNumber));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Finish saving a master index to an output stream.  Force the writing of
Packit Service 310c69
 * all of the remaining data.  If an error occurred asynchronously during
Packit Service 310c69
 * the save operation, it will be returned here.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex  The master index
Packit Service 310c69
 * @param zoneNumber   The number of the zone to save
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS on success, or an error code on failure
Packit Service 310c69
 **/
Packit Service 310c69
static int finishSavingMasterIndex_006(const MasterIndex *masterIndex,
Packit Service 310c69
                                       unsigned int zoneNumber)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  int result = finishSavingMasterIndex(mi6->miNonHook, zoneNumber);
Packit Service 310c69
  if (result == UDS_SUCCESS) {
Packit Service 310c69
    result = finishSavingMasterIndex(mi6->miHook, zoneNumber);
Packit Service 310c69
  }
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Abort saving a master index to an output stream.  If an error occurred
Packit Service 310c69
 * asynchronously during the save operation, it will be dropped.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex  The master index
Packit Service 310c69
 * @param zoneNumber   The number of the zone to save
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS on success, or an error code on failure
Packit Service 310c69
 **/
Packit Service 310c69
static int abortSavingMasterIndex_006(const MasterIndex *masterIndex,
Packit Service 310c69
                                      unsigned int zoneNumber)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  int result = abortSavingMasterIndex(mi6->miNonHook, zoneNumber);
Packit Service 310c69
  int result2 = abortSavingMasterIndex(mi6->miHook, zoneNumber);
Packit Service 310c69
  if (result == UDS_SUCCESS) {
Packit Service 310c69
    result = result2;
Packit Service 310c69
  }
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
__attribute__((warn_unused_result))
Packit Service 310c69
static int decodeMasterIndexHeader(Buffer *buffer, struct mi006_data *header)
Packit Service 310c69
{
Packit Service 310c69
  int result = getBytesFromBuffer(buffer, sizeof(header->magic),
Packit Service 310c69
                                  &header->magic);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  result = getUInt32LEFromBuffer(buffer, &header->sparseSampleRate);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  result = ASSERT_LOG_ONLY(contentLength(buffer) == 0,
Packit Service 310c69
                           "%zu bytes decoded of %zu expected",
Packit Service 310c69
                           bufferLength(buffer) - contentLength(buffer),
Packit Service 310c69
                           bufferLength(buffer));
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    result = UDS_CORRUPT_COMPONENT;
Packit Service 310c69
  }
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Start restoring the master index from multiple buffered readers
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex      The master index to restore into
Packit Service 310c69
 * @param bufferedReaders  The buffered reader to read the master index from
Packit Service 310c69
 * @param numReaders       The number of buffered readers
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS on success, or an error code on failure
Packit Service 310c69
 **/
Packit Service 310c69
static int startRestoringMasterIndex_006(MasterIndex *masterIndex,
Packit Service 310c69
                                         BufferedReader **bufferedReaders,
Packit Service 310c69
                                         int numReaders)
Packit Service 310c69
{
Packit Service 310c69
  MasterIndex6 *mi6 = container_of(masterIndex, MasterIndex6, common);
Packit Service 310c69
  int result = ASSERT_WITH_ERROR_CODE(masterIndex != NULL, UDS_BAD_STATE,
Packit Service 310c69
                                      "cannot restore to null master index");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  int i;
Packit Service 310c69
  for (i = 0; i < numReaders; i++) {
Packit Service 310c69
    Buffer *buffer;
Packit Service 310c69
    result = makeBuffer(sizeof(struct mi006_data), &buffer);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
    result = readFromBufferedReader(bufferedReaders[i],
Packit Service 310c69
                                    getBufferContents(buffer),
Packit Service 310c69
                                    bufferLength(buffer));
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      freeBuffer(&buffer);
Packit Service 310c69
      return logWarningWithStringError(result,
Packit Service 310c69
                                       "failed to read master index header");
Packit Service 310c69
    }
Packit Service 310c69
    result = resetBufferEnd(buffer, bufferLength(buffer));
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      freeBuffer(&buffer);
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
    struct mi006_data header;
Packit Service 310c69
    result = decodeMasterIndexHeader(buffer, &header);
Packit Service 310c69
    freeBuffer(&buffer);
Packit Service 310c69
    if (result != UDS_SUCCESS) {
Packit Service 310c69
      return result;
Packit Service 310c69
    }
Packit Service 310c69
    if (memcmp(header.magic, MAGIC_MI_START, MAGIC_SIZE) != 0) {
Packit Service 310c69
      return logWarningWithStringError(UDS_CORRUPT_COMPONENT,
Packit Service 310c69
                                       "master index file had bad magic"
Packit Service 310c69
                                       " number");
Packit Service 310c69
    }
Packit Service 310c69
    if (i == 0) {
Packit Service 310c69
      mi6->sparseSampleRate = header.sparseSampleRate;
Packit Service 310c69
    } else if (mi6->sparseSampleRate != header.sparseSampleRate) {
Packit Service 310c69
      logWarningWithStringError(UDS_CORRUPT_COMPONENT,
Packit Service 310c69
                                "Inconsistent sparse sample rate in delta"
Packit Service 310c69
                                " index zone files: %u vs. %u",
Packit Service 310c69
                                mi6->sparseSampleRate,
Packit Service 310c69
                                header.sparseSampleRate);
Packit Service 310c69
        return UDS_CORRUPT_COMPONENT;
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = startRestoringMasterIndex(mi6->miNonHook, bufferedReaders,
Packit Service 310c69
                                     numReaders);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  return startRestoringMasterIndex(mi6->miHook, bufferedReaders, numReaders);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Have all the data been read while restoring a master index from an
Packit Service 310c69
 * input stream?
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex  The master index to restore into
Packit Service 310c69
 *
Packit Service 310c69
 * @return true if all the data are read
Packit Service 310c69
 **/
Packit Service 310c69
static bool isRestoringMasterIndexDone_006(const MasterIndex *masterIndex)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  return (isRestoringMasterIndexDone(mi6->miNonHook)
Packit Service 310c69
          && isRestoringMasterIndexDone(mi6->miHook));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Restore a saved delta list
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex  The master index to restore into
Packit Service 310c69
 * @param dlsi         The DeltaListSaveInfo describing the delta list
Packit Service 310c69
 * @param data         The saved delta list bit stream
Packit Service 310c69
 *
Packit Service 310c69
 * @return error code or UDS_SUCCESS
Packit Service 310c69
 **/
Packit Service 310c69
static int restoreDeltaListToMasterIndex_006(MasterIndex *masterIndex,
Packit Service 310c69
                                             const DeltaListSaveInfo *dlsi,
Packit Service 310c69
                                             const byte data[DELTA_LIST_MAX_BYTE_COUNT])
Packit Service 310c69
{
Packit Service 310c69
  MasterIndex6 *mi6 = container_of(masterIndex, MasterIndex6, common);
Packit Service 310c69
  int result = restoreDeltaListToMasterIndex(mi6->miNonHook, dlsi, data);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    result = restoreDeltaListToMasterIndex(mi6->miHook, dlsi, data);
Packit Service 310c69
  }
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Abort restoring a master index from an input stream.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex  The master index
Packit Service 310c69
 **/
Packit Service 310c69
static void abortRestoringMasterIndex_006(MasterIndex *masterIndex)
Packit Service 310c69
{
Packit Service 310c69
  MasterIndex6 *mi6 = container_of(masterIndex, MasterIndex6, common);
Packit Service 310c69
  abortRestoringMasterIndex(mi6->miNonHook);
Packit Service 310c69
  abortRestoringMasterIndex(mi6->miHook);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Set the open chapter number on a zone.  The master index zone will be
Packit Service 310c69
 * modified to index the proper number of chapters ending with the new open
Packit Service 310c69
 * chapter.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex     The master index
Packit Service 310c69
 * @param zoneNumber      The zone number
Packit Service 310c69
 * @param virtualChapter  The new open chapter number
Packit Service 310c69
 **/
Packit Service 310c69
static void setMasterIndexZoneOpenChapter_006(MasterIndex *masterIndex,
Packit Service 310c69
                                              unsigned int zoneNumber,
Packit Service 310c69
                                              uint64_t virtualChapter)
Packit Service 310c69
{
Packit Service 310c69
  MasterIndex6 *mi6 = container_of(masterIndex, MasterIndex6, common);
Packit Service 310c69
  setMasterIndexZoneOpenChapter(mi6->miNonHook, zoneNumber, virtualChapter);
Packit Service 310c69
Packit Service 310c69
  // We need to prevent a lookupMasterIndexName() happening while we are
Packit Service 310c69
  // changing the open chapter number
Packit Service 310c69
  Mutex *mutex = &mi6->masterZones[zoneNumber].hookMutex;
Packit Service 310c69
  lockMutex(mutex);
Packit Service 310c69
  setMasterIndexZoneOpenChapter(mi6->miHook, zoneNumber, virtualChapter);
Packit Service 310c69
  unlockMutex(mutex);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Set the open chapter number.  The master index will be modified to index
Packit Service 310c69
 * the proper number of chapters ending with the new open chapter.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex     The master index
Packit Service 310c69
 * @param virtualChapter  The new open chapter number
Packit Service 310c69
 **/
Packit Service 310c69
static void setMasterIndexOpenChapter_006(MasterIndex *masterIndex,
Packit Service 310c69
                                          uint64_t virtualChapter)
Packit Service 310c69
{
Packit Service 310c69
  MasterIndex6 *mi6 = container_of(masterIndex, MasterIndex6, common);
Packit Service 310c69
  unsigned int zone;
Packit Service 310c69
  for (zone = 0; zone < mi6->numZones; zone++) {
Packit Service 310c69
    setMasterIndexZoneOpenChapter_006(masterIndex, zone, virtualChapter);
Packit Service 310c69
  }
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Find the master index zone associated with a chunk name
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex The master index
Packit Service 310c69
 * @param name        The chunk name
Packit Service 310c69
 *
Packit Service 310c69
 * @return the zone that the chunk name belongs to
Packit Service 310c69
 **/
Packit Service 310c69
static unsigned int getMasterIndexZone_006(const MasterIndex *masterIndex,
Packit Service 310c69
                                           const UdsChunkName *name)
Packit Service 310c69
{
Packit Service 310c69
  return getMasterIndexZone(getSubIndex(masterIndex, name), name);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Do a quick read-only lookup of the chunk name and return information
Packit Service 310c69
 * needed by the index code to process the chunk name.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex The master index
Packit Service 310c69
 * @param name        The chunk name
Packit Service 310c69
 * @param triage      Information about the chunk name
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
static int lookupMasterIndexName_006(const MasterIndex *masterIndex,
Packit Service 310c69
                                     const UdsChunkName *name,
Packit Service 310c69
                                     MasterIndexTriage *triage)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  triage->isSample = isMasterIndexSample_006(masterIndex, name);
Packit Service 310c69
  triage->inSampledChapter = false;
Packit Service 310c69
  triage->zone = getMasterIndexZone_006(masterIndex, name);
Packit Service 310c69
  int result = UDS_SUCCESS;
Packit Service 310c69
  if (triage->isSample) {
Packit Service 310c69
    Mutex *mutex = &mi6->masterZones[triage->zone].hookMutex;
Packit Service 310c69
    lockMutex(mutex);
Packit Service 310c69
    result = lookupMasterIndexSampledName(mi6->miHook, name, triage);
Packit Service 310c69
    unlockMutex(mutex);
Packit Service 310c69
  }
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Do a quick read-only lookup of the sampled chunk name and return
Packit Service 310c69
 * information needed by the index code to process the chunk name.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex The master index
Packit Service 310c69
 * @param name        The chunk name
Packit Service 310c69
 * @param triage      Information about the chunk name.  The zone and
Packit Service 310c69
 *                    isSample fields are already filled in.  Set
Packit Service 310c69
 *                    inSampledChapter and virtualChapter if the chunk
Packit Service 310c69
 *                    name is found in the index.
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
static int lookupMasterIndexSampledName_006(const MasterIndex *masterIndex
Packit Service 310c69
                                            __attribute__((unused)),
Packit Service 310c69
                                            const UdsChunkName *name
Packit Service 310c69
                                            __attribute__((unused)),
Packit Service 310c69
                                            MasterIndexTriage *triage
Packit Service 310c69
                                            __attribute__((unused)))
Packit Service 310c69
{
Packit Service 310c69
  return ASSERT_WITH_ERROR_CODE(false, UDS_BAD_STATE,
Packit Service 310c69
                                "%s should not be called", __func__);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Find the master index record associated with a block name
Packit Service 310c69
 *
Packit Service 310c69
 * This is always the first routine to be called when dealing with a delta
Packit Service 310c69
 * master index entry.  The fields of the record parameter should be
Packit Service 310c69
 * examined to determine the state of the record:
Packit Service 310c69
 *
Packit Service 310c69
 * If isFound is false, then we did not find an entry for the block
Packit Service 310c69
 * name.  Information is saved in the MasterIndexRecord so that
Packit Service 310c69
 * putMasterIndexRecord() will insert an entry for that block name at
Packit Service 310c69
 * the proper place.
Packit Service 310c69
 *
Packit Service 310c69
 * If isFound is true, then we did find an entry for the block name.
Packit Service 310c69
 * Information is saved in the MasterIndexRecord so that the "chapter"
Packit Service 310c69
 * and "isCollision" fields reflect the entry found.
Packit Service 310c69
 * Calls to removeMasterIndexRecord() will remove the entry, calls to
Packit Service 310c69
 * setMasterIndexRecordChapter() can modify the entry, and calls to
Packit Service 310c69
 * putMasterIndexRecord() can insert a collision record with this
Packit Service 310c69
 * entry.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex The master index to search
Packit Service 310c69
 * @param name        The chunk name
Packit Service 310c69
 * @param record      Set to the info about the record searched for
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
static int getMasterIndexRecord_006(MasterIndex *masterIndex,
Packit Service 310c69
                                    const UdsChunkName *name,
Packit Service 310c69
                                    MasterIndexRecord *record)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  int result;
Packit Service 310c69
  if (isMasterIndexSample_006(masterIndex, name)) {
Packit Service 310c69
    /*
Packit Service 310c69
     * We need to prevent a lookupMasterIndexName() happening while we are
Packit Service 310c69
     * finding the master index record.  Remember that because of lazy LRU
Packit Service 310c69
     * flushing of the master index, getMasterIndexRecord() is not a
Packit Service 310c69
     * read-only operation.
Packit Service 310c69
     */
Packit Service 310c69
    unsigned int zone = getMasterIndexZone(mi6->miHook, name);
Packit Service 310c69
    Mutex *mutex = &mi6->masterZones[zone].hookMutex;
Packit Service 310c69
    lockMutex(mutex);
Packit Service 310c69
    result = getMasterIndexRecord(mi6->miHook, name, record);
Packit Service 310c69
    unlockMutex(mutex);
Packit Service 310c69
    // Remember the mutex so that other operations on the MasterIndexRecord
Packit Service 310c69
    // can use it
Packit Service 310c69
    record->mutex = mutex;
Packit Service 310c69
  } else {
Packit Service 310c69
    result = getMasterIndexRecord(mi6->miNonHook, name, record);
Packit Service 310c69
  }
Packit Service 310c69
  return result;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Get the number of bytes used for master index entries.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex The master index
Packit Service 310c69
 *
Packit Service 310c69
 * @return The number of bytes in use
Packit Service 310c69
 **/
Packit Service 310c69
static size_t getMasterIndexMemoryUsed_006(const MasterIndex *masterIndex)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  return (getMasterIndexMemoryUsed(mi6->miNonHook)
Packit Service 310c69
          + getMasterIndexMemoryUsed(mi6->miHook));
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
/**
Packit Service 310c69
 * Return the master index stats.  There is only one portion of the master
Packit Service 310c69
 * index in this implementation, and we call it the dense portion of the
Packit Service 310c69
 * index.
Packit Service 310c69
 *
Packit Service 310c69
 * @param masterIndex The master index
Packit Service 310c69
 * @param dense       Stats for the dense portion of the index
Packit Service 310c69
 * @param sparse      Stats for the sparse portion of the index
Packit Service 310c69
 **/
Packit Service 310c69
static void getMasterIndexStats_006(const MasterIndex *masterIndex,
Packit Service 310c69
                                    MasterIndexStats *dense,
Packit Service 310c69
                                    MasterIndexStats *sparse)
Packit Service 310c69
{
Packit Service 310c69
  const MasterIndex6 *mi6 = const_container_of(masterIndex, MasterIndex6,
Packit Service 310c69
                                               common);
Packit Service 310c69
  MasterIndexStats dummyStats;
Packit Service 310c69
  getMasterIndexStats(mi6->miNonHook, dense,  &dummyStats);
Packit Service 310c69
  getMasterIndexStats(mi6->miHook,    sparse, &dummyStats);
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
typedef struct {
Packit Service 310c69
  Configuration hookConfig;      // Describe the hook part of the index
Packit Service 310c69
  Geometry      hookGeometry;
Packit Service 310c69
  Configuration nonHookConfig;   // Describe the non-hook part of the index
Packit Service 310c69
  Geometry      nonHookGeometry;
Packit Service 310c69
} SplitConfig;
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
static int splitConfiguration006(const Configuration *config,
Packit Service 310c69
                                 SplitConfig *split)
Packit Service 310c69
{
Packit Service 310c69
  int result
Packit Service 310c69
    = ASSERT_WITH_ERROR_CODE(config->geometry->sparseChaptersPerVolume != 0,
Packit Service 310c69
                             UDS_INVALID_ARGUMENT,
Packit Service 310c69
                             "cannot initialize sparse+dense master index"
Packit Service 310c69
                             " with no sparse chapters");
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  result = ASSERT_WITH_ERROR_CODE(config->sparseSampleRate != 0,
Packit Service 310c69
                                  UDS_INVALID_ARGUMENT,
Packit Service 310c69
                                  "cannot initialize sparse+dense master"
Packit Service 310c69
                                  " index with a sparse sample rate of %u",
Packit Service 310c69
                                  config->sparseSampleRate);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  // Start with copies of the base configuration
Packit Service 310c69
  split->hookConfig = *config;
Packit Service 310c69
  split->hookGeometry = *config->geometry;
Packit Service 310c69
  split->hookConfig.geometry = &split->hookGeometry;
Packit Service 310c69
  split->nonHookConfig   = *config;
Packit Service 310c69
  split->nonHookGeometry = *config->geometry;
Packit Service 310c69
  split->nonHookConfig.geometry = &split->nonHookGeometry;
Packit Service 310c69
Packit Service 310c69
  uint64_t sampleRate        = config->sparseSampleRate;
Packit Service 310c69
  uint64_t numChapters       = config->geometry->chaptersPerVolume;
Packit Service 310c69
  uint64_t numSparseChapters = config->geometry->sparseChaptersPerVolume;
Packit Service 310c69
  uint64_t numDenseChapters  = numChapters - numSparseChapters;
Packit Service 310c69
  uint64_t sampleRecords = config->geometry->recordsPerChapter / sampleRate;
Packit Service 310c69
Packit Service 310c69
  // Adjust the number of records indexed for each chapter
Packit Service 310c69
  split->hookGeometry.recordsPerChapter     = sampleRecords;
Packit Service 310c69
  split->nonHookGeometry.recordsPerChapter -= sampleRecords;
Packit Service 310c69
Packit Service 310c69
  // Adjust the number of chapters indexed
Packit Service 310c69
  split->hookGeometry.sparseChaptersPerVolume    = 0;
Packit Service 310c69
  split->nonHookGeometry.sparseChaptersPerVolume = 0;
Packit Service 310c69
  split->nonHookGeometry.chaptersPerVolume       = numDenseChapters;
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
int computeMasterIndexSaveBytes006(const Configuration *config,
Packit Service 310c69
                                   size_t *numBytes)
Packit Service 310c69
{
Packit Service 310c69
  SplitConfig split;
Packit Service 310c69
  int result = splitConfiguration006(config, &split);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  size_t hookBytes, nonHookBytes;
Packit Service 310c69
  result = computeMasterIndexSaveBytes005(&split.hookConfig, &hookBytes);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  result = computeMasterIndexSaveBytes005(&split.nonHookConfig, &nonHookBytes);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
  // Saving a MasterIndex006 needs a header plus the hook index plus the
Packit Service 310c69
  // non-hook index
Packit Service 310c69
  *numBytes = sizeof(struct mi006_data) + hookBytes + nonHookBytes;
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/***********************************************************************/
Packit Service 310c69
int makeMasterIndex006(const Configuration *config, unsigned int numZones,
Packit Service 310c69
                       uint64_t volumeNonce, MasterIndex **masterIndex)
Packit Service 310c69
{
Packit Service 310c69
  SplitConfig split;
Packit Service 310c69
  int result = splitConfiguration006(config, &split);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  MasterIndex6 *mi6;
Packit Service 310c69
  result = ALLOCATE(1, MasterIndex6, "master index", &mi6;;
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  mi6->common.abortRestoringMasterIndex     = abortRestoringMasterIndex_006;
Packit Service 310c69
  mi6->common.abortSavingMasterIndex        = abortSavingMasterIndex_006;
Packit Service 310c69
  mi6->common.finishSavingMasterIndex       = finishSavingMasterIndex_006;
Packit Service 310c69
  mi6->common.freeMasterIndex               = freeMasterIndex_006;
Packit Service 310c69
  mi6->common.getMasterIndexMemoryUsed      = getMasterIndexMemoryUsed_006;
Packit Service 310c69
  mi6->common.getMasterIndexRecord          = getMasterIndexRecord_006;
Packit Service 310c69
  mi6->common.getMasterIndexStats           = getMasterIndexStats_006;
Packit Service 310c69
  mi6->common.getMasterIndexZone            = getMasterIndexZone_006;
Packit Service 310c69
  mi6->common.isMasterIndexSample           = isMasterIndexSample_006;
Packit Service 310c69
  mi6->common.isRestoringMasterIndexDone    = isRestoringMasterIndexDone_006;
Packit Service 310c69
  mi6->common.isSavingMasterIndexDone       = isSavingMasterIndexDone_006;
Packit Service 310c69
  mi6->common.lookupMasterIndexName         = lookupMasterIndexName_006;
Packit Service 310c69
  mi6->common.lookupMasterIndexSampledName  = lookupMasterIndexSampledName_006;
Packit Service 310c69
  mi6->common.restoreDeltaListToMasterIndex = restoreDeltaListToMasterIndex_006;
Packit Service 310c69
  mi6->common.setMasterIndexOpenChapter     = setMasterIndexOpenChapter_006;
Packit Service 310c69
  mi6->common.setMasterIndexTag             = setMasterIndexTag_006;
Packit Service 310c69
  mi6->common.setMasterIndexZoneOpenChapter = setMasterIndexZoneOpenChapter_006;
Packit Service 310c69
  mi6->common.startRestoringMasterIndex     = startRestoringMasterIndex_006;
Packit Service 310c69
  mi6->common.startSavingMasterIndex        = startSavingMasterIndex_006;
Packit Service 310c69
Packit Service 310c69
  mi6->numZones         = numZones;
Packit Service 310c69
  mi6->sparseSampleRate = config->sparseSampleRate;
Packit Service 310c69
Packit Service 310c69
  result = ALLOCATE(numZones, MasterIndexZone, "master index zones",
Packit Service 310c69
                    &mi6->masterZones);
Packit Service 310c69
  unsigned int zone;
Packit Service 310c69
  for (zone = 0; zone < numZones; zone++) {
Packit Service 310c69
    if (result == UDS_SUCCESS) {
Packit Service 310c69
      result = initMutex(&mi6->masterZones[zone].hookMutex);
Packit Service 310c69
    }
Packit Service 310c69
  }
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    freeMasterIndex_006(&mi6->common);
Packit Service 310c69
    return result;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  result = makeMasterIndex005(&split.nonHookConfig, numZones, volumeNonce,
Packit Service 310c69
                              &mi6->miNonHook);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    freeMasterIndex_006(&mi6->common);
Packit Service 310c69
    return logErrorWithStringError(result,
Packit Service 310c69
                                   "Error creating non hook master index");
Packit Service 310c69
  }
Packit Service 310c69
  setMasterIndexTag(mi6->miNonHook, 'd');
Packit Service 310c69
Packit Service 310c69
  result = makeMasterIndex005(&split.hookConfig, numZones, volumeNonce,
Packit Service 310c69
                              &mi6->miHook);
Packit Service 310c69
  if (result != UDS_SUCCESS) {
Packit Service 310c69
    freeMasterIndex_006(&mi6->common);
Packit Service 310c69
    return logErrorWithStringError(result,
Packit Service 310c69
                                   "Error creating hook master index");
Packit Service 310c69
  }
Packit Service 310c69
  setMasterIndexTag(mi6->miHook, 's');
Packit Service 310c69
Packit Service 310c69
  *masterIndex = &mi6->common;
Packit Service 310c69
  return UDS_SUCCESS;
Packit Service 310c69
}