Example #1
0
  bool scan_manager_t::find_source_names(const std::string& file_hash,
                         source_names_t& source_names) const {

    if (file_hash.size() == 0) {
      std::cerr << "Error: find_source_names called with empty file_hash\n";
      return false;
    }

    // read source_id
    uint64_t source_id;
    bool has_id = lmdb_source_id_manager->find(file_hash, source_id);
    if (has_id == false) {
      // no source ID for this file_hash
      source_names.clear();
      return false;
    } else {
      // source
      return lmdb_source_name_manager->find(source_id, source_names);
    }
  }
  /**
   * Find source names, false on no source ID.
   */
  bool find(const uint64_t source_id,
            source_names_t& names) const {

    // get context
    hashdb::lmdb_context_t context(env, false, true);
    context.open();

    // set key
    uint8_t key_start[10];
    uint8_t* key_p = key_start;
    key_p = lmdb_helper::encode_uint64_t(source_id, key_p);
    const size_t key_size = key_p - key_start;
    context.key.mv_size = key_size;
    context.key.mv_data = key_start;
    context.data.mv_size = 0;
    context.data.mv_data = NULL;

    // set the cursor to this key
    int rc = mdb_cursor_get(context.cursor, &context.key, &context.data,
                            MDB_SET_KEY);
#ifdef DEBUG_LMDB_SOURCE_NAME_MANAGER_HPP
print_mdb_val("source_name_manager find start at key", context.key);
#endif

    // note if source ID was found
    bool source_id_found = (rc == 0);

    // read name pairs while data available and key matches
    names.clear();
    while (rc == 0 &&
           context.key.mv_size == key_size &&
           memcmp(context.key.mv_data, key_start, key_size) == 0) {

#ifdef DEBUG_LMDB_SOURCE_NAME_MANAGER_HPP
print_mdb_val("source_name_manager find key", context.key);
print_mdb_val("source_name_manager find data", context.data);
#endif
      // read repository_name, filename pair into names
      const uint8_t* p = static_cast<uint8_t*>(context.data.mv_data);
      const uint8_t* const p_stop = p + context.data.mv_size;
      uint64_t repository_name_size;
      const uint8_t* const rn_p = lmdb_helper::decode_uint64_t(
                                           p, repository_name_size);
      p = rn_p + repository_name_size;
      uint64_t filename_size;
      const uint8_t* const fn_p = lmdb_helper::decode_uint64_t(
                                         p, filename_size);
      p = fn_p + filename_size;
      names.insert(source_name_t(
              std::string(reinterpret_cast<const char*>(rn_p),
                          repository_name_size),
              std::string(reinterpret_cast<const char*>(fn_p),
                          filename_size)));

      // validate that the decoding was properly consumed
      if (p != p_stop) {
        std::cerr << "data decode error in LMDB source name store\n";
        assert(0);
      }

      // next
      rc = mdb_cursor_get(context.cursor, &context.key, &context.data,
                          MDB_NEXT);
    }

    // make sure rc is valid
    if (rc == 0 || rc == MDB_NOTFOUND) {
      // good, LMDB worked correctly
      context.close();
      return source_id_found;

    } else {
      // invalid rc
      std::cerr << "LMDB error: " << mdb_strerror(rc) << "\n";
      assert(0);
      return false; // for mingw
    }
  }