示例#1
0
void Map::optimize(const fs::path& directory, const fs::path& target,
                   const Options& options) {
  const auto descriptor = internal::Descriptor::readFromDirectory(directory);
  checkDescriptor(descriptor, directory);
  fs::path prefix = directory / getPartitionPrefix(0);
  const Stats stats = internal::Partition::stats(prefix);
  Options new_options = options;
  new_options.error_if_exists = true;
  new_options.create_if_missing = true;
  if (options.block_size == 0) {
    new_options.block_size = stats.block_size;
  }
  if (options.num_partitions == 0) {
    new_options.num_partitions = descriptor.num_partitions;
  }
  Map new_map(target, new_options);

  for (int i = 0; i < descriptor.num_partitions; i++) {
    prefix = directory / getPartitionPrefix(i);
    if (options.verbose) {
      mt::log() << "Optimizing partition " << (i + 1) << " of "
                << descriptor.num_partitions << std::endl;
    }
    if (options.compare) {
      Arena arena;
      std::vector<Slice> values;
      internal::Partition::forEachEntry(
          prefix, [&new_map, &arena, &options, &values](const Slice& key,
                                                        Iterator* iter) {
            arena.deallocateAll();
            values.reserve(iter->available());
            values.clear();
            while (iter->hasNext()) {
              values.push_back(iter->next().makeCopy(&arena));
            }
            std::sort(values.begin(), values.end(), options.compare);
            for (const auto& value : values) {
              new_map.put(key, value);
            }
          });
    } else {
      internal::Partition::forEachEntry(
          prefix, [&new_map](const Slice& key, Iterator* iter) {
            while (iter->hasNext()) {
              new_map.put(key, iter->next());
            }
          });
    }
  }
}
示例#2
0
Map::Map(const fs::path& directory, const Options& options)
    : dlock_(directory.string()) {
  checkOptions(options);
  Options partition_options;
  partition_options.readonly = options.readonly;
  partition_options.block_size = options.block_size;
  internal::Descriptor descriptor;
  if (internal::Descriptor::tryReadFromDirectory(directory, &descriptor)) {
    checkDescriptor(descriptor, directory);
    mt::Check::isFalse(options.error_if_exists, "Map in %s already exists",
                       fs::absolute(directory).c_str());
    partitions_.resize(descriptor.num_partitions);

  } else {
    mt::Check::isTrue(options.create_if_missing, "Map in %s does not exist",
                      fs::absolute(directory).c_str());
    partitions_.resize(mt::nextPrime(options.num_partitions));
    descriptor.map_type = internal::Descriptor::TYPE_MAP;
    descriptor.num_partitions = partitions_.size();
    descriptor.writeToDirectory(directory);
  }
  for (size_t i = 0; i != partitions_.size(); i++) {
    const fs::path prefix = directory / getPartitionPrefix(i);
    partitions_[i].reset(new internal::Partition(prefix, partition_options));
  }
}
示例#3
0
std::vector<Stats> Map::stats(const fs::path& directory) {
  internal::DirectoryLock lock(directory.string());
  const auto descriptor = internal::Descriptor::readFromDirectory(directory);
  checkDescriptor(descriptor, directory);
  std::vector<Stats> stats;
  for (int i = 0; i < descriptor.num_partitions; i++) {
    const fs::path prefix = directory / getPartitionPrefix(i);
    stats.push_back(internal::Partition::stats(prefix));
  }
  return stats;
}
示例#4
0
// Required interface:
// void process(const boost::filesystem::path& partition_prefix,
//              const internal::Partition::Options& partition_options,
//              size_t partition_index, size_t num_partitions);
void forEachPartition(const boost::filesystem::path& directory,
                      Procedure process) {
  mt::DirectoryLockGuard lock(directory, getNameOfLockFile());
  const auto id = Map::Id::readFromDirectory(directory);
  Version::checkCompatibility(id.major_version, id.minor_version);

  internal::Partition::Options partition_options;
  partition_options.block_size = id.block_size;
  partition_options.readonly = true;

  for (size_t i = 0; i != id.num_partitions; ++i) {
    const auto partition_prefix = directory / getPartitionPrefix(i);
    process(partition_prefix, partition_options, i, id.num_partitions);
  }
}
示例#5
0
void Map::exportToBase64(const fs::path& directory, const fs::path& target,
                         const Options& options) {
  internal::DirectoryLock lock(directory.string());
  const auto descriptor = internal::Descriptor::readFromDirectory(directory);
  checkDescriptor(descriptor, directory);
  internal::TsvFileWriter writer(target);

  for (int i = 0; i < descriptor.num_partitions; i++) {
    const fs::path prefix = directory / getPartitionPrefix(i);
    if (options.verbose) {
      mt::log() << "Exporting partition " << (i + 1) << " of "
                << descriptor.num_partitions << std::endl;
    }
    if (options.compare) {
      Arena arena;
      std::vector<Slice> values;
      internal::Partition::forEachEntry(
          prefix, [&writer, &arena, &options, &values](const Slice& key,
                                                       Iterator* iter) {
            arena.deallocateAll();
            values.reserve(iter->available());
            values.clear();
            while (iter->hasNext()) {
              values.push_back(iter->next().makeCopy(&arena));
            }
            std::sort(values.begin(), values.end(), options.compare);
            auto range_iter = makeRangeIterator(values.begin(), values.end());
            writer.write(key, &range_iter);
          });
    } else {
      internal::Partition::forEachEntry(
          prefix, [&writer](const Slice& key, Iterator* iter) {
            writer.write(key, iter);
          });
    }
  }
}