[go: up one dir, main page]

File: vy_read_set.h

package info (click to toggle)
tarantool 2.6.0-1.4
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 85,412 kB
  • sloc: ansic: 513,775; cpp: 69,493; sh: 25,650; python: 19,190; perl: 14,973; makefile: 4,178; yacc: 1,329; sql: 1,074; pascal: 620; ruby: 190; awk: 18; lisp: 7
file content (223 lines) | stat: -rw-r--r-- 6,615 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#ifndef INCLUDES_TARANTOOL_BOX_VY_READ_SET_H
#define INCLUDES_TARANTOOL_BOX_VY_READ_SET_H
/*
 * Copyright 2010-2017, Tarantool AUTHORS, please see AUTHORS file.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * 1. Redistributions of source code must retain the above
 *    copyright notice, this list of conditions and the
 *    following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY AUTHORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#define RB_COMPACT 1
#include <small/rb.h>

#include "salad/stailq.h"
#include "trivia/util.h"
#include "vy_entry.h"

#if defined(__cplusplus)
extern "C" {
#endif /* defined(__cplusplus) */

struct vy_tx;
struct vy_lsm;

/**
 * A tuple interval read by a transaction.
 */
struct vy_read_interval {
	/** Transaction. */
	struct vy_tx *tx;
	/** LSM tree that the transaction read from. */
	struct vy_lsm *lsm;
	/** Left boundary of the interval. */
	struct vy_entry left;
	/** Right boundary of the interval. */
	struct vy_entry right;
	/** Set if the left boundary belongs to the interval. */
	bool left_belongs;
	/** Set if the right boundary belongs to the interval. */
	bool right_belongs;
	/**
	 * The interval with the max right boundary over
	 * all nodes in the subtree rooted at this node.
	 */
	const struct vy_read_interval *subtree_last;
	/** Link in vy_tx->read_set. */
	rb_node(struct vy_read_interval) in_tx;
	/** Link in vy_lsm->read_set. */
	rb_node(struct vy_read_interval) in_lsm;
	/**
	 * Auxiliary list node. Used by vy_tx_track() to
	 * link intervals to be merged.
	 */
	struct stailq_entry in_merge;
};

/**
 * Compare left boundaries of two intervals.
 *
 * Let 'A' and 'B' be the intervals of keys from the left boundary
 * of 'a' and 'b' to plus infinity, respectively. Assume that
 *
 * - a > b iff A is spanned by B
 * - a = b iff A equals B
 * - a < b iff A spans B
 */
int
vy_read_interval_cmpl(const struct vy_read_interval *a,
		      const struct vy_read_interval *b);

/**
 * Compare right boundaries of two intervals.
 *
 * Let 'A' and 'B' be the intervals of keys from minus infinity to
 * the right boundary of 'a' and 'b', respectively. Assume that
 *
 * - a > b iff A spans B
 * - a = b iff A equals B
 * - a < b iff A is spanned by B
 */
int
vy_read_interval_cmpr(const struct vy_read_interval *a,
		      const struct vy_read_interval *b);

/**
 * Return true if two intervals should be merged.
 * Interval 'l' must start before interval 'r'.
 * Note, if this function returns true, it does not
 * necessarily mean that the intervals intersect -
 * they might complement each other, e.g.
 *
 *   (10, 12] and (12, 20]
 */
bool
vy_read_interval_should_merge(const struct vy_read_interval *l,
			      const struct vy_read_interval *r);

/**
 * Tree that contains tuple intervals read by a transactions.
 * Linked by vy_read_interval->in_tx. Sorted by vy_lsm, then
 * by vy_read_interval->left. Intervals stored in this tree
 * must not intersect.
 */
typedef rb_tree(struct vy_read_interval) vy_tx_read_set_t;

static inline int
vy_tx_read_set_cmp(const struct vy_read_interval *a,
		   const struct vy_read_interval *b)
{
	assert(a->tx == b->tx);
	int rc = a->lsm < b->lsm ? -1 : a->lsm > b->lsm;
	if (rc == 0)
		rc = vy_read_interval_cmpl(a, b);
	return rc;
}

rb_gen(MAYBE_UNUSED static inline, vy_tx_read_set_, vy_tx_read_set_t,
       struct vy_read_interval, in_tx, vy_tx_read_set_cmp);

/**
 * Interval tree used for tracking reads done from an LSM tree by
 * all active transactions. Linked by vy_read_interval->in_lsm.
 * Sorted by vy_read_interval->left, then by vy_tx. Intervals that
 * belong to different transactions may intersect.
 */
typedef rb_tree(struct vy_read_interval) vy_lsm_read_set_t;

static inline int
vy_lsm_read_set_cmp(const struct vy_read_interval *a,
		    const struct vy_read_interval *b)
{
	assert(a->lsm == b->lsm);
	int rc = vy_read_interval_cmpl(a, b);
	if (rc == 0)
		rc = a->tx < b->tx ? -1 : a->tx > b->tx;
	return rc;
}

static inline void
vy_lsm_read_set_aug(struct vy_read_interval *node,
		    const struct vy_read_interval *left,
		    const struct vy_read_interval *right)
{
	node->subtree_last = node;
	if (left != NULL &&
	    vy_read_interval_cmpr(left->subtree_last, node->subtree_last) > 0)
		node->subtree_last = left->subtree_last;
	if (right != NULL &&
	    vy_read_interval_cmpr(right->subtree_last, node->subtree_last) > 0)
		node->subtree_last = right->subtree_last;
}

rb_gen_aug(MAYBE_UNUSED static inline, vy_lsm_read_set_, vy_lsm_read_set_t,
	   struct vy_read_interval, in_lsm, vy_lsm_read_set_cmp,
	   vy_lsm_read_set_aug);

/**
 * Iterator over transactions that conflict with a statement.
 */
struct vy_tx_conflict_iterator {
	/** The statement. */
	struct vy_entry key;
	/**
	 * Iterator over the interval tree checked
	 * for intersections with the statement.
	 */
	struct vy_lsm_read_set_walk tree_walk;
	/**
	 * Direction of tree traversal to be used on the
	 * next iteration.
	 */
	int tree_dir;
};

static inline void
vy_tx_conflict_iterator_init(struct vy_tx_conflict_iterator *it,
			     vy_lsm_read_set_t *read_set, struct vy_entry key)
{
	vy_lsm_read_set_walk_init(&it->tree_walk, read_set);
	it->tree_dir = 0;
	it->key = key;
}

/**
 * Return the next conflicting transaction or NULL.
 * Note, the same transaction may be returned more than once.
 */
struct vy_tx *
vy_tx_conflict_iterator_next(struct vy_tx_conflict_iterator *it);

#if defined(__cplusplus)
} /* extern "C" */
#endif /* defined(__cplusplus) */

#endif /* INCLUDES_TARANTOOL_BOX_VY_READ_SET_H */