/* * Copyright (c) 2020 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: //eng/uds-releases/jasper/src/uds/masterIndexOps.c#4 $ */ #include "masterIndexOps.h" #include "compiler.h" #include "errors.h" #include "indexComponent.h" #include "logger.h" #include "masterIndex005.h" #include "masterIndex006.h" #include "memoryAlloc.h" #include "permassert.h" #include "uds.h" #include "zone.h" /**********************************************************************/ static INLINE bool usesSparse(const Configuration *config) { return config->geometry->sparseChaptersPerVolume > 0; } /**********************************************************************/ void getMasterIndexCombinedStats(const MasterIndex *masterIndex, MasterIndexStats *stats) { MasterIndexStats dense, sparse; getMasterIndexStats(masterIndex, &dense, &sparse); stats->memoryAllocated = dense.memoryAllocated + sparse.memoryAllocated; stats->rebalanceTime = dense.rebalanceTime + sparse.rebalanceTime; stats->rebalanceCount = dense.rebalanceCount + sparse.rebalanceCount; stats->recordCount = dense.recordCount + sparse.recordCount; stats->collisionCount = dense.collisionCount + sparse.collisionCount; stats->discardCount = dense.discardCount + sparse.discardCount; stats->overflowCount = dense.overflowCount + sparse.overflowCount; stats->numLists = dense.numLists + sparse.numLists; stats->earlyFlushes = dense.earlyFlushes + sparse.earlyFlushes; } /**********************************************************************/ int makeMasterIndex(const Configuration *config, unsigned int numZones, uint64_t volumeNonce, MasterIndex **masterIndex) { if (usesSparse(config)) { return makeMasterIndex006(config, numZones, volumeNonce, masterIndex); } else { return makeMasterIndex005(config, numZones, volumeNonce, masterIndex); } } /**********************************************************************/ int computeMasterIndexSaveBlocks(const Configuration *config, size_t blockSize, uint64_t *blockCount) { size_t numBytes; int result = (usesSparse(config) ? computeMasterIndexSaveBytes006(config, &numBytes) : computeMasterIndexSaveBytes005(config, &numBytes)); if (result != UDS_SUCCESS) { return result; } numBytes += sizeof(DeltaListSaveInfo); *blockCount = (numBytes + blockSize - 1) / blockSize + MAX_ZONES; return UDS_SUCCESS; } /**********************************************************************/ static int readMasterIndex(ReadPortal *portal) { MasterIndex *masterIndex = indexComponentContext(portal->component); unsigned int numZones = portal->zones; if (numZones > MAX_ZONES) { return logErrorWithStringError(UDS_BAD_STATE, "zone count %u must not exceed MAX_ZONES", numZones); } BufferedReader *readers[MAX_ZONES]; unsigned int z; for (z = 0; z < numZones; ++z) { int result = getBufferedReaderForPortal(portal, z, &readers[z]); if (result != UDS_SUCCESS) { return logErrorWithStringError(result, "cannot read component for zone %u", z); } } return restoreMasterIndex(readers, numZones, masterIndex); } /**********************************************************************/ static int writeMasterIndex(IndexComponent *component, BufferedWriter *writer, unsigned int zone, IncrementalWriterCommand command, bool *completed) { MasterIndex *masterIndex = indexComponentContext(component); bool isComplete = false; int result = UDS_SUCCESS; switch (command) { case IWC_START: result = startSavingMasterIndex(masterIndex, zone, writer); isComplete = result != UDS_SUCCESS; break; case IWC_CONTINUE: isComplete = isSavingMasterIndexDone(masterIndex, zone); break; case IWC_FINISH: result = finishSavingMasterIndex(masterIndex, zone); if (result == UDS_SUCCESS) { result = writeGuardDeltaList(writer); } isComplete = true; break; case IWC_ABORT: result = abortSavingMasterIndex(masterIndex, zone); isComplete = true; break; default: result = logWarningWithStringError(UDS_INVALID_ARGUMENT, "Invalid writer command"); break; } if (completed != NULL) { *completed = isComplete; } return result; } /**********************************************************************/ static const IndexComponentInfo MASTER_INDEX_INFO_DATA = { .kind = RL_KIND_MASTER_INDEX, .name = "master index", .saveOnly = false, .chapterSync = false, .multiZone = true, .ioStorage = true, .loader = readMasterIndex, .saver = NULL, .incremental = writeMasterIndex, }; const IndexComponentInfo *const MASTER_INDEX_INFO = &MASTER_INDEX_INFO_DATA; /**********************************************************************/ static int restoreMasterIndexBody(BufferedReader **bufferedReaders, unsigned int numReaders, MasterIndex *masterIndex, byte dlData[DELTA_LIST_MAX_BYTE_COUNT]) { // Start by reading the "header" section of the stream int result = startRestoringMasterIndex(masterIndex, bufferedReaders, numReaders); if (result != UDS_SUCCESS) { return result; } // Loop to read the delta lists, stopping when they have all been processed. unsigned int z; for (z = 0; z < numReaders; z++) { for (;;) { DeltaListSaveInfo dlsi; result = readSavedDeltaList(&dlsi, dlData, bufferedReaders[z]); if (result == UDS_END_OF_FILE) { break; } else if (result != UDS_SUCCESS) { abortRestoringMasterIndex(masterIndex); return result; } result = restoreDeltaListToMasterIndex(masterIndex, &dlsi, dlData); if (result != UDS_SUCCESS) { abortRestoringMasterIndex(masterIndex); return result; } } } if (!isRestoringMasterIndexDone(masterIndex)) { abortRestoringMasterIndex(masterIndex); return logWarningWithStringError(UDS_CORRUPT_COMPONENT, "incomplete delta list data"); } return UDS_SUCCESS; } /**********************************************************************/ int restoreMasterIndex(BufferedReader **bufferedReaders, unsigned int numReaders, MasterIndex *masterIndex) { byte *dlData; int result = ALLOCATE(DELTA_LIST_MAX_BYTE_COUNT, byte, __func__, &dlData); if (result != UDS_SUCCESS) { return result; } result = restoreMasterIndexBody(bufferedReaders, numReaders, masterIndex, dlData); FREE(dlData); return result; }