23 #include "mysqld_error.h"
31 "",
"",
":",
"-",
":",
",\n",
"",
38 "'",
"'",
":",
"-",
":",
"',\n'",
"''",
45 "# ",
"",
":",
"-",
":",
",\n# ",
"# [empty]",
51 : sid_lock(_sid_lock), sid_map(_sid_map)
59 : sid_lock(_sid_lock), sid_map(_sid_map)
61 DBUG_ASSERT(_sid_map != NULL);
69 DBUG_ENTER(
"Gtid_set::init");
70 cached_string_length= -1;
71 cached_string_format= NULL;
74 my_init_dynamic_array(&intervals,
sizeof(Interval *), 0, 8);
86 DBUG_ENTER(
"Gtid_set::~Gtid_set");
87 Interval_chunk *chunk= chunks;
90 Interval_chunk *next_chunk= chunk->next;
97 DBUG_ASSERT(n_chunks == 0);
98 delete_dynamic(&intervals);
107 DBUG_ENTER(
"Gtid_set::ensure_sidno");
108 if (sid_lock != NULL)
110 DBUG_PRINT(
"info", (
"sidno=%d get_max_sidno()=%d sid_map=%p "
111 "sid_map->get_max_sidno()=%d",
114 DBUG_ASSERT(sid_map == NULL || sidno <= sid_map->
get_max_sidno());
117 if (sidno > max_sidno)
125 bool is_wrlock=
false;
126 if (sid_lock != NULL)
135 if (sidno <= max_sidno)
143 if (allocate_dynamic(&intervals,
147 for (rpl_sidno
i= max_sidno;
i < sidno;
i++)
148 if (insert_dynamic(&intervals, &null_p))
150 if (sid_lock != NULL)
161 BINLOG_ERROR((
"Out of memory."), (ER_OUT_OF_RESOURCES, MYF(0)));
162 RETURN_REPORTED_ERROR;
166 void Gtid_set::add_interval_memory_lock_taken(
int n_ivs, Interval *ivs)
168 DBUG_ENTER(
"Gtid_set::add_interval_memory");
169 assert_free_intervals_locked();
171 for (
int i= 0;
i < n_ivs - 1;
i++)
172 ivs[
i].next= &(ivs[
i + 1]);
173 Interval_iterator ivit(
this);
174 ivs[n_ivs - 1].next= ivit.get();
181 enum_return_status Gtid_set::create_new_chunk(
int size)
183 DBUG_ENTER(
"Gtid_set::create_new_chunk");
186 assert_free_intervals_locked();
187 Interval_chunk *new_chunk=
188 (Interval_chunk *)my_malloc(
sizeof(Interval_chunk) +
189 sizeof(Interval) * (size - 1),
191 if (new_chunk == NULL)
192 RETURN_REPORTED_ERROR;
194 new_chunk->next= chunks;
200 add_interval_memory_lock_taken(size, new_chunk->intervals);
205 enum_return_status Gtid_set::get_free_interval(Interval **out)
207 DBUG_ENTER(
"Gtid_set::get_free_interval");
208 assert_free_intervals_locked();
209 Interval_iterator ivit(
this);
210 if (ivit.get() == NULL)
211 PROPAGATE_REPORTED_ERROR(create_new_chunk(CHUNK_GROW_SIZE));
213 ivit.set((*out)->next);
218 void Gtid_set::put_free_interval(Interval *iv)
220 DBUG_ENTER(
"Gtid_set::put_free_interval");
221 assert_free_intervals_locked();
222 Interval_iterator ivit(
this);
223 iv->next= ivit.get();
231 DBUG_ENTER(
"Gtid_set::clear");
236 for (rpl_sidno sidno= 1; sidno <= max_sidno; sidno++)
247 while (free_ivit.
get() != NULL)
260 Gtid_set::add_gno_interval(Interval_iterator *ivitp,
261 rpl_gno start, rpl_gno end,
262 Free_intervals_lock *lock)
264 DBUG_ENTER(
"Gtid_set::add_gno_interval(Interval_iterator*, rpl_gno, rpl_gno)");
265 DBUG_ASSERT(start > 0);
266 DBUG_ASSERT(start < end);
267 DBUG_PRINT(
"info", (
"start=%lld end=%lld", start, end));
269 Interval_iterator ivit= *ivitp;
270 cached_string_length= -1;
272 while ((iv= ivit.get()) != NULL)
274 if (iv->end >= start)
281 if (iv->start < start)
285 while (iv->next && end >= iv->next->start)
287 lock->lock_if_not_locked();
307 lock->lock_if_not_locked();
308 PROPAGATE_REPORTED_ERROR(get_free_interval(&new_iv));
309 new_iv->start= start;
317 enum_return_status Gtid_set::remove_gno_interval(Interval_iterator *ivitp,
318 rpl_gno start, rpl_gno end,
319 Free_intervals_lock *lock)
321 DBUG_ENTER(
"Gtid_set::remove_gno_interval(Interval_iterator *ivitp, rpl_gno start, rpl_gno end)");
322 DBUG_ASSERT(start < end);
323 Interval_iterator ivit= *ivitp;
325 cached_string_length= -1;
339 DBUG_ASSERT(iv != NULL && iv->end > start);
340 if (iv->start < start)
346 lock->lock_if_not_locked();
347 PROPAGATE_REPORTED_ERROR(get_free_interval(&new_iv));
349 new_iv->end= iv->end;
365 DBUG_ASSERT(iv != NULL && iv->start >= start);
366 while (iv->end <= end)
370 lock->lock_if_not_locked();
378 DBUG_ASSERT(iv != NULL && iv->end > end);
391 rpl_gno parse_gno(
const char **s)
394 rpl_gno
ret= strtoll(*s, &endp, 0);
395 if (ret < 0 || ret == LLONG_MAX)
402 int format_gno(
char *s, rpl_gno gno)
404 return (
int)(ll2str(gno, s, 10, 1) - s);
410 DBUG_ENTER(
"Gtid_set::add_gtid_text(const char *, bool *)");
411 DBUG_ASSERT(sid_map != NULL);
412 if (sid_lock != NULL)
416 DBUG_PRINT(
"info", (
"adding '%s'", text));
418 if (anonymous != NULL)
424 DBUG_PRINT(
"info", (
"'%s' is empty", text));
428 Free_intervals_lock lock(
this);
430 DBUG_PRINT(
"info", (
"'%s' not only whitespace", text));
442 lock.lock_if_not_locked();
443 create_new_chunk(n_intervals);
444 lock.unlock_if_locked();
460 DBUG_PRINT(
"info", (
"successfully parsed"));
465 if (anonymous != NULL && strncmp(s,
"ANONYMOUS", 9) == 0)
473 if (sid.
parse(s) != 0)
475 DBUG_PRINT(
"info", (
"expected UUID; found garbage '%.80s' at char %d in '%s'", s, (
int)(s - text), text));
479 rpl_sidno sidno= sid_map->
add_sid(sid);
482 RETURN_REPORTED_ERROR;
495 rpl_gno start= parse_gno(&s);
499 DBUG_PRINT(
"info", (
"expected positive NUMBER; found zero ('%.80s') at char %d in '%s'", s - 1, (
int)(s - text) - 1, text));
501 DBUG_PRINT(
"info", (
"expected positive NUMBER; found zero or garbage '%.80s' at char %d in '%s'", s, (
int)(s - text), text));
515 DBUG_PRINT(
"info", (
"expected NUMBER; found garbage '%.80s' at char %d in '%s'", s, (
int)(s - text), text));
530 if (current == NULL || start < current->start)
531 ivit.
init(
this, sidno);
532 if (add_gno_interval(&ivit, start, end, &lock) != RETURN_STATUS_OK)
534 RETURN_REPORTED_ERROR;
542 if (*s !=
',' && *s != 0)
544 DBUG_PRINT(
"info", (
"expected end of string, UUID, or :NUMBER; found garbage '%.80s' at char %d in '%s'", s, (
int)(s - text), text));
551 BINLOG_ERROR((
"Malformed Gtid_set specification '%.200s'.", text),
552 (ER_MALFORMED_GTID_SET_SPECIFICATION, MYF(0), text));
553 RETURN_REPORTED_ERROR;
558 DBUG_ENTER(
"Gtid_set::is_valid(const char*)");
587 if (parse_gno(&s) <= 0)
595 if (parse_gno(&s) < 0)
609 Gtid_set::add_gno_intervals(rpl_sidno sidno,
610 Const_interval_iterator other_ivit,
611 Free_intervals_lock *lock)
613 DBUG_ENTER(
"Gtid_set::add_gno_intervals(rpl_sidno, Const_interval_iterator, bool *)");
615 const Interval *other_iv;
616 Interval_iterator ivit(
this, sidno);
617 while ((other_iv= other_ivit.get()) != NULL)
619 PROPAGATE_REPORTED_ERROR(add_gno_interval(&ivit,
620 other_iv->start, other_iv->end,
629 Gtid_set::remove_gno_intervals(rpl_sidno sidno,
630 Const_interval_iterator other_ivit,
631 Free_intervals_lock *lock)
633 DBUG_ENTER(
"Gtid_set::remove_gno_intervals(rpl_sidno, Interval_iterator, bool *)");
635 const Interval *other_iv;
636 Interval_iterator ivit(
this, sidno);
637 while ((other_iv= other_ivit.get()) != NULL)
639 PROPAGATE_REPORTED_ERROR(remove_gno_interval(&ivit,
640 other_iv->start, other_iv->end,
650 DBUG_ENTER(
"Gtid_set::add_gtid_set(const Gtid_set *)");
651 if (sid_lock != NULL)
654 Free_intervals_lock lock(
this);
655 if (other->sid_map == sid_map || other->sid_map == NULL || sid_map == NULL)
657 PROPAGATE_REPORTED_ERROR(
ensure_sidno(max_other_sidno));
658 for (rpl_sidno sidno= 1; sidno <= max_other_sidno; sidno++)
659 PROPAGATE_REPORTED_ERROR(
671 Sid_map *other_sid_map= other->sid_map;
672 for (rpl_sidno other_sidno= 1; other_sidno <= max_other_sidno;
676 if (other_ivit.
get() != NULL)
679 rpl_sidno this_sidno= sid_map->
add_sid(sid);
681 RETURN_REPORTED_ERROR;
683 PROPAGATE_REPORTED_ERROR(add_gno_intervals(this_sidno, other_ivit,
694 DBUG_ENTER(
"Gtid_set::remove_gtid_set(Gtid_set *)");
695 if (sid_lock != NULL)
698 Free_intervals_lock lock(
this);
699 if (other->sid_map == sid_map || other->sid_map == NULL || sid_map == NULL)
702 for (rpl_sidno sidno= 1; sidno <= max_sidno; sidno++)
703 PROPAGATE_REPORTED_ERROR(
716 #ifdef NON_DISABLED_GTID
717 Sid_map *other_sid_map= other->sid_map;
718 for (rpl_sidno other_sidno= 1; other_sidno <= max_other_sidno;
722 if (other_ivit.
get() != NULL)
727 PROPAGATE_REPORTED_ERROR(
728 remove_gno_intervals(this_sidno, other_ivit, &lock));
739 DBUG_ENTER(
"Gtid_set::contains_gtid");
740 DBUG_ASSERT(sidno >= 1 && gno >= 1);
741 if (sid_lock != NULL)
747 while ((iv= ivit.
get()) != NULL)
751 else if (gno < iv->end)
760 DBUG_ENTER(
"Gtid_set::to_string");
762 *buf_arg= (
char *)my_malloc(len + 1, MYF(MY_WME));
763 if (*buf_arg == NULL)
771 DBUG_ENTER(
"Gtid_set::to_string");
772 DBUG_ASSERT(sid_map != NULL);
773 if (sid_lock != NULL)
780 buf[sf->empty_set_string_length]=
'\0';
781 DBUG_RETURN(sf->empty_set_string_length);
787 bool first_sidno=
true;
788 for (
int sid_i= 0; sid_i < map_max_sidno; sid_i++)
800 s+= sf->gno_sid_separator_length;
803 bool first_gno=
true;
809 s+= sf->sid_gno_separator_length;
814 s+= sf->gno_gno_separator_length;
816 s+= format_gno(s, iv->
start);
820 sf->gno_start_end_separator_length);
821 s+= sf->gno_start_end_separator_length;
822 s+= format_gno(s, iv->
end - 1);
826 }
while (iv != NULL);
829 memcpy(s, sf->
end, sf->end_length);
832 DBUG_PRINT(
"info", (
"ret='%s' strlen(s)=%lu s-buf=%lu get_string_length=%d", buf,
835 DBUG_RETURN((
int)(s - buf));
843 static int get_string_length(rpl_gno gno)
845 DBUG_ASSERT(gno >= 1 && gno < MAX_GNO);
848 if (gno >= 10000000000000000LL)
849 len+= 16, cmp= 10000000000000000LL;
852 if (gno >= 100000000LL)
853 len += 8, cmp = 100000000LL;
858 len += 4, cmp = cmp2;
862 len += 2, cmp = cmp2;
868 DBUG_ASSERT(snprintf(buf, 22,
"%lld", gno) == len);
876 DBUG_ASSERT(sid_map != NULL);
877 if (sid_lock != NULL)
881 if (cached_string_length == -1 || cached_string_format != sf)
883 int n_sids= 0, n_intervals= 0, n_long_intervals= 0;
884 int total_interval_length= 0;
886 for (rpl_sidno sidno= 1; sidno <= max_sidno; sidno++)
904 }
while (iv != NULL);
908 cached_string_length= sf->empty_set_string_length;
911 cached_string_length= sf->
begin_length + sf->end_length;
913 cached_string_length+=
914 total_interval_length +
916 (n_sids - 1) * sf->gno_sid_separator_length +
917 (n_intervals - n_sids) * sf->gno_gno_separator_length +
918 n_long_intervals * sf->gno_start_end_separator_length;
920 cached_string_format= sf;
922 return cached_string_length;
928 #ifdef NON_DISABLED_UNITTEST_GTID
929 bool Gtid_set::sidno_equals(rpl_sidno sidno,
const Gtid_set *other,
930 rpl_sidno other_sidno)
const
932 DBUG_ENTER(
"Gtid_set::sidno_equals");
933 Const_interval_iterator ivit(
this, sidno);
934 Const_interval_iterator other_ivit(other, other_sidno);
935 const Interval *iv= ivit.get();
936 const Interval *other_iv= other_ivit.get();
937 while (iv != NULL && other_iv != NULL)
939 if (!iv->equals(*other_iv))
944 other_iv= other_ivit.get();
946 if (iv != NULL || other_iv != NULL)
952 bool Gtid_set::equals(
const Gtid_set *other)
const
954 DBUG_ENTER(
"Gtid_set::equals");
956 if (sid_lock != NULL)
958 if (other->sid_lock != NULL)
960 if (sid_map == NULL || other->sid_map == NULL || sid_map == other->sid_map)
965 rpl_sidno common_max_sidno= min(max_sidno, other_max_sidno);
966 if (max_sidno > common_max_sidno)
968 for (rpl_sidno sidno= common_max_sidno + 1; sidno < max_sidno; sidno++)
972 else if (other_max_sidno > common_max_sidno)
974 for (rpl_sidno sidno= common_max_sidno + 1;
975 sidno < other_max_sidno; sidno++)
979 for (rpl_sidno sidno= 1; sidno <= common_max_sidno; sidno++)
980 if (!sidno_equals(sidno, other, sidno))
985 Sid_map *other_sid_map= other->sid_map;
987 rpl_sidno other_map_max_sidno= other_sid_map->
get_max_sidno();
989 int sid_i= 0, other_sid_i= 0;
992 rpl_sidno sidno= 0, other_sidno= 0;
994 while (sid_i < map_max_sidno &&
998 while (other_sid_i < other_map_max_sidno &&
1003 if (sid_i == map_max_sidno || other_sid_i == other_map_max_sidno)
1005 DBUG_RETURN(sid_i == map_max_sidno && other_sid_i == other_map_max_sidno);
1009 if (!sid.
equals(other_sid))
1012 if (!sidno_equals(sidno, other, other_sidno))
1023 bool Gtid_set::is_interval_subset(Const_interval_iterator *sub,
1024 Const_interval_iterator *super)
1026 DBUG_ENTER(
"is_interval_subset");
1029 const Interval *super_iv= super->get();
1030 const Interval *sub_iv= sub->get();
1040 if (super_iv == NULL)
1044 while (sub_iv->start > super_iv->end)
1047 super_iv= super->get();
1050 if (super_iv == NULL)
1056 if (sub_iv->start < super_iv->start || sub_iv->end > super_iv->end)
1063 }
while (sub_iv != NULL);
1072 DBUG_ENTER(
"Gtid_set::is_subset");
1073 if (sid_lock != NULL)
1075 if (super->sid_lock != NULL)
1078 Sid_map *super_sid_map= super->sid_map;
1088 for (
int sidno= 1; sidno <= max_sidno; sidno++)
1097 if (super_sid_map == sid_map || super_sid_map == NULL || sid_map == NULL)
1102 if (super_sidno == 0)
1105 if (super_sidno > super_max_sidno)
1111 if (!is_interval_subset(&ivit, &super_ivit))
1122 bool Gtid_set::is_interval_intersection_nonempty(Const_interval_iterator *ivit1,
1123 Const_interval_iterator *ivit2)
1125 DBUG_ENTER(
"is_interval_intersection_nonempty");
1126 const Interval *iv1= ivit1->get();
1127 const Interval *iv2= ivit2->get();
1128 DBUG_ASSERT(iv1 != NULL);
1142 while (iv2->end <= iv1->start)
1152 if (iv2->start < iv1->end)
1159 }
while (iv1 != NULL);
1169 DBUG_ENTER(
"Gtid_set::is_intersection_nonempty(Gtid_set *)");
1183 if (sid_lock != NULL)
1185 if (other->sid_lock != NULL)
1188 Sid_map *other_sid_map= other->sid_map;
1199 for (
int sidno= 1; sidno <= max_sidno; sidno++)
1208 if (other_sid_map == sid_map || other_sid_map == NULL || sid_map == NULL)
1213 if (other_sidno == 0)
1216 if (other_sidno > other_max_sidno)
1222 if (is_interval_intersection_nonempty(&ivit, &other_ivit))
1233 DBUG_ENTER(
"Gtid_set::intersection(Gtid_set *, Gtid_set *)");
1234 if (sid_lock != NULL)
1236 DBUG_ASSERT(result != NULL);
1237 DBUG_ASSERT(other != NULL);
1238 DBUG_ASSERT(result !=
this);
1239 DBUG_ASSERT(result != other);
1240 DBUG_ASSERT(other !=
this);
1247 Gtid_set this_minus_other(sid_map);
1250 PROPAGATE_REPORTED_ERROR(this_minus_other.
add_gtid_set(
this));
1252 PROPAGATE_REPORTED_ERROR(intersection.
add_gtid_set(
this));
1253 PROPAGATE_REPORTED_ERROR(intersection.
remove_gtid_set(&this_minus_other));
1254 PROPAGATE_REPORTED_ERROR(result->
add_gtid_set(&intersection));
1261 DBUG_ENTER(
"Gtid_set::encode(uchar *)");
1262 if (sid_lock != NULL)
1266 uchar *n_sids_p=
buf;
1271 for (rpl_sidno sid_i= 0; sid_i < sidmap_max_sidno; sid_i++)
1275 if (sidno > max_sidno)
1277 DBUG_PRINT(
"info", (
"sid_i=%d sidno=%d max_sidno=%d sid_map->max_sidno=%d",
1288 uint64 n_intervals= 0;
1289 uchar *n_intervals_p=
buf;
1296 int8store(buf, iv->
start);
1298 int8store(buf, iv->
end);
1303 }
while (iv != NULL);
1305 int8store(n_intervals_p, n_intervals);
1309 int8store(n_sids_p, n_sids);
1317 size_t *actual_length)
1319 DBUG_ENTER(
"Gtid_set::add_gtid_encoding(const uchar *, size_t)");
1320 if (sid_lock != NULL)
1324 Free_intervals_lock lock(
this);
1328 DBUG_PRINT(
"error", (
"(length=%lu) < 8", (ulong) length));
1331 n_sids= uint8korr(encoded);
1334 for (uint
i= 0;
i < n_sids;
i++)
1337 if (length - pos < 16 + 8)
1339 DBUG_PRINT(
"error", (
"(length=%lu) - (pos=%lu) < 16 + 8. "
1340 "[n_sids=%llu i=%u]",
1341 (ulong) length, (ulong) pos, n_sids,
i));
1347 uint64 n_intervals= uint8korr(encoded + pos);
1349 rpl_sidno sidno= sid_map->
add_sid(sid);
1352 DBUG_PRINT(
"error", (
"sidno=%d", sidno));
1353 RETURN_REPORTED_ERROR;
1357 if (length - pos < 2 * 8 * n_intervals)
1359 DBUG_PRINT(
"error", (
"(length=%lu) - (pos=%lu) < 2 * 8 * (n_intervals=%llu)",
1360 (ulong) length, (ulong) pos, n_intervals));
1365 for (uint
i= 0;
i < n_intervals;
i++)
1368 rpl_gno start= sint8korr(encoded + pos);
1370 rpl_gno end= sint8korr(encoded + pos);
1372 if (start <= last || end <= start)
1374 DBUG_PRINT(
"error", (
"last=%lld start=%lld end=%lld",
1383 if (current == NULL || start < current->start)
1384 ivit.
init(
this, sidno);
1385 DBUG_PRINT(
"info", (
"adding %d:%lld-%lld", sidno, start, end - 1));
1386 PROPAGATE_REPORTED_ERROR(add_gno_interval(&ivit, start, end, &lock));
1389 DBUG_ASSERT(pos <= length);
1390 if (actual_length == NULL)
1394 DBUG_PRINT(
"error", (
"(pos=%lu) != (length=%lu)", (ulong) pos,
1400 *actual_length= pos;
1405 BINLOG_ERROR((
"Malformed GTID_set encoding."),
1406 (ER_MALFORMED_GTID_SET_ENCODING, MYF(0)));
1407 RETURN_REPORTED_ERROR;
1413 if (sid_lock != NULL)
1417 for (rpl_sidno sidno= 1; sidno <= max_sidno; sidno++)
1419 ret+= 16 + 8 + 2 * 8 * get_n_intervals(sidno);