<commit_before>/**
 * This file is part of the CernVM File System.
 */

#ifndef OBJECT_FETCHER_H
#define OBJECT_FETCHER_H

#include <string>

#include "catalog.h"
#include "download.h"
#include "history_sqlite.h"
#include "manifest.h"
#include "manifest_fetch.h"
#include "signature.h"

/**
 * Trait class to define the concrete object types produced by the methods of
 * concrete instantiations of AbstractObjectFetcher<>. For each implementation
 * of AbstractObjectFetcher<> one needs to provide a specialisation of this
 * trait. Note that this specialisation can be templated with the actual para-
 * meters, hence the parameter space does not explode.
 *
 * See: http://stackoverflow.com/questions/6006614/
 *      c-static-polymorphism-crtp-and-using-typedefs-from-derived-classes
 */
template <class ConcreteObjectFetcherT>
struct object_fetcher_traits;

/**
 * This is the default class implementing the data object fetching strategy. It
 * is meant to be used when CVMFS specific data structures need to be downloaded
 * from a backend storage of a repository.
 *
 * ObjectFetchers are supposed to be configured for one specific repository. How
 * this is done depends on the concrete implementation of this base class.
 *
 * It abstracts all accesses to external file or HTTP resources and gathers this
 * access logic in one central point. This also comes in handy when unit testing
 * components that depend on downloading CVMFS data structures from a repository
 * backend storage like CatalogTraversal<> or GarbageCollector<>.
 */
template <class DerivedT>
class AbstractObjectFetcher {
 public:
  typedef typename object_fetcher_traits<DerivedT>::CatalogTN CatalogTN;
  typedef typename object_fetcher_traits<DerivedT>::HistoryTN HistoryTN;

  static const std::string kManifestFilename;

 public:
  /**
   * Fetches and opens the manifest of the repository this object fetcher is
   * configured for. Note that the user is responsible to clean up this object.
   *
   * @return  a manifest object or NULL on error
   */
  manifest::Manifest* FetchManifest() {
    return static_cast<DerivedT*>(this)->FetchManifest();
  }

  /**
   * Downloads and opens (read-only) a history database. Note that the user is
   * responsible to remove the history object after usage.
   *
   * @param history_hash  (optional) the content hash of the history database
   *                                 if left blank, the latest one is downloaded
   * @return              a history database object or NULL on error
   */
  HistoryTN* FetchHistory(const shash::Any &history_hash = shash::Any()) {
    // retrieve the current HEAD history hash (if nothing else given)
    shash::Any effective_history_hash = (! history_hash.IsNull())
            ? history_hash
            : GetHistoryHash();

    // download the history hash
    std::string path;
    if (effective_history_hash.IsNull() ||
        ! Fetch(effective_history_hash, shash::kSuffixHistory, &path)) {
      return NULL;
    }

    // open the history file
    return HistoryTN::Open(path);
  }

  /**
   * Downloads and opens a catalog. Note that the user is responsible to remove
   * the catalog object after usage.
   *
   * @param catalog_hash   the content hash of the catalog object
   * @param catalog_path   the root_path the catalog is mounted on
   * @param is_nested      a hint if the catalog to be loaded is a nested one
   * @param parent         (optional) parent catalog of the requested catalog
   * @return               a catalog object or NULL on error
   */
  CatalogTN* FetchCatalog(const shash::Any  &catalog_hash,
                          const std::string &catalog_path,
                          const bool         is_nested = false,
                                CatalogTN   *parent    = NULL) {
    assert (! catalog_hash.IsNull());

    std::string path;
    if (! Fetch(catalog_hash, shash::kSuffixCatalog, &path)) {
      return NULL;
    }

    return CatalogTN::AttachFreely(catalog_path,
                                   path,
                                   catalog_hash,
                                   parent,
                                   is_nested);
  }

 public:
  bool HasHistory() {
    shash::Any history_hash = GetHistoryHash();
    return ! history_hash.IsNull();
  }

 protected:
  /**<commit_msg>ObjectFetcher<> produces auto cleaned objects<commit_after>/**
 * This file is part of the CernVM File System.
 */

#ifndef OBJECT_FETCHER_H
#define OBJECT_FETCHER_H

#include <string>

#include "catalog.h"
#include "download.h"
#include "history_sqlite.h"
#include "manifest.h"
#include "manifest_fetch.h"
#include "signature.h"

/**
 * Trait class to define the concrete object types produced by the methods of
 * concrete instantiations of AbstractObjectFetcher<>. For each implementation
 * of AbstractObjectFetcher<> one needs to provide a specialisation of this
 * trait. Note that this specialisation can be templated with the actual para-
 * meters, hence the parameter space does not explode.
 *
 * See: http://stackoverflow.com/questions/6006614/
 *      c-static-polymorphism-crtp-and-using-typedefs-from-derived-classes
 */
template <class ConcreteObjectFetcherT>
struct object_fetcher_traits;

/**
 * This is the default class implementing the data object fetching strategy. It
 * is meant to be used when CVMFS specific data structures need to be downloaded
 * from a backend storage of a repository.
 *
 * ObjectFetchers are supposed to be configured for one specific repository. How
 * this is done depends on the concrete implementation of this base class. When
 * a concrete implementation of ObjectFetcher<> needs to deal with files on the
 * local file system it is obliged to take measures for proper cleanup of those
 * files after usage.
 *
 * It abstracts all accesses to external file or HTTP resources and gathers this
 * access logic in one central point. This also comes in handy when unit testing
 * components that depend on downloading CVMFS data structures from a repository
 * backend storage like CatalogTraversal<> or GarbageCollector<>.
 */
template <class DerivedT>
class AbstractObjectFetcher {
 public:
  typedef typename object_fetcher_traits<DerivedT>::CatalogTN CatalogTN;
  typedef typename object_fetcher_traits<DerivedT>::HistoryTN HistoryTN;

  static const std::string kManifestFilename;

 public:
  /**
   * Fetches and opens the manifest of the repository this object fetcher is
   * configured for. Note that the user is responsible to clean up this object.
   *
   * @return  a manifest object or NULL on error
   */
  manifest::Manifest* FetchManifest() {
    return static_cast<DerivedT*>(this)->FetchManifest();
  }

  /**
   * Downloads and opens (read-only) a history database. Note that the user is
   * responsible to remove the history object after usage.
   *
   * @param history_hash  (optional) the content hash of the history database
   *                                 if left blank, the latest one is downloaded
   * @return              a history database object or NULL on error
   */
  HistoryTN* FetchHistory(const shash::Any &history_hash = shash::Any()) {
    // retrieve the current HEAD history hash (if nothing else given)
    shash::Any effective_history_hash = (! history_hash.IsNull())
            ? history_hash
            : GetHistoryHash();

    // download the history hash
    std::string path;
    if (effective_history_hash.IsNull() ||
        ! Fetch(effective_history_hash, shash::kSuffixHistory, &path)) {
      return NULL;
    }

    // open the history file
    HistoryTN *history = HistoryTN::Open(path);
    if (NULL != history) {
      history->TakeFileOwnership();
    }

    return history;
  }

  /**
   * Downloads and opens a catalog. Note that the user is responsible to remove
   * the catalog object after usage.
   *
   * @param catalog_hash   the content hash of the catalog object
   * @param catalog_path   the root_path the catalog is mounted on
   * @param is_nested      a hint if the catalog to be loaded is a nested one
   * @param parent         (optional) parent catalog of the requested catalog
   * @return               a catalog object or NULL on error
   */
  CatalogTN* FetchCatalog(const shash::Any  &catalog_hash,
                          const std::string &catalog_path,
                          const bool         is_nested = false,
                                CatalogTN   *parent    = NULL) {
    assert (! catalog_hash.IsNull());

    std::string path;
    if (! Fetch(catalog_hash, shash::kSuffixCatalog, &path)) {
      return NULL;
    }

    CatalogTN *catalog = CatalogTN::AttachFreely(catalog_path,
                                                 path,
                                                 catalog_hash,
                                                 parent,
                                                 is_nested);
    if (NULL != catalog) {
      catalog->TakeFileOwnership();
    }

    return catalog;
  }

 public:
  bool HasHistory() {
    shash::Any history_hash = GetHistoryHash();
    return ! history_hash.IsNull();
  }

 protected:
  /**
{'fraction_non_alphanumeric': 0.07558330594807755, 'fraction_numerical': 0.0015335743235841822, 'mean_word_length': 2.74487284659557, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4375877', 'n_tokens_mistral': 2446, 'n_tokens_neox': 2370, 'n_words': 916}