CUBRID Engine  latest
mvcc_active_tran.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 //
20 // MVCC active transactions map
21 //
22 
23 #include "mvcc_active_tran.hpp"
24 
25 #include "log_impl.h"
26 
27 #include <cstring>
28 
30  : m_bit_area (NULL)
31  , m_bit_area_start_mvccid (MVCCID_FIRST)
32  , m_bit_area_length (0)
33  , m_long_tran_mvccids (NULL)
34  , m_long_tran_mvccids_length (0)
35  , m_initialized (false)
36 {
37 }
38 
40 {
41  delete [] m_bit_area;
42  delete [] m_long_tran_mvccids;
43 }
44 
45 void
47 {
48  if (m_initialized)
49  {
50  return;
51  }
57  m_initialized = true;
58 }
59 
60 void
62 {
63  delete [] m_bit_area;
64  m_bit_area = NULL;
65 
66  delete [] m_long_tran_mvccids;
68 
69  m_initialized = false;
70 }
71 
72 void
74 {
75  if (!m_initialized)
76  {
77  return;
78  }
79  if (m_bit_area_length > 0)
80  {
81  // clear bits
82  std::memset (m_bit_area, 0, get_bit_area_memsize ());
83  }
87 
88  check_valid ();
89 }
90 
91 MVCCID
93 {
95 }
96 
97 size_t
99 {
101 }
102 
103 size_t
105 {
106  return (bit_count + UNIT_BIT_COUNT - 1) / UNIT_BIT_COUNT;
107 }
108 
109 size_t
111 {
112  return unit_count * UNIT_BIT_COUNT;
113 }
114 
115 size_t
117 {
118  return unit_count * UNIT_BYTE_COUNT;
119 }
120 
122 mvcc_active_tran::get_mask_of (size_t bit_offset)
123 {
124  return ((unit_type) 1) << (bit_offset & 0x3F);
125 }
126 
127 size_t
129 {
130  return static_cast<size_t> (mvccid - m_bit_area_start_mvccid);
131 }
132 
133 MVCCID
134 mvcc_active_tran::get_mvccid (size_t bit_offset) const
135 {
136  return m_bit_area_start_mvccid + bit_offset;
137 }
138 
140 mvcc_active_tran::get_unit_of (size_t bit_offset) const
141 {
142  return m_bit_area + (bit_offset / UNIT_BIT_COUNT);
143 }
144 
145 bool
146 mvcc_active_tran::is_set (size_t bit_offset) const
147 {
148  return ((*get_unit_of (bit_offset)) & get_mask_of (bit_offset)) != 0;
149 }
150 
151 size_t
153 {
155 }
156 
157 size_t
159 {
160  return units_to_bytes (get_area_size ());
161 }
162 
163 size_t
165 {
166  return m_long_tran_mvccids_length * sizeof (MVCCID);
167 }
168 
169 MVCCID
171 {
173 
174  if (m_bit_area_length == 0)
175  {
176  return m_bit_area_start_mvccid - 1;
177  }
178 
179  /* compute highest highest_bit_pos and highest_completed_bit_area */
180  size_t end_position = m_bit_area_length - 1;
181  unit_type *highest_completed_bit_area;
182  size_t highest_bit_position;
183  unit_type bits;
184  size_t bit_pos;
185  size_t count_bits;
186 
187  for (highest_completed_bit_area = get_unit_of (end_position); highest_completed_bit_area >= m_bit_area;
188  --highest_completed_bit_area)
189  {
190  bits = *highest_completed_bit_area;
191  if (bits == 0)
192  {
193  continue;
194  }
195  for (bit_pos = 0, count_bits = UNIT_BIT_COUNT / 2; count_bits > 0; count_bits /= 2)
196  {
197  if (bits >= (1ULL << count_bits))
198  {
199  bit_pos += count_bits;
200  bits >>= count_bits;
201  }
202  }
203  assert (bit_pos < UNIT_BIT_COUNT);
204  highest_bit_position = bit_pos;
205  break;
206  }
207  if (highest_completed_bit_area < m_bit_area)
208  {
209  // not found
210  return m_bit_area_start_mvccid - 1;
211  }
212  else
213  {
214  return get_mvccid (units_to_bits (highest_completed_bit_area - m_bit_area) + highest_bit_position);
215  }
216 }
217 
218 MVCCID
220 {
221  assert (m_bit_area != NULL);
222 
224  {
225  /* long time transactions are ordered */
226  return m_long_tran_mvccids[0];
227  }
228 
229  if (m_bit_area_length == 0)
230  {
232  }
233 
234  /* find the lowest bit 0 */
235  size_t end_position = m_bit_area_length - 1;
236  unit_type *end_bit_area = get_unit_of (end_position);
237  unit_type *lowest_active_bit_area;
238  size_t lowest_bit_pos = 0;
239  unit_type bits;
240  size_t bit_pos;
241  size_t count_bits;
242  unit_type mask;
243 
244  for (lowest_active_bit_area = m_bit_area; lowest_active_bit_area <= end_bit_area; ++lowest_active_bit_area)
245  {
246  bits = *lowest_active_bit_area;
247  if (bits == ALL_COMMITTED)
248  {
249  lowest_bit_pos += UNIT_BIT_COUNT;
250  continue;
251  }
252  /* find least significant bit 0 position */
253  for (bit_pos = 0, count_bits = UNIT_BIT_COUNT / 2; count_bits > 0; count_bits /= 2)
254  {
255  mask = (1ULL << count_bits) - 1;
256  if ((bits & mask) == mask)
257  {
258  bit_pos += count_bits;
259  bits >>= count_bits;
260  }
261  }
262  lowest_bit_pos += bit_pos;
263  break;
264  }
265  /* compute lowest_active_mvccid */
266  if (lowest_active_bit_area > end_bit_area)
267  {
268  /* didn't find 0 bit */
269  return get_mvccid (m_bit_area_length);
270  }
271  else
272  {
273  return get_mvccid (lowest_bit_pos);
274  }
275 }
276 
277 void
279 {
281 
282  if (safety == copy_safety::THREAD_SAFE)
283  {
284  check_valid ();
285  dest.check_valid ();
286  }
287 
288  size_t new_bit_area_memsize = get_bit_area_memsize ();
289  size_t old_bit_area_memsize = dest.get_bit_area_memsize ();
290  char *dest_bit_area = (char *) dest.m_bit_area;
291 
292  if (new_bit_area_memsize > 0)
293  {
294  std::memcpy (dest_bit_area, m_bit_area, new_bit_area_memsize);
295  }
296  if (old_bit_area_memsize > new_bit_area_memsize)
297  {
298  // clear
299  std::memset (dest_bit_area + new_bit_area_memsize, 0, old_bit_area_memsize - new_bit_area_memsize);
300  }
302  {
304  }
305 
309 
310  if (safety == copy_safety::THREAD_SAFE)
311  {
312  dest.check_valid ();
313  }
314 }
315 
316 bool
318 {
320  {
321  /* check long time transactions */
322  if (m_long_tran_mvccids != NULL)
323  {
324  for (size_t i = 0; i < m_long_tran_mvccids_length; i++)
325  {
326  if (mvccid == m_long_tran_mvccids[i])
327  {
328  return true;
329  }
330  }
331  }
332  // is committed
333  return false;
334  }
335  else if (m_bit_area_length == 0)
336  {
337  return true;
338  }
339  else
340  {
341  size_t position = get_bit_offset (mvccid);
342  if (position < m_bit_area_length)
343  {
344  return !is_set (position);
345  }
346  else
347  {
348  return true;
349  }
350  }
351 }
352 
353 void
355 {
356  /* Safe guard: */
358 
359  size_t i;
360  for (i = 0; i < m_long_tran_mvccids_length - 1; i++)
361  {
362  if (m_long_tran_mvccids[i] == mvccid)
363  {
364  size_t memsize = (m_long_tran_mvccids_length - i - 1) * sizeof (MVCCID);
365  std::memmove (&m_long_tran_mvccids[i], &m_long_tran_mvccids[i + 1], memsize);
366  break;
367  }
368  }
369  assert ((i < m_long_tran_mvccids_length - 1) || m_long_tran_mvccids[i] == mvccid);
371 
372  check_valid ();
373 }
374 
375 void
377 {
381 }
382 
383 void
385 {
386  if (trim_size == 0)
387  {
388  return;
389  }
390  size_t new_memsize = (get_area_size () - trim_size) * sizeof (unit_type);
391  if (new_memsize > 0)
392  {
393  std::memmove (m_bit_area, &m_bit_area[trim_size], new_memsize);
394  }
395  size_t trimmed_bits = units_to_bits (trim_size);
396  m_bit_area_length -= trimmed_bits;
397  m_bit_area_start_mvccid += trimmed_bits;
398  // clear moved units
399  std::memset (&m_bit_area[get_area_size ()], ALL_ACTIVE, trim_size * sizeof (unit_type));
400 #if !defined (NDEBUG)
401  // verify untouched units are also zero
402  for (size_t i = get_area_size () + trim_size; i < BITAREA_MAX_SIZE; i++)
403  {
405  }
406 #endif // DEBUG
407 
408  assert (new_memsize == get_bit_area_memsize ());
409 }
410 
411 void
413 {
414  const size_t CLEANUP_THRESHOLD = UNIT_BIT_COUNT;
415  const size_t LONG_TRAN_THRESHOLD = BITAREA_MAX_BITS - long_tran_max_size ();
416 
417  assert (mvccid >= m_bit_area_start_mvccid);
418  size_t position = get_bit_offset (mvccid);
419  if (position >= BITAREA_MAX_BITS)
420  {
421  // force cleanup_migrate_to_long_transations
423  position = get_bit_offset (mvccid);
424  }
425  assert (position < BITAREA_MAX_BITS); // is this a guaranteed?
426  if (position >= m_bit_area_length)
427  {
428  // extend area size; it is enough to update bit_area_length since all data is already zero
429  m_bit_area_length = position + 1;
430  }
431 
432  unit_type mask = get_mask_of (position);
433  unit_type *p_area = get_unit_of (position);
434  *p_area |= mask;
435 
436  check_valid ();
437 
438  if (m_bit_area_length > CLEANUP_THRESHOLD)
439  {
440  // trim all committed units from bit_area
441  size_t first_not_all_committed;
442  for (first_not_all_committed = 0; first_not_all_committed < get_area_size (); first_not_all_committed++)
443  {
444  if (m_bit_area[first_not_all_committed] != ALL_COMMITTED)
445  {
446  break;
447  }
448  }
449  ltrim_area (first_not_all_committed);
450  check_valid ();
451  }
452 
453  if (m_bit_area_length > LONG_TRAN_THRESHOLD)
454  {
456  }
457 }
458 
459 void
461 {
462  const size_t BITAREA_SIZE_AFTER_CLEANUP = 16;
463  size_t delete_count = get_area_size () - BITAREA_SIZE_AFTER_CLEANUP;
464  unit_type bits;
465  unit_type mask;
466  size_t bit_pos;
467  MVCCID long_tran_mvccid;
468 
469  for (size_t i = 0; i < delete_count; i++)
470  {
471  bits = m_bit_area[i];
472  // iterate on bits and find active MVCCID's
473  for (bit_pos = 0, mask = 1, long_tran_mvccid = get_mvccid (i * UNIT_BIT_COUNT);
474  bit_pos < UNIT_BIT_COUNT && bits != ALL_COMMITTED;
475  ++bit_pos, mask <<= 1, ++long_tran_mvccid)
476  {
477  if ((bits & mask) == 0)
478  {
479  add_long_transaction (long_tran_mvccid);
480  /* set the bit to in order to break faster */
481  bits |= mask;
482  }
483  }
484  }
485  ltrim_area (delete_count);
486 
487  check_valid ();
488 }
489 
490 void
492 {
493  /* check whether is long transaction */
495  {
496  remove_long_transaction (mvccid);
497  }
498  else
499  {
500  set_bitarea_mvccid (mvccid);
501  }
502 }
503 
504 void
506 {
507  m_bit_area_start_mvccid = mvccid;
508 
509  if (m_initialized)
510  {
511  check_valid ();
512  }
513 }
514 
515 void
517 {
518  std::memset (m_bit_area, 0, BITAREA_MAX_MEMSIZE);
519  m_bit_area_length = 0;
521 }
522 
523 void
525 {
526 #if !defined (NDEBUG)
527  // all bits after bit_area_length must be 0
528  if ((m_bit_area_length % UNIT_BIT_COUNT) != 0)
529  {
530  // we need to test bits after bit_area_length in same unit
531  size_t last_bit_pos = m_bit_area_length - 1;
532  unit_type last_unit = *get_unit_of (last_bit_pos);
533  for (size_t i = (last_bit_pos + 1) ; i < UNIT_BIT_COUNT; i++)
534  {
535  if ((get_mask_of (i) & last_unit) != 0)
536  {
537  assert (false);
538  }
539  }
540  }
541  for (unit_type *p_area = get_unit_of (m_bit_area_length) + 1; p_area < m_bit_area + BITAREA_MAX_SIZE; ++p_area)
542  {
543  if (*p_area != ALL_ACTIVE)
544  {
545  assert (false);
546  }
547  }
548 
549  // all long transaction should be ordered and smaller than bit_area_start_mvccid
550  for (size_t i = 0; i < m_long_tran_mvccids_length; i++)
551  {
554  }
555 #endif // debug
556 }
size_t get_area_size() const
static int count_bits(const unsigned char *mem, int nbits)
Definition: unittests_bit.c:31
#define MVCCID_FIRST
int logtb_get_number_of_total_tran_indices(void)
static const size_t UNIT_BIT_COUNT
std::uint64_t unit_type
MVCCID get_mvccid(size_t bit_offset) const
void reset_start_mvccid(MVCCID mvccid)
#define MVCCID_NULL
static const size_t BITAREA_MAX_BITS
static const unit_type ALL_ACTIVE
unit_type * m_bit_area
void cleanup_migrate_to_long_transations()
bool is_set(size_t bit_offset) const
MVCCID * m_long_tran_mvccids
static size_t long_tran_max_size()
#define assert(x)
unit_type * get_unit_of(size_t bit_offset) const
static const size_t UNIT_BYTE_COUNT
static const size_t BITAREA_MAX_SIZE
void set_inactive_mvccid(MVCCID mvccid)
volatile size_t m_long_tran_mvccids_length
MVCCID compute_highest_completed_mvccid() const
void remove_long_transaction(MVCCID mvccid)
static size_t bit_size_to_unit_size(size_t bit_count)
volatile MVCCID m_bit_area_start_mvccid
#define NULL
Definition: freelistheap.h:34
UINT64 MVCCID
void check_valid() const
if(extra_options)
Definition: dynamic_load.c:958
static const unit_type ALL_COMMITTED
#define MVCC_ID_PRECEDES(id1, id2)
Definition: mvcc.h:137
size_t get_bit_area_memsize() const
static size_t units_to_bytes(size_t unit_count)
void set_bitarea_mvccid(MVCCID mvccid)
size_t get_long_tran_memsize() const
static const size_t BITAREA_MAX_MEMSIZE
MVCCID get_bit_area_start_mvccid()
MVCCID compute_lowest_active_mvccid() const
int i
Definition: dynamic_load.c:954
bool is_active(MVCCID mvccid) const
void copy_to(mvcc_active_tran &dest, copy_safety safety) const
size_t get_bit_offset(MVCCID mvccid) const
static unit_type get_mask_of(size_t bit_offset)
static size_t units_to_bits(size_t unit_count)
void ltrim_area(size_t trim_size)
volatile size_t m_bit_area_length
void add_long_transaction(MVCCID mvccid)