<commit_before>#ifndef BUFFER_CACHE_ALT_ALT_HPP_
#define BUFFER_CACHE_ALT_ALT_HPP_

#include <vector>
#include <utility>

#include "buffer_cache/alt/page.hpp"
#include "buffer_cache/general_types.hpp"
#include "concurrency/auto_drainer.hpp"
#include "concurrency/semaphore.hpp"
#include "containers/two_level_array.hpp"
#include "repli_timestamp.hpp"
#include "utils.hpp"

class serializer_t;

namespace alt {

class alt_buf_lock_t;
class alt_cache_config_t;
class alt_cache_stats_t;
class alt_snapshot_node_t;

class alt_memory_tracker_t : public memory_tracker_t {
public:
    alt_memory_tracker_t();
    ~alt_memory_tracker_t();
    void inform_memory_change(uint64_t in_memory_size,
                              uint64_t memory_limit);
    void begin_txn_or_throttle(int64_t expected_change_count);
    void end_txn(int64_t saved_expected_change_count);
private:
    adjustable_semaphore_t semaphore_;
    DISABLE_COPYING(alt_memory_tracker_t);
};

class alt_cache_t : public home_thread_mixin_t {
public:
    explicit alt_cache_t(serializer_t *serializer,
                         const alt_cache_config_t &dynamic_config,
                         perfmon_collection_t *perfmon_collection);
    ~alt_cache_t();

    block_size_t max_block_size() const;
    // RSI: Remove this.
    block_size_t get_block_size() const { return max_block_size(); }

    // These todos come from the mirrored cache.  The real problem is that whole
    // cache account / priority thing is just one ghetto hack amidst a dozen other
    // throttling systems.  TODO: Come up with a consistent priority scheme,
    // i.e. define a "default" priority etc.  TODO: As soon as we can support it, we
    // might consider supporting a mem_cap paremeter.
    void create_cache_account(int priority, scoped_ptr_t<alt_cache_account_t> *out);

private:
    friend class alt_txn_t;  // for drainer_->lock()
    friend class alt_inner_txn_t;  // for &page_cache_
    friend class alt_buf_read_t;  // for &page_cache_
    friend class alt_buf_write_t;  // for &page_cache_

    friend class alt_buf_lock_t;  // for latest_snapshot_node and
                                  // push_latest_snapshot_node

    alt_snapshot_node_t *matching_snapshot_node_or_null(block_id_t block_id,
                                                        block_version_t block_version);
    void add_snapshot_node(block_id_t block_id, alt_snapshot_node_t *node);
    void remove_snapshot_node(block_id_t block_id, alt_snapshot_node_t *node);

    scoped_ptr_t<alt_cache_stats_t> stats_;

    // tracker_ is used for throttling (which can cause the alt_txn_t constructor to
    // block).  RSI: The throttling interface is bad (maybe) because it's worried
    // about transaction_t's passing one another(?) or maybe the callers are bad with
    // their use of chained mutexes.  Make sure that timestamps don't get mixed up in
    // their ordering, once they begin to play a role.
    alt_memory_tracker_t tracker_;
    page_cache_t page_cache_;

    two_level_nevershrink_array_t<intrusive_list_t<alt_snapshot_node_t> > snapshot_nodes_by_block_id_;

    scoped_ptr_t<auto_drainer_t> drainer_;

    DISABLE_COPYING(alt_cache_t);
};

class alt_inner_txn_t {
public:
    // This is public because scoped_ptr_t needs to call it.
    ~alt_inner_txn_t();

private:
    friend class alt_txn_t;
    alt_inner_txn_t(alt_cache_t *cache,
                    // Unused for read transactions, pass repli_timestamp_t::invalid.
                    repli_timestamp_t txn_recency,
                    alt_inner_txn_t *preceding_txn_or_null);

    alt_cache_t *cache() { return cache_; }

    page_txn_t *page_txn() { return &page_txn_; }

    alt_cache_t *cache_;
    page_txn_t page_txn_;

    DISABLE_COPYING(alt_inner_txn_t);
};

class alt_txn_t {
public:
    // Constructor for read-only transactions.
    // RSI: Generally speaking I don't think we use preceding_txn -- and should read
    // transactions use preceding_txn at all?
    explicit alt_txn_t(alt_cache_t *cache,
                       alt_read_access_t read_access,
                       alt_txn_t *preceding_txn = NULL);


    // RSI: Remove default parameter for expected_change_count.
    // RSI: Generally speaking I don't think we use preceding_txn and we should.
    alt_txn_t(alt_cache_t *cache,
              write_durability_t durability,
              repli_timestamp_t txn_timestamp,
              int64_t expected_change_count = 2,
              alt_txn_t *preceding_txn = NULL);

    ~alt_txn_t();

    alt_cache_t *cache() { return inner_->cache(); }
    page_txn_t *page_txn() { return inner_->page_txn(); }
    alt_access_t access() const { return access_; }

    void set_account(alt_cache_account_t *cache_account);

private:
    static void destroy_inner_txn(alt_inner_txn_t *inner,
                                  alt_cache_t *cache,
                                  int64_t saved_expected_change_count,
                                  auto_drainer_t::lock_t);

    const alt_access_t access_;

    // Only applicable if access_ == write.
    const write_durability_t durability_;
    const int64_t saved_expected_change_count_;  // RSI: A fugly relationship with
                                                 // the tracker.

    scoped_ptr_t<alt_inner_txn_t> inner_;
    DISABLE_COPYING(alt_txn_t);
};

// The intrusive list of alt_snapshot_node_t contains all the snapshot nodes for a
// given block id, in order by version.  (See
// alt_cache_t::snapshot_nodes_by_block_id_.)
class alt_snapshot_node_t : public intrusive_list_node_t<alt_snapshot_node_t> {
public:
    alt_snapshot_node_t(scoped_ptr_t<current_page_acq_t> &&acq);
    ~alt_snapshot_node_t();

private:
    // RSI: Should this really use friends?  Does this type need to be visible in the
    // header?
    friend class alt_buf_lock_t;
    friend class alt_cache_t;

    // This is never null (and is always a current_page_acq_t that has had
    // declare_snapshotted() called).
    scoped_ptr_t<current_page_acq_t> current_page_acq_;

    // RSP: std::map memory usage.
    // A NULL pointer associated with a block id indicates that the block is deleted.
    std::map<block_id_t, alt_snapshot_node_t *> children_;<commit_msg>Fixed some trivial style problems.<commit_after>#ifndef BUFFER_CACHE_ALT_ALT_HPP_
#define BUFFER_CACHE_ALT_ALT_HPP_

#include <map>
#include <vector>
#include <utility>

#include "buffer_cache/alt/page.hpp"
#include "buffer_cache/general_types.hpp"
#include "concurrency/auto_drainer.hpp"
#include "concurrency/semaphore.hpp"
#include "containers/two_level_array.hpp"
#include "repli_timestamp.hpp"
#include "utils.hpp"

class serializer_t;

namespace alt {

class alt_buf_lock_t;
class alt_cache_config_t;
class alt_cache_stats_t;
class alt_snapshot_node_t;

class alt_memory_tracker_t : public memory_tracker_t {
public:
    alt_memory_tracker_t();
    ~alt_memory_tracker_t();
    void inform_memory_change(uint64_t in_memory_size,
                              uint64_t memory_limit);
    void begin_txn_or_throttle(int64_t expected_change_count);
    void end_txn(int64_t saved_expected_change_count);
private:
    adjustable_semaphore_t semaphore_;
    DISABLE_COPYING(alt_memory_tracker_t);
};

class alt_cache_t : public home_thread_mixin_t {
public:
    explicit alt_cache_t(serializer_t *serializer,
                         const alt_cache_config_t &dynamic_config,
                         perfmon_collection_t *perfmon_collection);
    ~alt_cache_t();

    block_size_t max_block_size() const;
    // RSI: Remove this.
    block_size_t get_block_size() const { return max_block_size(); }

    // These todos come from the mirrored cache.  The real problem is that whole
    // cache account / priority thing is just one ghetto hack amidst a dozen other
    // throttling systems.  TODO: Come up with a consistent priority scheme,
    // i.e. define a "default" priority etc.  TODO: As soon as we can support it, we
    // might consider supporting a mem_cap paremeter.
    void create_cache_account(int priority, scoped_ptr_t<alt_cache_account_t> *out);

private:
    friend class alt_txn_t;  // for drainer_->lock()
    friend class alt_inner_txn_t;  // for &page_cache_
    friend class alt_buf_read_t;  // for &page_cache_
    friend class alt_buf_write_t;  // for &page_cache_

    friend class alt_buf_lock_t;  // for latest_snapshot_node and
                                  // push_latest_snapshot_node

    alt_snapshot_node_t *matching_snapshot_node_or_null(block_id_t block_id,
                                                        block_version_t block_version);
    void add_snapshot_node(block_id_t block_id, alt_snapshot_node_t *node);
    void remove_snapshot_node(block_id_t block_id, alt_snapshot_node_t *node);

    scoped_ptr_t<alt_cache_stats_t> stats_;

    // tracker_ is used for throttling (which can cause the alt_txn_t constructor to
    // block).  RSI: The throttling interface is bad (maybe) because it's worried
    // about transaction_t's passing one another(?) or maybe the callers are bad with
    // their use of chained mutexes.  Make sure that timestamps don't get mixed up in
    // their ordering, once they begin to play a role.
    alt_memory_tracker_t tracker_;
    page_cache_t page_cache_;

    two_level_nevershrink_array_t<intrusive_list_t<alt_snapshot_node_t> > snapshot_nodes_by_block_id_;

    scoped_ptr_t<auto_drainer_t> drainer_;

    DISABLE_COPYING(alt_cache_t);
};

class alt_inner_txn_t {
public:
    // This is public because scoped_ptr_t needs to call it.
    ~alt_inner_txn_t();

private:
    friend class alt_txn_t;
    alt_inner_txn_t(alt_cache_t *cache,
                    // Unused for read transactions, pass repli_timestamp_t::invalid.
                    repli_timestamp_t txn_recency,
                    alt_inner_txn_t *preceding_txn_or_null);

    alt_cache_t *cache() { return cache_; }

    page_txn_t *page_txn() { return &page_txn_; }

    alt_cache_t *cache_;
    page_txn_t page_txn_;

    DISABLE_COPYING(alt_inner_txn_t);
};

class alt_txn_t {
public:
    // Constructor for read-only transactions.
    // RSI: Generally speaking I don't think we use preceding_txn -- and should read
    // transactions use preceding_txn at all?
    explicit alt_txn_t(alt_cache_t *cache,
                       alt_read_access_t read_access,
                       alt_txn_t *preceding_txn = NULL);


    // RSI: Remove default parameter for expected_change_count.
    // RSI: Generally speaking I don't think we use preceding_txn and we should.
    alt_txn_t(alt_cache_t *cache,
              write_durability_t durability,
              repli_timestamp_t txn_timestamp,
              int64_t expected_change_count = 2,
              alt_txn_t *preceding_txn = NULL);

    ~alt_txn_t();

    alt_cache_t *cache() { return inner_->cache(); }
    page_txn_t *page_txn() { return inner_->page_txn(); }
    alt_access_t access() const { return access_; }

    void set_account(alt_cache_account_t *cache_account);

private:
    static void destroy_inner_txn(alt_inner_txn_t *inner,
                                  alt_cache_t *cache,
                                  int64_t saved_expected_change_count,
                                  auto_drainer_t::lock_t);

    const alt_access_t access_;

    // Only applicable if access_ == write.
    const write_durability_t durability_;
    const int64_t saved_expected_change_count_;  // RSI: A fugly relationship with
                                                 // the tracker.

    scoped_ptr_t<alt_inner_txn_t> inner_;
    DISABLE_COPYING(alt_txn_t);
};

// The intrusive list of alt_snapshot_node_t contains all the snapshot nodes for a
// given block id, in order by version.  (See
// alt_cache_t::snapshot_nodes_by_block_id_.)
class alt_snapshot_node_t : public intrusive_list_node_t<alt_snapshot_node_t> {
public:
    explicit alt_snapshot_node_t(scoped_ptr_t<current_page_acq_t> &&acq);
    ~alt_snapshot_node_t();

private:
    // RSI: Should this really use friends?  Does this type need to be visible in the
    // header?
    friend class alt_buf_lock_t;
    friend class alt_cache_t;

    // This is never null (and is always a current_page_acq_t that has had
    // declare_snapshotted() called).
    scoped_ptr_t<current_page_acq_t> current_page_acq_;

    // RSP: std::map memory usage.
    // A NULL pointer associated with a block id indicates that the block is deleted.
    std::map<block_id_t, alt_snapshot_node_t *> children_;
{'fraction_non_alphanumeric': 0.07080636138416048, 'fraction_numerical': 0.002397506593143131, 'mean_word_length': 3.098919095971176, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '215962', 'n_tokens_mistral': 4186, 'n_tokens_neox': 4082, 'n_words': 1004}