Blame source/uds/cachedChapterIndex.h

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/cachedChapterIndex.h#3 $
Packit Service 310c69
 */
Packit Service 310c69
Packit Service 310c69
#ifndef CACHED_CHAPTER_INDEX_H
Packit Service 310c69
#define CACHED_CHAPTER_INDEX_H
Packit Service 310c69
Packit Service 310c69
#include "chapterIndex.h"
Packit Service 310c69
#include "common.h"
Packit Service 310c69
#include "compiler.h"
Packit Service 310c69
#include "cpu.h"
Packit Service 310c69
#include "geometry.h"
Packit Service 310c69
#include "indexPageMap.h"
Packit Service 310c69
#include "typeDefs.h"
Packit Service 310c69
#include "volume.h"
Packit Service 310c69
#include "volumeStore.h"
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * These counters are essentially fields of the CachedChapterIndex, but are
Packit Service 310c69
 * segregated into this structure because they are frequently modified. They
Packit Service 310c69
 * are grouped and aligned to keep them on different cache lines from the
Packit Service 310c69
 * chapter fields that are accessed far more often than they are updated.
Packit Service 310c69
 **/
Packit Service 310c69
struct __attribute__((aligned(CACHE_LINE_BYTES))) cachedIndexCounters {
Packit Service 310c69
  /** the total number of search hits since this chapter was cached */
Packit Service 310c69
  uint64_t searchHits;
Packit Service 310c69
Packit Service 310c69
  /** the total number of search misses since this chapter was cached */
Packit Service 310c69
  uint64_t searchMisses;
Packit Service 310c69
Packit Service 310c69
  /** the number of consecutive search misses since the last cache hit */
Packit Service 310c69
  uint64_t consecutiveMisses;
Packit Service 310c69
};
Packit Service 310c69
typedef struct cachedIndexCounters CachedIndexCounters;
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * CachedChapterIndex is the structure for a cache entry, representing a
Packit Service 310c69
 * single cached chapter index in the sparse chapter index cache.
Packit Service 310c69
 **/
Packit Service 310c69
struct __attribute__((aligned(CACHE_LINE_BYTES))) cachedChapterIndex {
Packit Service 310c69
  /*
Packit Service 310c69
   * The virtual chapter number of the cached chapter index. UINT64_MAX means
Packit Service 310c69
   * this cache entry is unused. Must only be modified in the critical section
Packit Service 310c69
   * in updateSparseCache().
Packit Service 310c69
   */
Packit Service 310c69
  uint64_t          virtualChapter;
Packit Service 310c69
Packit Service 310c69
  /* The number of index pages in a chapter */
Packit Service 310c69
  unsigned int      indexPagesCount;
Packit Service 310c69
Packit Service 310c69
  /*
Packit Service 310c69
   * This flag is mutable between cache updates, but it rarely changes and
Packit Service 310c69
   * is frequently accessed, so it groups with the immutable fields.
Packit Service 310c69
   *
Packit Service 310c69
   * If set, skip the chapter when searching the entire cache.  This flag is
Packit Service 310c69
   * just a performance optimization.  If we do not see a recent change to it,
Packit Service 310c69
   * it will be corrected when we pass through a memory barrier while getting
Packit Service 310c69
   * the next request from the queue.  So we may do one extra search of the
Packit Service 310c69
   * chapter index, or miss one deduplication opportunity.
Packit Service 310c69
   */
Packit Service 310c69
  bool              skipSearch;
Packit Service 310c69
Packit Service 310c69
  // These pointers are immutable during the life of the cache. The contents
Packit Service 310c69
  // of the arrays change when the cache entry is replaced.
Packit Service 310c69
Packit Service 310c69
  /* pointer to a cache-aligned array of ChapterIndexPages */
Packit Service 310c69
  DeltaIndexPage *indexPages;
Packit Service 310c69
Packit Service 310c69
  /* pointer to an array of VolumePages containing the index pages */
Packit Service 310c69
  struct volume_page *volumePages;
Packit Service 310c69
Packit Service 310c69
  // The cache-aligned counters change often and are placed at the end of the
Packit Service 310c69
  // structure to prevent false sharing with the more stable fields above.
Packit Service 310c69
Packit Service 310c69
  /* counter values updated by the thread servicing zone zero */
Packit Service 310c69
  CachedIndexCounters counters;
Packit Service 310c69
};
Packit Service 310c69
typedef struct cachedChapterIndex CachedChapterIndex;
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Initialize a CachedChapterIndex, allocating the memory for the array of
Packit Service 310c69
 * ChapterIndexPages and the raw index page data. The chapter index will be
Packit Service 310c69
 * marked as unused (virtualChapter == UINT64_MAX).
Packit Service 310c69
 *
Packit Service 310c69
 * @param chapter   the chapter index cache entry to initialize
Packit Service 310c69
 * @param geometry  the geometry governing the volume
Packit Service 310c69
 **/
Packit Service 310c69
int initializeCachedChapterIndex(CachedChapterIndex *chapter,
Packit Service 310c69
                                 const Geometry     *geometry)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Destroy a CachedChapterIndex, freeing the memory allocated for the
Packit Service 310c69
 * ChapterIndexPages and raw index page data.
Packit Service 310c69
 *
Packit Service 310c69
 * @param chapter   the chapter index cache entry to destroy
Packit Service 310c69
 **/
Packit Service 310c69
void destroyCachedChapterIndex(CachedChapterIndex *chapter);
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Assign a new value to the skipSearch flag of a cached chapter index.
Packit Service 310c69
 *
Packit Service 310c69
 * @param chapter     the chapter index cache entry to modify
Packit Service 310c69
 * @param skipSearch  the new value of the skipSearch falg
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE void setSkipSearch(CachedChapterIndex *chapter, bool skipSearch)
Packit Service 310c69
{
Packit Service 310c69
  // Explicitly check if the field is set so we don't keep dirtying the memory
Packit Service 310c69
  // cache line on continued search hits.
Packit Service 310c69
  if (READ_ONCE(chapter->skipSearch) != skipSearch) {
Packit Service 310c69
    WRITE_ONCE(chapter->skipSearch, skipSearch);
Packit Service 310c69
  }
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Check if a cached sparse chapter index should be skipped over in the search
Packit Service 310c69
 * for a chunk name. Filters out unused, invalid, disabled, and irrelevant
Packit Service 310c69
 * cache entries.
Packit Service 310c69
 *
Packit Service 310c69
 * @param zone            the zone doing the check
Packit Service 310c69
 * @param chapter         the cache entry search candidate
Packit Service 310c69
 * @param virtualChapter  the virtualChapter containing a hook, or UINT64_MAX
Packit Service 310c69
 *                        if searching the whole cache for a non-hook
Packit Service 310c69
 *
Packit Service 310c69
 * @return true if the provided chapter index should be skipped
Packit Service 310c69
 **/
Packit Service 310c69
static INLINE bool shouldSkipChapterIndex(const IndexZone *zone,
Packit Service 310c69
                                          const CachedChapterIndex *chapter,
Packit Service 310c69
                                          uint64_t virtualChapter)
Packit Service 310c69
{
Packit Service 310c69
  // Don't search unused entries (contents undefined) or invalid entries
Packit Service 310c69
  // (the chapter is no longer the zone's view of the volume).
Packit Service 310c69
  if ((chapter->virtualChapter == UINT64_MAX)
Packit Service 310c69
      || (chapter->virtualChapter < zone->oldestVirtualChapter)) {
Packit Service 310c69
    return true;
Packit Service 310c69
  }
Packit Service 310c69
Packit Service 310c69
  if (virtualChapter != UINT64_MAX) {
Packit Service 310c69
    // If the caller specified a virtual chapter, only search the cache
Packit Service 310c69
    // entry containing that chapter.
Packit Service 310c69
    return (virtualChapter != chapter->virtualChapter);
Packit Service 310c69
  } else {
Packit Service 310c69
    // When searching the entire cache, save time by skipping over chapters
Packit Service 310c69
    // that have had too many consecutive misses.
Packit Service 310c69
    return READ_ONCE(chapter->skipSearch);
Packit Service 310c69
  }
Packit Service 310c69
}
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Cache a chapter index, reading all the index pages from the volume and
Packit Service 310c69
 * initializing the array of ChapterIndexPages in the cache entry to represent
Packit Service 310c69
 * them. The virtualChapter field of the cache entry will be set to UINT64_MAX
Packit Service 310c69
 * if there is any error since the remaining mutable fields will be in an
Packit Service 310c69
 * undefined state.
Packit Service 310c69
 *
Packit Service 310c69
 * @param chapter         the chapter index cache entry to replace
Packit Service 310c69
 * @param virtualChapter  the virtual chapter number of the index to read
Packit Service 310c69
 * @param volume          the volume containing the chapter index
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
int cacheChapterIndex(CachedChapterIndex *chapter,
Packit Service 310c69
                      uint64_t            virtualChapter,
Packit Service 310c69
                      const Volume       *volume)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
/**
Packit Service 310c69
 * Search a single cached sparse chapter index for a chunk name, returning the
Packit Service 310c69
 * record page number that may contain the name.
Packit Service 310c69
 *
Packit Service 310c69
 * @param [in]  chapter        the cache entry for the chapter to search
Packit Service 310c69
 * @param [in]  geometry       the geometry governing the volume
Packit Service 310c69
 * @param [in]  indexPageMap   the index page number map for the volume
Packit Service 310c69
 * @param [in]  name           the chunk name to search for
Packit Service 310c69
 * @param [out] recordPagePtr  the record page number of a match, else
Packit Service 310c69
 *                             NO_CHAPTER_INDEX_ENTRY if nothing matched
Packit Service 310c69
 *
Packit Service 310c69
 * @return UDS_SUCCESS or an error code
Packit Service 310c69
 **/
Packit Service 310c69
int searchCachedChapterIndex(CachedChapterIndex *chapter,
Packit Service 310c69
                             const Geometry     *geometry,
Packit Service 310c69
                             const IndexPageMap *indexPageMap,
Packit Service 310c69
                             const UdsChunkName *name,
Packit Service 310c69
                             int                *recordPagePtr)
Packit Service 310c69
  __attribute__((warn_unused_result));
Packit Service 310c69
Packit Service 310c69
#endif /* CACHED_CHAPTER_INDEX_H */