<commit_before>// Copyright 2010-2015 RethinkDB, all rights reserved.
#include "rdb_protocol/store_metainfo.hpp"

#include "btree/reql_specific.hpp"
#include "containers/archive/buffer_stream.hpp"
#include "containers/archive/vector_stream.hpp"

store_metainfo_manager_t::store_metainfo_manager_t(real_superblock_t *superblock) {
    std::vector<std::pair<std::vector<char>, std::vector<char> > > kv_pairs;
    // TODO: this is inefficient, cut out the middleman (vector)
    get_superblock_metainfo(superblock, &kv_pairs);
    std::vector<region_t> regions;
    std::vector<binary_blob_t> values;
    for (auto &pair : kv_pairs) {
        region_t region;
        {
            buffer_read_stream_t key(pair.first.data(), pair.first.size());
            archive_result_t res = deserialize_for_metainfo(&key, &region);
            guarantee_deserialization(res, "region");
        }
        regions.push_back(region);
        values.push_back(binary_blob_t(pair.second.begin(), pair.second.end()));
    }
    cache = region_map_t<binary_blob_t>::from_unordered_fragments(
        std::move(regions), std::move(values));;
    rassert(cache.get_domain() == region_t::universe());
}

region_map_t<binary_blob_t> store_metainfo_manager_t::get(
        real_superblock_t *superblock,
        const region_t &region) {
    guarantee(superblock != nullptr);
    return cache.mask(region);
}

void store_metainfo_manager_t::visit(
        real_superblock_t *superblock,
        const region_t &region,
        const std::function<void(const region_t &, const binary_blob_t &)> &cb) {
    guarantee(superblock != nullptr);
    cache.visit(region, cb);
}

void store_metainfo_manager_t::update(
        real_superblock_t *superblock,
        const region_map_t<binary_blob_t> &new_values) {
    cache.update(new_values);

    std::vector<std::vector<char> > keys;
    std::vector<binary_blob_t> values;
    cache.visit(region_t::universe(),
        [&](const region_t &region, const binary_blob_t &value) {
            vector_stream_t key;
            write_message_t wm;
            serialize_for_metainfo(&wm, region);
            key.reserve(wm.size());
            DEBUG_VAR int res = send_write_message(&key, &wm);
            rassert(!res);

            keys.push_back(std::move(key.vector()));
            values.push_back(value);
        });

    set_superblock_metainfo(superblock, keys, values);
}
<commit_msg>Make store_metainfo_manager_t ensure that it holds the superblock lock before accessing its cache.<commit_after>// Copyright 2010-2015 RethinkDB, all rights reserved.
#include "rdb_protocol/store_metainfo.hpp"

#include "btree/reql_specific.hpp"
#include "containers/archive/buffer_stream.hpp"
#include "containers/archive/vector_stream.hpp"

store_metainfo_manager_t::store_metainfo_manager_t(real_superblock_t *superblock) {
    std::vector<std::pair<std::vector<char>, std::vector<char> > > kv_pairs;
    // TODO: this is inefficient, cut out the middleman (vector)
    get_superblock_metainfo(superblock, &kv_pairs);
    std::vector<region_t> regions;
    std::vector<binary_blob_t> values;
    for (auto &pair : kv_pairs) {
        region_t region;
        {
            buffer_read_stream_t key(pair.first.data(), pair.first.size());
            archive_result_t res = deserialize_for_metainfo(&key, &region);
            guarantee_deserialization(res, "region");
        }
        regions.push_back(region);
        values.push_back(binary_blob_t(pair.second.begin(), pair.second.end()));
    }
    cache = region_map_t<binary_blob_t>::from_unordered_fragments(
        std::move(regions), std::move(values));;
    rassert(cache.get_domain() == region_t::universe());
}

region_map_t<binary_blob_t> store_metainfo_manager_t::get(
        real_superblock_t *superblock,
        const region_t &region) {
    guarantee(superblock != nullptr);
    superblock->get()->read_acq_signal()->wait_lazily_unordered();
    return cache.mask(region);
}

void store_metainfo_manager_t::visit(
        real_superblock_t *superblock,
        const region_t &region,
        const std::function<void(const region_t &, const binary_blob_t &)> &cb) {
    guarantee(superblock != nullptr);
    superblock->get()->read_acq_signal()->wait_lazily_unordered();
    cache.visit(region, cb);
}

void store_metainfo_manager_t::update(
        real_superblock_t *superblock,
        const region_map_t<binary_blob_t> &new_values) {
    guarantee(superblock != nullptr);
    superblock->get()->write_acq_signal()->wait_lazily_unordered();

    cache.update(new_values);

    std::vector<std::vector<char> > keys;
    std::vector<binary_blob_t> values;
    cache.visit(region_t::universe(),
        [&](const region_t &region, const binary_blob_t &value) {
            vector_stream_t key;
            write_message_t wm;
            serialize_for_metainfo(&wm, region);
            key.reserve(wm.size());
            DEBUG_VAR int res = send_write_message(&key, &wm);
            rassert(!res);

            keys.push_back(std::move(key.vector()));
            values.push_back(value);
        });

    set_superblock_metainfo(superblock, keys, values);
}

{'fraction_non_alphanumeric': 0.12611737271667314, 'fraction_numerical': 0.003109211037699184, 'mean_word_length': 3.7481549815498156, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6325767', 'n_tokens_mistral': 1704, 'n_tokens_neox': 1689, 'n_words': 265}