1/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3/*======
4This file is part of PerconaFT.
5
6
7Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
8
9 PerconaFT is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License, version 2,
11 as published by the Free Software Foundation.
12
13 PerconaFT is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
20
21----------------------------------------
22
23 PerconaFT is free software: you can redistribute it and/or modify
24 it under the terms of the GNU Affero General Public License, version 3,
25 as published by the Free Software Foundation.
26
27 PerconaFT is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU Affero General Public License for more details.
31
32 You should have received a copy of the GNU Affero General Public License
33 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
34======= */
35
36#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
37
38#pragma once
39
40#include "ft/msg.h"
41#include "ft/txn/xids.h"
42#include "util/dbt.h"
43
44class message_buffer {
45public:
46 void create();
47
48 void clone(message_buffer *dst);
49
50 void destroy();
51
52 // effect: deserializes a message buffer from the given rbuf
53 // returns: *fresh_offsets (etc) malloc'd to be num_entries large and
54 // populated with *nfresh (etc) offsets in the message buffer
55 // requires: if fresh_offsets (etc) != nullptr, then nfresh != nullptr
56 void deserialize_from_rbuf(struct rbuf *rb,
57 int32_t **fresh_offsets, int32_t *nfresh,
58 int32_t **stale_offsets, int32_t *nstale,
59 int32_t **broadcast_offsets, int32_t *nbroadcast);
60
61 // effect: deserializes a message buffer whose messages are at version 13/14
62 // returns: similar to deserialize_from_rbuf(), excpet there are no stale messages
63 // and each message is assigned a sequential value from *highest_unused_msn_for_upgrade,
64 // which is modified as needed using toku_sync_fech_and_sub()
65 // returns: the highest MSN assigned to any message in this buffer
66 // requires: similar to deserialize_from_rbuf(), and highest_unused_msn_for_upgrade != nullptr
67 MSN deserialize_from_rbuf_v13(struct rbuf *rb,
68 MSN *highest_unused_msn_for_upgrade,
69 int32_t **fresh_offsets, int32_t *nfresh,
70 int32_t **broadcast_offsets, int32_t *nbroadcast);
71
72 void enqueue(const ft_msg &msg, bool is_fresh, int32_t *offset);
73
74 void set_freshness(int32_t offset, bool is_fresh);
75
76 bool get_freshness(int32_t offset) const;
77
78 ft_msg get_message(int32_t offset, DBT *keydbt, DBT *valdbt) const;
79
80 void get_message_key_msn(int32_t offset, DBT *key, MSN *msn) const;
81
82 int num_entries() const;
83
84 size_t buffer_size_in_use() const;
85
86 size_t memory_size_in_use() const;
87
88 size_t memory_footprint() const;
89
90 template <typename F>
91 int iterate(F &fn) const {
92 for (int32_t offset = 0; offset < _memory_used; ) {
93 DBT k, v;
94 const ft_msg msg = get_message(offset, &k, &v);
95 bool is_fresh = get_freshness(offset);
96 int r = fn(msg, is_fresh);
97 if (r != 0) {
98 return r;
99 }
100 offset += msg_memsize_in_buffer(msg);
101 }
102 return 0;
103 }
104
105 bool equals(message_buffer *other) const;
106
107 void serialize_to_wbuf(struct wbuf *wb) const;
108
109 static size_t msg_memsize_in_buffer(const ft_msg &msg);
110
111private:
112 void _resize(size_t new_size);
113
114 // If this isn't packged, the compiler aligns the xids array and we waste a lot of space
115 struct __attribute__((__packed__)) buffer_entry {
116 unsigned int keylen;
117 unsigned int vallen;
118 unsigned char type;
119 bool is_fresh;
120 MSN msn;
121 XIDS_S xids_s;
122 };
123
124 struct buffer_entry *get_buffer_entry(int32_t offset) const;
125
126 int _num_entries;
127 char *_memory; // An array of bytes into which buffer entries are embedded.
128 int _memory_size; // How big is _memory
129 int _memory_used; // How many bytes are in use?
130 size_t _memory_usable; // a cached result of toku_malloc_usable_size(_memory).
131};
132