1 /*****************************************************************************
2 
3 Copyright (c) 2007, 2012, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file trx/trx0i_s.cc
29 INFORMATION SCHEMA innodb_trx, innodb_locks and
30 innodb_lock_waits tables fetch code.
31 
32 The code below fetches information needed to fill those
33 3 dynamic tables and uploads it into a "transactions
34 table cache" for later retrieval.
35 
36 Created July 17, 2007 Vasil Dimov
37 *******************************************************/
38 
39 /* Found during the build of 5.5.3 on Linux 2.4 and early 2.6 kernels:
40    The includes "univ.i" -> "my_global.h" cause a different path
41    to be taken further down with pthread functions and types,
42    so they must come first.
43    From the symptoms, this is related to bug#46587 in the MySQL bug DB.
44 */
45 #include "univ.i"
46 
47 #include <mysql/plugin.h>
48 
49 #include "buf0buf.h"
50 #include "dict0dict.h"
51 #include "ha0storage.h"
52 #include "ha_prototypes.h"
53 #include "hash0hash.h"
54 #include "lock0iter.h"
55 #include "lock0lock.h"
56 #include "mem0mem.h"
57 #include "page0page.h"
58 #include "rem0rec.h"
59 #include "row0row.h"
60 #include "srv0srv.h"
61 #include "sync0rw.h"
62 #include "sync0sync.h"
63 #include "sync0types.h"
64 #include "trx0i_s.h"
65 #include "trx0sys.h"
66 #include "trx0trx.h"
67 #include "ut0mem.h"
68 #include "ut0ut.h"
69 
70 /** Initial number of rows in the table cache */
71 #define TABLE_CACHE_INITIAL_ROWSNUM	1024
72 
73 /** @brief The maximum number of chunks to allocate for a table cache.
74 
75 The rows of a table cache are stored in a set of chunks. When a new
76 row is added a new chunk is allocated if necessary. Assuming that the
77 first one is 1024 rows (TABLE_CACHE_INITIAL_ROWSNUM) and each
78 subsequent is N/2 where N is the number of rows we have allocated till
79 now, then 39th chunk would accommodate 1677416425 rows and all chunks
80 would accommodate 3354832851 rows. */
81 #define MEM_CHUNKS_IN_TABLE_CACHE	39
82 
83 /** The following are some testing auxiliary macros. Do not enable them
84 in a production environment. */
85 /* @{ */
86 
87 #if 0
88 /** If this is enabled then lock folds will always be different
89 resulting in equal rows being put in a different cells of the hash
90 table. Checking for duplicates will be flawed because different
91 fold will be calculated when a row is searched in the hash table. */
92 #define TEST_LOCK_FOLD_ALWAYS_DIFFERENT
93 #endif
94 
95 #if 0
96 /** This effectively kills the search-for-duplicate-before-adding-a-row
97 function, but searching in the hash is still performed. It will always
98 be assumed that lock is not present and insertion will be performed in
99 the hash table. */
100 #define TEST_NO_LOCKS_ROW_IS_EVER_EQUAL_TO_LOCK_T
101 #endif
102 
103 #if 0
104 /** This aggressively repeats adding each row many times. Depending on
105 the above settings this may be noop or may result in lots of rows being
106 added. */
107 #define TEST_ADD_EACH_LOCKS_ROW_MANY_TIMES
108 #endif
109 
110 #if 0
111 /** Very similar to TEST_NO_LOCKS_ROW_IS_EVER_EQUAL_TO_LOCK_T but hash
112 table search is not performed at all. */
113 #define TEST_DO_NOT_CHECK_FOR_DUPLICATE_ROWS
114 #endif
115 
116 #if 0
117 /** Do not insert each row into the hash table, duplicates may appear
118 if this is enabled, also if this is enabled searching into the hash is
119 noop because it will be empty. */
120 #define TEST_DO_NOT_INSERT_INTO_THE_HASH_TABLE
121 #endif
122 /* @} */
123 
124 /** Memory limit passed to ha_storage_put_memlim().
125 @param cache	hash storage
126 @return		maximum allowed allocation size */
127 #define MAX_ALLOWED_FOR_STORAGE(cache)		\
128 	(TRX_I_S_MEM_LIMIT			\
129 	 - (cache)->mem_allocd)
130 
131 /** Memory limit in table_cache_create_empty_row().
132 @param cache	hash storage
133 @return		maximum allowed allocation size */
134 #define MAX_ALLOWED_FOR_ALLOC(cache)		\
135 	(TRX_I_S_MEM_LIMIT			\
136 	 - (cache)->mem_allocd			\
137 	 - ha_storage_get_size((cache)->storage))
138 
139 /** Memory for each table in the intermediate buffer is allocated in
140 separate chunks. These chunks are considered to be concatenated to
141 represent one flat array of rows. */
142 struct i_s_mem_chunk_t {
143 	ulint	offset;		/*!< offset, in number of rows */
144 	ulint	rows_allocd;	/*!< the size of this chunk, in number
145 				of rows */
146 	void*	base;		/*!< start of the chunk */
147 };
148 
149 /** This represents one table's cache. */
150 struct i_s_table_cache_t {
151 	ulint		rows_used;	/*!< number of used rows */
152 	ulint		rows_allocd;	/*!< number of allocated rows */
153 	ulint		row_size;	/*!< size of a single row */
154 	i_s_mem_chunk_t	chunks[MEM_CHUNKS_IN_TABLE_CACHE]; /*!< array of
155 					memory chunks that stores the
156 					rows */
157 };
158 
159 /** This structure describes the intermediate buffer */
160 struct trx_i_s_cache_t {
161 	rw_lock_t	rw_lock;	/*!< read-write lock protecting
162 					the rest of this structure */
163 	ullint		last_read;	/*!< last time the cache was read;
164 					measured in microseconds since
165 					epoch */
166 	ib_mutex_t		last_read_mutex;/*!< mutex protecting the
167 					last_read member - it is updated
168 					inside a shared lock of the
169 					rw_lock member */
170 	i_s_table_cache_t innodb_trx;	/*!< innodb_trx table */
171 	i_s_table_cache_t innodb_locks;	/*!< innodb_locks table */
172 	i_s_table_cache_t innodb_lock_waits;/*!< innodb_lock_waits table */
173 /** the hash table size is LOCKS_HASH_CELLS_NUM * sizeof(void*) bytes */
174 #define LOCKS_HASH_CELLS_NUM		10000
175 	hash_table_t*	locks_hash;	/*!< hash table used to eliminate
176 					duplicate entries in the
177 					innodb_locks table */
178 /** Initial size of the cache storage */
179 #define CACHE_STORAGE_INITIAL_SIZE	1024
180 /** Number of hash cells in the cache storage */
181 #define CACHE_STORAGE_HASH_CELLS	2048
182 	ha_storage_t*	storage;	/*!< storage for external volatile
183 					data that may become unavailable
184 					when we release
185 					lock_sys->mutex or trx_sys->mutex */
186 	ulint		mem_allocd;	/*!< the amount of memory
187 					allocated with mem_alloc*() */
188 	ibool		is_truncated;	/*!< this is TRUE if the memory
189 					limit was hit and thus the data
190 					in the cache is truncated */
191 };
192 
193 /** This is the intermediate buffer where data needed to fill the
194 INFORMATION SCHEMA tables is fetched and later retrieved by the C++
195 code in handler/i_s.cc. */
196 static trx_i_s_cache_t	trx_i_s_cache_static;
197 /** This is the intermediate buffer where data needed to fill the
198 INFORMATION SCHEMA tables is fetched and later retrieved by the C++
199 code in handler/i_s.cc. */
200 UNIV_INTERN trx_i_s_cache_t*	trx_i_s_cache = &trx_i_s_cache_static;
201 
202 /* Key to register the lock/mutex with performance schema */
203 #ifdef UNIV_PFS_RWLOCK
204 UNIV_INTERN mysql_pfs_key_t	trx_i_s_cache_lock_key;
205 #endif /* UNIV_PFS_RWLOCK */
206 
207 #ifdef UNIV_PFS_MUTEX
208 UNIV_INTERN mysql_pfs_key_t	cache_last_read_mutex_key;
209 #endif /* UNIV_PFS_MUTEX */
210 
211 /*******************************************************************//**
212 For a record lock that is in waiting state retrieves the only bit that
213 is set, for a table lock returns ULINT_UNDEFINED.
214 @return	record number within the heap */
215 static
216 ulint
wait_lock_get_heap_no(const lock_t * lock)217 wait_lock_get_heap_no(
218 /*==================*/
219 	const lock_t*	lock)	/*!< in: lock */
220 {
221 	ulint	ret;
222 
223 	switch (lock_get_type(lock)) {
224 	case LOCK_REC:
225 		ret = lock_rec_find_set_bit(lock);
226 		ut_a(ret != ULINT_UNDEFINED);
227 		break;
228 	case LOCK_TABLE:
229 		ret = ULINT_UNDEFINED;
230 		break;
231 	default:
232 		ut_error;
233 	}
234 
235 	return(ret);
236 }
237 
238 /*******************************************************************//**
239 Initializes the members of a table cache. */
240 static
241 void
table_cache_init(i_s_table_cache_t * table_cache,size_t row_size)242 table_cache_init(
243 /*=============*/
244 	i_s_table_cache_t*	table_cache,	/*!< out: table cache */
245 	size_t			row_size)	/*!< in: the size of a
246 						row */
247 {
248 	ulint	i;
249 
250 	table_cache->rows_used = 0;
251 	table_cache->rows_allocd = 0;
252 	table_cache->row_size = row_size;
253 
254 	for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
255 
256 		/* the memory is actually allocated in
257 		table_cache_create_empty_row() */
258 		table_cache->chunks[i].base = NULL;
259 	}
260 }
261 
262 /*******************************************************************//**
263 Frees a table cache. */
264 static
265 void
table_cache_free(i_s_table_cache_t * table_cache)266 table_cache_free(
267 /*=============*/
268 	i_s_table_cache_t*	table_cache)	/*!< in/out: table cache */
269 {
270 	ulint	i;
271 
272 	for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
273 
274 		/* the memory is actually allocated in
275 		table_cache_create_empty_row() */
276 		if (table_cache->chunks[i].base) {
277 			mem_free(table_cache->chunks[i].base);
278 			table_cache->chunks[i].base = NULL;
279 		}
280 	}
281 }
282 
283 /*******************************************************************//**
284 Returns an empty row from a table cache. The row is allocated if no more
285 empty rows are available. The number of used rows is incremented.
286 If the memory limit is hit then NULL is returned and nothing is
287 allocated.
288 @return	empty row, or NULL if out of memory */
289 static
290 void*
table_cache_create_empty_row(i_s_table_cache_t * table_cache,trx_i_s_cache_t * cache)291 table_cache_create_empty_row(
292 /*=========================*/
293 	i_s_table_cache_t*	table_cache,	/*!< in/out: table cache */
294 	trx_i_s_cache_t*	cache)		/*!< in/out: cache to record
295 						how many bytes are
296 						allocated */
297 {
298 	ulint	i;
299 	void*	row;
300 
301 	ut_a(table_cache->rows_used <= table_cache->rows_allocd);
302 
303 	if (table_cache->rows_used == table_cache->rows_allocd) {
304 
305 		/* rows_used == rows_allocd means that new chunk needs
306 		to be allocated: either no more empty rows in the
307 		last allocated chunk or nothing has been allocated yet
308 		(rows_num == rows_allocd == 0); */
309 
310 		i_s_mem_chunk_t*	chunk;
311 		ulint			req_bytes;
312 		ulint			got_bytes;
313 		ulint			req_rows;
314 		ulint			got_rows;
315 
316 		/* find the first not allocated chunk */
317 		for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
318 
319 			if (table_cache->chunks[i].base == NULL) {
320 
321 				break;
322 			}
323 		}
324 
325 		/* i == MEM_CHUNKS_IN_TABLE_CACHE means that all chunks
326 		have been allocated :-X */
327 		ut_a(i < MEM_CHUNKS_IN_TABLE_CACHE);
328 
329 		/* allocate the chunk we just found */
330 
331 		if (i == 0) {
332 
333 			/* first chunk, nothing is allocated yet */
334 			req_rows = TABLE_CACHE_INITIAL_ROWSNUM;
335 		} else {
336 
337 			/* Memory is increased by the formula
338 			new = old + old / 2; We are trying not to be
339 			aggressive here (= using the common new = old * 2)
340 			because the allocated memory will not be freed
341 			until InnoDB exit (it is reused). So it is better
342 			to once allocate the memory in more steps, but
343 			have less unused/wasted memory than to use less
344 			steps in allocation (which is done once in a
345 			lifetime) but end up with lots of unused/wasted
346 			memory. */
347 			req_rows = table_cache->rows_allocd / 2;
348 		}
349 		req_bytes = req_rows * table_cache->row_size;
350 
351 		if (req_bytes > MAX_ALLOWED_FOR_ALLOC(cache)) {
352 
353 			return(NULL);
354 		}
355 
356 		chunk = &table_cache->chunks[i];
357 
358 		chunk->base = mem_alloc2(req_bytes, &got_bytes);
359 
360 		got_rows = got_bytes / table_cache->row_size;
361 
362 		cache->mem_allocd += got_bytes;
363 
364 #if 0
365 		printf("allocating chunk %d req bytes=%lu, got bytes=%lu, "
366 		       "row size=%lu, "
367 		       "req rows=%lu, got rows=%lu\n",
368 		       i, req_bytes, got_bytes,
369 		       table_cache->row_size,
370 		       req_rows, got_rows);
371 #endif
372 
373 		chunk->rows_allocd = got_rows;
374 
375 		table_cache->rows_allocd += got_rows;
376 
377 		/* adjust the offset of the next chunk */
378 		if (i < MEM_CHUNKS_IN_TABLE_CACHE - 1) {
379 
380 			table_cache->chunks[i + 1].offset
381 				= chunk->offset + chunk->rows_allocd;
382 		}
383 
384 		/* return the first empty row in the newly allocated
385 		chunk */
386 		row = chunk->base;
387 	} else {
388 
389 		char*	chunk_start;
390 		ulint	offset;
391 
392 		/* there is an empty row, no need to allocate new
393 		chunks */
394 
395 		/* find the first chunk that contains allocated but
396 		empty/unused rows */
397 		for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
398 
399 			if (table_cache->chunks[i].offset
400 			    + table_cache->chunks[i].rows_allocd
401 			    > table_cache->rows_used) {
402 
403 				break;
404 			}
405 		}
406 
407 		/* i == MEM_CHUNKS_IN_TABLE_CACHE means that all chunks
408 		are full, but
409 		table_cache->rows_used != table_cache->rows_allocd means
410 		exactly the opposite - there are allocated but
411 		empty/unused rows :-X */
412 		ut_a(i < MEM_CHUNKS_IN_TABLE_CACHE);
413 
414 		chunk_start = (char*) table_cache->chunks[i].base;
415 		offset = table_cache->rows_used
416 			- table_cache->chunks[i].offset;
417 
418 		row = chunk_start + offset * table_cache->row_size;
419 	}
420 
421 	table_cache->rows_used++;
422 
423 	return(row);
424 }
425 
426 #ifdef UNIV_DEBUG
427 /*******************************************************************//**
428 Validates a row in the locks cache.
429 @return	TRUE if valid */
430 static
431 ibool
i_s_locks_row_validate(const i_s_locks_row_t * row)432 i_s_locks_row_validate(
433 /*===================*/
434 	const i_s_locks_row_t*	row)	/*!< in: row to validate */
435 {
436 	ut_ad(row->lock_trx_id != 0);
437 	ut_ad(row->lock_mode != NULL);
438 	ut_ad(row->lock_type != NULL);
439 	ut_ad(row->lock_table != NULL);
440 	ut_ad(row->lock_table_id != 0);
441 
442 	if (row->lock_space == ULINT_UNDEFINED) {
443 		/* table lock */
444 		ut_ad(!strcmp("TABLE", row->lock_type));
445 		ut_ad(row->lock_index == NULL);
446 		ut_ad(row->lock_data == NULL);
447 		ut_ad(row->lock_page == ULINT_UNDEFINED);
448 		ut_ad(row->lock_rec == ULINT_UNDEFINED);
449 	} else {
450 		/* record lock */
451 		ut_ad(!strcmp("RECORD", row->lock_type));
452 		ut_ad(row->lock_index != NULL);
453 		/* row->lock_data == NULL if buf_page_try_get() == NULL */
454 		ut_ad(row->lock_page != ULINT_UNDEFINED);
455 		ut_ad(row->lock_rec != ULINT_UNDEFINED);
456 	}
457 
458 	return(TRUE);
459 }
460 #endif /* UNIV_DEBUG */
461 
462 /*******************************************************************//**
463 Fills i_s_trx_row_t object.
464 If memory can not be allocated then FALSE is returned.
465 @return	FALSE if allocation fails */
466 static
467 ibool
fill_trx_row(i_s_trx_row_t * row,const trx_t * trx,const i_s_locks_row_t * requested_lock_row,trx_i_s_cache_t * cache)468 fill_trx_row(
469 /*=========*/
470 	i_s_trx_row_t*		row,		/*!< out: result object
471 						that's filled */
472 	const trx_t*		trx,		/*!< in: transaction to
473 						get data from */
474 	const i_s_locks_row_t*	requested_lock_row,/*!< in: pointer to the
475 						corresponding row in
476 						innodb_locks if trx is
477 						waiting or NULL if trx
478 						is not waiting */
479 	trx_i_s_cache_t*	cache)		/*!< in/out: cache into
480 						which to copy volatile
481 						strings */
482 {
483 	const char*	stmt;
484 	size_t		stmt_len;
485 	const char*	s;
486 
487 	ut_ad(lock_mutex_own());
488 
489 	row->trx_id = trx->id;
490 	row->trx_started = (ib_time_t) trx->start_time;
491 	row->trx_state = trx_get_que_state_str(trx);
492 	row->requested_lock_row = requested_lock_row;
493 	ut_ad(requested_lock_row == NULL
494 	      || i_s_locks_row_validate(requested_lock_row));
495 
496 	if (trx->lock.wait_lock != NULL) {
497 
498 		ut_a(requested_lock_row != NULL);
499 		row->trx_wait_started = (ib_time_t) trx->lock.wait_started;
500 	} else {
501 		ut_a(requested_lock_row == NULL);
502 		row->trx_wait_started = 0;
503 	}
504 
505 	row->trx_weight = (ullint) TRX_WEIGHT(trx);
506 
507 	if (trx->mysql_thd == NULL) {
508 		/* For internal transactions e.g., purge and transactions
509 		being recovered at startup there is no associated MySQL
510 		thread data structure. */
511 		row->trx_mysql_thread_id = 0;
512 		row->trx_query = NULL;
513 		goto thd_done;
514 	}
515 
516 	row->trx_mysql_thread_id = thd_get_thread_id(trx->mysql_thd);
517 
518 	stmt = innobase_get_stmt(trx->mysql_thd, &stmt_len);
519 
520 	if (stmt != NULL) {
521 		char	query[TRX_I_S_TRX_QUERY_MAX_LEN + 1];
522 
523 		if (stmt_len > TRX_I_S_TRX_QUERY_MAX_LEN) {
524 			stmt_len = TRX_I_S_TRX_QUERY_MAX_LEN;
525 		}
526 
527 		memcpy(query, stmt, stmt_len);
528 		query[stmt_len] = '\0';
529 
530 		row->trx_query = static_cast<const char*>(
531 			ha_storage_put_memlim(
532 				cache->storage, query, stmt_len + 1,
533 				MAX_ALLOWED_FOR_STORAGE(cache)));
534 
535 		row->trx_query_cs = innobase_get_charset(trx->mysql_thd);
536 
537 		if (row->trx_query == NULL) {
538 
539 			return(FALSE);
540 		}
541 	} else {
542 
543 		row->trx_query = NULL;
544 	}
545 
546 thd_done:
547 	s = trx->op_info;
548 
549 	if (s != NULL && s[0] != '\0') {
550 
551 		TRX_I_S_STRING_COPY(s, row->trx_operation_state,
552 				    TRX_I_S_TRX_OP_STATE_MAX_LEN, cache);
553 
554 		if (row->trx_operation_state == NULL) {
555 
556 			return(FALSE);
557 		}
558 	} else {
559 
560 		row->trx_operation_state = NULL;
561 	}
562 
563 	row->trx_tables_in_use = trx->n_mysql_tables_in_use;
564 
565 	row->trx_tables_locked = trx->mysql_n_tables_locked;
566 
567 	/* These are protected by both trx->mutex or lock_sys->mutex,
568 	or just lock_sys->mutex. For reading, it suffices to hold
569 	lock_sys->mutex. */
570 
571 	row->trx_lock_structs = UT_LIST_GET_LEN(trx->lock.trx_locks);
572 
573 	row->trx_lock_memory_bytes = mem_heap_get_size(trx->lock.lock_heap);
574 
575 	row->trx_rows_locked = lock_number_of_rows_locked(&trx->lock);
576 
577 	row->trx_rows_modified = trx->undo_no;
578 
579 	row->trx_concurrency_tickets = trx->n_tickets_to_enter_innodb;
580 
581 	switch (trx->isolation_level) {
582 	case TRX_ISO_READ_UNCOMMITTED:
583 		row->trx_isolation_level = "READ UNCOMMITTED";
584 		break;
585 	case TRX_ISO_READ_COMMITTED:
586 		row->trx_isolation_level = "READ COMMITTED";
587 		break;
588 	case TRX_ISO_REPEATABLE_READ:
589 		row->trx_isolation_level = "REPEATABLE READ";
590 		break;
591 	case TRX_ISO_SERIALIZABLE:
592 		row->trx_isolation_level = "SERIALIZABLE";
593 		break;
594 	/* Should not happen as TRX_ISO_READ_COMMITTED is default */
595 	default:
596 		row->trx_isolation_level = "UNKNOWN";
597 	}
598 
599 	row->trx_unique_checks = (ibool) trx->check_unique_secondary;
600 
601 	row->trx_foreign_key_checks = (ibool) trx->check_foreigns;
602 
603 	s = trx->detailed_error;
604 
605 	if (s != NULL && s[0] != '\0') {
606 
607 		TRX_I_S_STRING_COPY(s,
608 				    row->trx_foreign_key_error,
609 				    TRX_I_S_TRX_FK_ERROR_MAX_LEN, cache);
610 
611 		if (row->trx_foreign_key_error == NULL) {
612 
613 			return(FALSE);
614 		}
615 	} else {
616 		row->trx_foreign_key_error = NULL;
617 	}
618 
619 	row->trx_has_search_latch = (ibool) trx->has_search_latch;
620 
621 	row->trx_search_latch_timeout = trx->search_latch_timeout;
622 
623 	row->trx_is_read_only = trx->read_only;
624 
625 	row->trx_is_autocommit_non_locking = trx_is_autocommit_non_locking(trx);
626 
627 	return(TRUE);
628 }
629 
630 /*******************************************************************//**
631 Format the nth field of "rec" and put it in "buf". The result is always
632 NUL-terminated. Returns the number of bytes that were written to "buf"
633 (including the terminating NUL).
634 @return	end of the result */
635 static
636 ulint
put_nth_field(char * buf,ulint buf_size,ulint n,const dict_index_t * index,const rec_t * rec,const ulint * offsets)637 put_nth_field(
638 /*==========*/
639 	char*			buf,	/*!< out: buffer */
640 	ulint			buf_size,/*!< in: buffer size in bytes */
641 	ulint			n,	/*!< in: number of field */
642 	const dict_index_t*	index,	/*!< in: index */
643 	const rec_t*		rec,	/*!< in: record */
644 	const ulint*		offsets)/*!< in: record offsets, returned
645 					by rec_get_offsets() */
646 {
647 	const byte*	data;
648 	ulint		data_len;
649 	dict_field_t*	dict_field;
650 	ulint		ret;
651 
652 	ut_ad(rec_offs_validate(rec, NULL, offsets));
653 
654 	if (buf_size == 0) {
655 
656 		return(0);
657 	}
658 
659 	ret = 0;
660 
661 	if (n > 0) {
662 		/* we must append ", " before the actual data */
663 
664 		if (buf_size < 3) {
665 
666 			buf[0] = '\0';
667 			return(1);
668 		}
669 
670 		memcpy(buf, ", ", 3);
671 
672 		buf += 2;
673 		buf_size -= 2;
674 		ret += 2;
675 	}
676 
677 	/* now buf_size >= 1 */
678 
679 	data = rec_get_nth_field(rec, offsets, n, &data_len);
680 
681 	dict_field = dict_index_get_nth_field(index, n);
682 
683 	ret += row_raw_format((const char*) data, data_len,
684 			      dict_field, buf, buf_size);
685 
686 	return(ret);
687 }
688 
689 /*******************************************************************//**
690 Fills the "lock_data" member of i_s_locks_row_t object.
691 If memory can not be allocated then FALSE is returned.
692 @return	FALSE if allocation fails */
693 static
694 ibool
fill_lock_data(const char ** lock_data,const lock_t * lock,ulint heap_no,trx_i_s_cache_t * cache)695 fill_lock_data(
696 /*===========*/
697 	const char**		lock_data,/*!< out: "lock_data" to fill */
698 	const lock_t*		lock,	/*!< in: lock used to find the data */
699 	ulint			heap_no,/*!< in: rec num used to find the data */
700 	trx_i_s_cache_t*	cache)	/*!< in/out: cache where to store
701 					volatile data */
702 {
703 	mtr_t			mtr;
704 
705 	const buf_block_t*	block;
706 	const page_t*		page;
707 	const rec_t*		rec;
708 
709 	ut_a(lock_get_type(lock) == LOCK_REC);
710 
711 	mtr_start(&mtr);
712 
713 	block = buf_page_try_get(lock_rec_get_space_id(lock),
714 				 lock_rec_get_page_no(lock),
715 				 &mtr);
716 
717 	if (block == NULL) {
718 
719 		*lock_data = NULL;
720 
721 		mtr_commit(&mtr);
722 
723 		return(TRUE);
724 	}
725 
726 	page = (const page_t*) buf_block_get_frame(block);
727 
728 	rec = page_find_rec_with_heap_no(page, heap_no);
729 
730 	if (page_rec_is_infimum(rec)) {
731 
732 		*lock_data = ha_storage_put_str_memlim(
733 			cache->storage, "infimum pseudo-record",
734 			MAX_ALLOWED_FOR_STORAGE(cache));
735 	} else if (page_rec_is_supremum(rec)) {
736 
737 		*lock_data = ha_storage_put_str_memlim(
738 			cache->storage, "supremum pseudo-record",
739 			MAX_ALLOWED_FOR_STORAGE(cache));
740 	} else {
741 
742 		const dict_index_t*	index;
743 		ulint			n_fields;
744 		mem_heap_t*		heap;
745 		ulint			offsets_onstack[REC_OFFS_NORMAL_SIZE];
746 		ulint*			offsets;
747 		char			buf[TRX_I_S_LOCK_DATA_MAX_LEN];
748 		ulint			buf_used;
749 		ulint			i;
750 
751 		rec_offs_init(offsets_onstack);
752 		offsets = offsets_onstack;
753 
754 		index = lock_rec_get_index(lock);
755 
756 		n_fields = dict_index_get_n_unique(index);
757 
758 		ut_a(n_fields > 0);
759 
760 		heap = NULL;
761 		offsets = rec_get_offsets(rec, index, offsets, n_fields,
762 					  &heap);
763 
764 		/* format and store the data */
765 
766 		buf_used = 0;
767 		for (i = 0; i < n_fields; i++) {
768 
769 			buf_used += put_nth_field(
770 				buf + buf_used, sizeof(buf) - buf_used,
771 				i, index, rec, offsets) - 1;
772 		}
773 
774 		*lock_data = (const char*) ha_storage_put_memlim(
775 			cache->storage, buf, buf_used + 1,
776 			MAX_ALLOWED_FOR_STORAGE(cache));
777 
778 		if (UNIV_UNLIKELY(heap != NULL)) {
779 
780 			/* this means that rec_get_offsets() has created a new
781 			heap and has stored offsets in it; check that this is
782 			really the case and free the heap */
783 			ut_a(offsets != offsets_onstack);
784 			mem_heap_free(heap);
785 		}
786 	}
787 
788 	mtr_commit(&mtr);
789 
790 	if (*lock_data == NULL) {
791 
792 		return(FALSE);
793 	}
794 
795 	return(TRUE);
796 }
797 
798 /*******************************************************************//**
799 Fills i_s_locks_row_t object. Returns its first argument.
800 If memory can not be allocated then FALSE is returned.
801 @return	FALSE if allocation fails */
802 static
803 ibool
fill_locks_row(i_s_locks_row_t * row,const lock_t * lock,ulint heap_no,trx_i_s_cache_t * cache)804 fill_locks_row(
805 /*===========*/
806 	i_s_locks_row_t* row,	/*!< out: result object that's filled */
807 	const lock_t*	lock,	/*!< in: lock to get data from */
808 	ulint		heap_no,/*!< in: lock's record number
809 				or ULINT_UNDEFINED if the lock
810 				is a table lock */
811 	trx_i_s_cache_t* cache)	/*!< in/out: cache into which to copy
812 				volatile strings */
813 {
814 	row->lock_trx_id = lock_get_trx_id(lock);
815 	row->lock_mode = lock_get_mode_str(lock);
816 	row->lock_type = lock_get_type_str(lock);
817 
818 	row->lock_table = ha_storage_put_str_memlim(
819 		cache->storage, lock_get_table_name(lock),
820 		MAX_ALLOWED_FOR_STORAGE(cache));
821 
822 	/* memory could not be allocated */
823 	if (row->lock_table == NULL) {
824 
825 		return(FALSE);
826 	}
827 
828 	switch (lock_get_type(lock)) {
829 	case LOCK_REC:
830 		row->lock_index = ha_storage_put_str_memlim(
831 			cache->storage, lock_rec_get_index_name(lock),
832 			MAX_ALLOWED_FOR_STORAGE(cache));
833 
834 		/* memory could not be allocated */
835 		if (row->lock_index == NULL) {
836 
837 			return(FALSE);
838 		}
839 
840 		row->lock_space = lock_rec_get_space_id(lock);
841 		row->lock_page = lock_rec_get_page_no(lock);
842 		row->lock_rec = heap_no;
843 
844 		if (!fill_lock_data(&row->lock_data, lock, heap_no, cache)) {
845 
846 			/* memory could not be allocated */
847 			return(FALSE);
848 		}
849 
850 		break;
851 	case LOCK_TABLE:
852 		row->lock_index = NULL;
853 
854 		row->lock_space = ULINT_UNDEFINED;
855 		row->lock_page = ULINT_UNDEFINED;
856 		row->lock_rec = ULINT_UNDEFINED;
857 
858 		row->lock_data = NULL;
859 
860 		break;
861 	default:
862 		ut_error;
863 	}
864 
865 	row->lock_table_id = lock_get_table_id(lock);
866 
867 	row->hash_chain.value = row;
868 	ut_ad(i_s_locks_row_validate(row));
869 
870 	return(TRUE);
871 }
872 
873 /*******************************************************************//**
874 Fills i_s_lock_waits_row_t object. Returns its first argument.
875 @return	result object that's filled */
876 static
877 i_s_lock_waits_row_t*
fill_lock_waits_row(i_s_lock_waits_row_t * row,const i_s_locks_row_t * requested_lock_row,const i_s_locks_row_t * blocking_lock_row)878 fill_lock_waits_row(
879 /*================*/
880 	i_s_lock_waits_row_t*	row,		/*!< out: result object
881 						that's filled */
882 	const i_s_locks_row_t*	requested_lock_row,/*!< in: pointer to the
883 						relevant requested lock
884 						row in innodb_locks */
885 	const i_s_locks_row_t*	blocking_lock_row)/*!< in: pointer to the
886 						relevant blocking lock
887 						row in innodb_locks */
888 {
889 	ut_ad(i_s_locks_row_validate(requested_lock_row));
890 	ut_ad(i_s_locks_row_validate(blocking_lock_row));
891 
892 	row->requested_lock_row = requested_lock_row;
893 	row->blocking_lock_row = blocking_lock_row;
894 
895 	return(row);
896 }
897 
898 /*******************************************************************//**
899 Calculates a hash fold for a lock. For a record lock the fold is
900 calculated from 4 elements, which uniquely identify a lock at a given
901 point in time: transaction id, space id, page number, record number.
902 For a table lock the fold is table's id.
903 @return	fold */
904 static
905 ulint
fold_lock(const lock_t * lock,ulint heap_no)906 fold_lock(
907 /*======*/
908 	const lock_t*	lock,	/*!< in: lock object to fold */
909 	ulint		heap_no)/*!< in: lock's record number
910 				or ULINT_UNDEFINED if the lock
911 				is a table lock */
912 {
913 #ifdef TEST_LOCK_FOLD_ALWAYS_DIFFERENT
914 	static ulint	fold = 0;
915 
916 	return(fold++);
917 #else
918 	ulint	ret;
919 
920 	switch (lock_get_type(lock)) {
921 	case LOCK_REC:
922 		ut_a(heap_no != ULINT_UNDEFINED);
923 
924 		ret = ut_fold_ulint_pair((ulint) lock_get_trx_id(lock),
925 					 lock_rec_get_space_id(lock));
926 
927 		ret = ut_fold_ulint_pair(ret,
928 					 lock_rec_get_page_no(lock));
929 
930 		ret = ut_fold_ulint_pair(ret, heap_no);
931 
932 		break;
933 	case LOCK_TABLE:
934 		/* this check is actually not necessary for continuing
935 		correct operation, but something must have gone wrong if
936 		it fails. */
937 		ut_a(heap_no == ULINT_UNDEFINED);
938 
939 		ret = (ulint) lock_get_table_id(lock);
940 
941 		break;
942 	default:
943 		ut_error;
944 	}
945 
946 	return(ret);
947 #endif
948 }
949 
950 /*******************************************************************//**
951 Checks whether i_s_locks_row_t object represents a lock_t object.
952 @return	TRUE if they match */
953 static
954 ibool
locks_row_eq_lock(const i_s_locks_row_t * row,const lock_t * lock,ulint heap_no)955 locks_row_eq_lock(
956 /*==============*/
957 	const i_s_locks_row_t*	row,	/*!< in: innodb_locks row */
958 	const lock_t*		lock,	/*!< in: lock object */
959 	ulint			heap_no)/*!< in: lock's record number
960 					or ULINT_UNDEFINED if the lock
961 					is a table lock */
962 {
963 	ut_ad(i_s_locks_row_validate(row));
964 #ifdef TEST_NO_LOCKS_ROW_IS_EVER_EQUAL_TO_LOCK_T
965 	return(0);
966 #else
967 	switch (lock_get_type(lock)) {
968 	case LOCK_REC:
969 		ut_a(heap_no != ULINT_UNDEFINED);
970 
971 		return(row->lock_trx_id == lock_get_trx_id(lock)
972 		       && row->lock_space == lock_rec_get_space_id(lock)
973 		       && row->lock_page == lock_rec_get_page_no(lock)
974 		       && row->lock_rec == heap_no);
975 
976 	case LOCK_TABLE:
977 		/* this check is actually not necessary for continuing
978 		correct operation, but something must have gone wrong if
979 		it fails. */
980 		ut_a(heap_no == ULINT_UNDEFINED);
981 
982 		return(row->lock_trx_id == lock_get_trx_id(lock)
983 		       && row->lock_table_id == lock_get_table_id(lock));
984 
985 	default:
986 		ut_error;
987 		return(FALSE);
988 	}
989 #endif
990 }
991 
992 /*******************************************************************//**
993 Searches for a row in the innodb_locks cache that has a specified id.
994 This happens in O(1) time since a hash table is used. Returns pointer to
995 the row or NULL if none is found.
996 @return	row or NULL */
997 static
998 i_s_locks_row_t*
search_innodb_locks(trx_i_s_cache_t * cache,const lock_t * lock,ulint heap_no)999 search_innodb_locks(
1000 /*================*/
1001 	trx_i_s_cache_t*	cache,	/*!< in: cache */
1002 	const lock_t*		lock,	/*!< in: lock to search for */
1003 	ulint			heap_no)/*!< in: lock's record number
1004 					or ULINT_UNDEFINED if the lock
1005 					is a table lock */
1006 {
1007 	i_s_hash_chain_t*	hash_chain;
1008 
1009 	HASH_SEARCH(
1010 		/* hash_chain->"next" */
1011 		next,
1012 		/* the hash table */
1013 		cache->locks_hash,
1014 		/* fold */
1015 		fold_lock(lock, heap_no),
1016 		/* the type of the next variable */
1017 		i_s_hash_chain_t*,
1018 		/* auxiliary variable */
1019 		hash_chain,
1020 		/* assertion on every traversed item */
1021 		ut_ad(i_s_locks_row_validate(hash_chain->value)),
1022 		/* this determines if we have found the lock */
1023 		locks_row_eq_lock(hash_chain->value, lock, heap_no));
1024 
1025 	if (hash_chain == NULL) {
1026 
1027 		return(NULL);
1028 	}
1029 	/* else */
1030 
1031 	return(hash_chain->value);
1032 }
1033 
1034 /*******************************************************************//**
1035 Adds new element to the locks cache, enlarging it if necessary.
1036 Returns a pointer to the added row. If the row is already present then
1037 no row is added and a pointer to the existing row is returned.
1038 If row can not be allocated then NULL is returned.
1039 @return	row */
1040 static
1041 i_s_locks_row_t*
add_lock_to_cache(trx_i_s_cache_t * cache,const lock_t * lock,ulint heap_no)1042 add_lock_to_cache(
1043 /*==============*/
1044 	trx_i_s_cache_t*	cache,	/*!< in/out: cache */
1045 	const lock_t*		lock,	/*!< in: the element to add */
1046 	ulint			heap_no)/*!< in: lock's record number
1047 					or ULINT_UNDEFINED if the lock
1048 					is a table lock */
1049 {
1050 	i_s_locks_row_t*	dst_row;
1051 
1052 #ifdef TEST_ADD_EACH_LOCKS_ROW_MANY_TIMES
1053 	ulint	i;
1054 	for (i = 0; i < 10000; i++) {
1055 #endif
1056 #ifndef TEST_DO_NOT_CHECK_FOR_DUPLICATE_ROWS
1057 	/* quit if this lock is already present */
1058 	dst_row = search_innodb_locks(cache, lock, heap_no);
1059 	if (dst_row != NULL) {
1060 
1061 		ut_ad(i_s_locks_row_validate(dst_row));
1062 		return(dst_row);
1063 	}
1064 #endif
1065 
1066 	dst_row = (i_s_locks_row_t*)
1067 		table_cache_create_empty_row(&cache->innodb_locks, cache);
1068 
1069 	/* memory could not be allocated */
1070 	if (dst_row == NULL) {
1071 
1072 		return(NULL);
1073 	}
1074 
1075 	if (!fill_locks_row(dst_row, lock, heap_no, cache)) {
1076 
1077 		/* memory could not be allocated */
1078 		cache->innodb_locks.rows_used--;
1079 		return(NULL);
1080 	}
1081 
1082 #ifndef TEST_DO_NOT_INSERT_INTO_THE_HASH_TABLE
1083 	HASH_INSERT(
1084 		/* the type used in the hash chain */
1085 		i_s_hash_chain_t,
1086 		/* hash_chain->"next" */
1087 		next,
1088 		/* the hash table */
1089 		cache->locks_hash,
1090 		/* fold */
1091 		fold_lock(lock, heap_no),
1092 		/* add this data to the hash */
1093 		&dst_row->hash_chain);
1094 #endif
1095 #ifdef TEST_ADD_EACH_LOCKS_ROW_MANY_TIMES
1096 	} /* for()-loop */
1097 #endif
1098 
1099 	ut_ad(i_s_locks_row_validate(dst_row));
1100 	return(dst_row);
1101 }
1102 
1103 /*******************************************************************//**
1104 Adds new pair of locks to the lock waits cache.
1105 If memory can not be allocated then FALSE is returned.
1106 @return	FALSE if allocation fails */
1107 static
1108 ibool
add_lock_wait_to_cache(trx_i_s_cache_t * cache,const i_s_locks_row_t * requested_lock_row,const i_s_locks_row_t * blocking_lock_row)1109 add_lock_wait_to_cache(
1110 /*===================*/
1111 	trx_i_s_cache_t*	cache,		/*!< in/out: cache */
1112 	const i_s_locks_row_t*	requested_lock_row,/*!< in: pointer to the
1113 						relevant requested lock
1114 						row in innodb_locks */
1115 	const i_s_locks_row_t*	blocking_lock_row)/*!< in: pointer to the
1116 						relevant blocking lock
1117 						row in innodb_locks */
1118 {
1119 	i_s_lock_waits_row_t*	dst_row;
1120 
1121 	dst_row = (i_s_lock_waits_row_t*)
1122 		table_cache_create_empty_row(&cache->innodb_lock_waits,
1123 					     cache);
1124 
1125 	/* memory could not be allocated */
1126 	if (dst_row == NULL) {
1127 
1128 		return(FALSE);
1129 	}
1130 
1131 	fill_lock_waits_row(dst_row, requested_lock_row, blocking_lock_row);
1132 
1133 	return(TRUE);
1134 }
1135 
1136 /*******************************************************************//**
1137 Adds transaction's relevant (important) locks to cache.
1138 If the transaction is waiting, then the wait lock is added to
1139 innodb_locks and a pointer to the added row is returned in
1140 requested_lock_row, otherwise requested_lock_row is set to NULL.
1141 If rows can not be allocated then FALSE is returned and the value of
1142 requested_lock_row is undefined.
1143 @return	FALSE if allocation fails */
1144 static
1145 ibool
add_trx_relevant_locks_to_cache(trx_i_s_cache_t * cache,const trx_t * trx,i_s_locks_row_t ** requested_lock_row)1146 add_trx_relevant_locks_to_cache(
1147 /*============================*/
1148 	trx_i_s_cache_t*	cache,	/*!< in/out: cache */
1149 	const trx_t*		trx,	/*!< in: transaction */
1150 	i_s_locks_row_t**	requested_lock_row)/*!< out: pointer to the
1151 					requested lock row, or NULL or
1152 					undefined */
1153 {
1154 	ut_ad(lock_mutex_own());
1155 
1156 	/* If transaction is waiting we add the wait lock and all locks
1157 	from another transactions that are blocking the wait lock. */
1158 	if (trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
1159 
1160 		const lock_t*		curr_lock;
1161 		ulint			wait_lock_heap_no;
1162 		i_s_locks_row_t*	blocking_lock_row;
1163 		lock_queue_iterator_t	iter;
1164 
1165 		ut_a(trx->lock.wait_lock != NULL);
1166 
1167 		wait_lock_heap_no
1168 			= wait_lock_get_heap_no(trx->lock.wait_lock);
1169 
1170 		/* add the requested lock */
1171 		*requested_lock_row
1172 			= add_lock_to_cache(cache, trx->lock.wait_lock,
1173 					    wait_lock_heap_no);
1174 
1175 		/* memory could not be allocated */
1176 		if (*requested_lock_row == NULL) {
1177 
1178 			return(FALSE);
1179 		}
1180 
1181 		/* then iterate over the locks before the wait lock and
1182 		add the ones that are blocking it */
1183 
1184 		lock_queue_iterator_reset(&iter, trx->lock.wait_lock,
1185 					  ULINT_UNDEFINED);
1186 
1187 		for (curr_lock = lock_queue_iterator_get_prev(&iter);
1188 		     curr_lock != NULL;
1189 		     curr_lock = lock_queue_iterator_get_prev(&iter)) {
1190 
1191 			if (lock_has_to_wait(trx->lock.wait_lock,
1192 					     curr_lock)) {
1193 
1194 				/* add the lock that is
1195 				blocking trx->lock.wait_lock */
1196 				blocking_lock_row
1197 					= add_lock_to_cache(
1198 						cache, curr_lock,
1199 						/* heap_no is the same
1200 						for the wait and waited
1201 						locks */
1202 						wait_lock_heap_no);
1203 
1204 				/* memory could not be allocated */
1205 				if (blocking_lock_row == NULL) {
1206 
1207 					return(FALSE);
1208 				}
1209 
1210 				/* add the relation between both locks
1211 				to innodb_lock_waits */
1212 				if (!add_lock_wait_to_cache(
1213 						cache, *requested_lock_row,
1214 						blocking_lock_row)) {
1215 
1216 					/* memory could not be allocated */
1217 					return(FALSE);
1218 				}
1219 			}
1220 		}
1221 	} else {
1222 
1223 		*requested_lock_row = NULL;
1224 	}
1225 
1226 	return(TRUE);
1227 }
1228 
1229 /** The minimum time that a cache must not be updated after it has been
1230 read for the last time; measured in microseconds. We use this technique
1231 to ensure that SELECTs which join several INFORMATION SCHEMA tables read
1232 the same version of the cache. */
1233 #define CACHE_MIN_IDLE_TIME_US	100000 /* 0.1 sec */
1234 
1235 /*******************************************************************//**
1236 Checks if the cache can safely be updated.
1237 @return	TRUE if can be updated */
1238 static
1239 ibool
can_cache_be_updated(trx_i_s_cache_t * cache)1240 can_cache_be_updated(
1241 /*=================*/
1242 	trx_i_s_cache_t*	cache)	/*!< in: cache */
1243 {
1244 	ullint	now;
1245 
1246 	/* Here we read cache->last_read without acquiring its mutex
1247 	because last_read is only updated when a shared rw lock on the
1248 	whole cache is being held (see trx_i_s_cache_end_read()) and
1249 	we are currently holding an exclusive rw lock on the cache.
1250 	So it is not possible for last_read to be updated while we are
1251 	reading it. */
1252 
1253 #ifdef UNIV_SYNC_DEBUG
1254 	ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
1255 #endif
1256 
1257 	now = ut_time_us(NULL);
1258 	if (now - cache->last_read > CACHE_MIN_IDLE_TIME_US) {
1259 
1260 		return(TRUE);
1261 	}
1262 
1263 	return(FALSE);
1264 }
1265 
1266 /*******************************************************************//**
1267 Declare a cache empty, preparing it to be filled up. Not all resources
1268 are freed because they can be reused. */
1269 static
1270 void
trx_i_s_cache_clear(trx_i_s_cache_t * cache)1271 trx_i_s_cache_clear(
1272 /*================*/
1273 	trx_i_s_cache_t*	cache)	/*!< out: cache to clear */
1274 {
1275 	cache->innodb_trx.rows_used = 0;
1276 	cache->innodb_locks.rows_used = 0;
1277 	cache->innodb_lock_waits.rows_used = 0;
1278 
1279 	hash_table_clear(cache->locks_hash);
1280 
1281 	ha_storage_empty(&cache->storage);
1282 }
1283 
1284 /*******************************************************************//**
1285 Fetches the data needed to fill the 3 INFORMATION SCHEMA tables into the
1286 table cache buffer. Cache must be locked for write. */
1287 static
1288 void
fetch_data_into_cache_low(trx_i_s_cache_t * cache,ibool only_ac_nl,trx_list_t * trx_list)1289 fetch_data_into_cache_low(
1290 /*======================*/
1291 	trx_i_s_cache_t*	cache,		/*!< in/out: cache */
1292 	ibool			only_ac_nl,	/*!< in: only select non-locking
1293 						autocommit transactions */
1294 	trx_list_t*		trx_list)	/*!< in: trx list */
1295 {
1296 	const trx_t*		trx;
1297 
1298 	ut_ad(trx_list == &trx_sys->rw_trx_list
1299 	      || trx_list == &trx_sys->ro_trx_list
1300 	      || trx_list == &trx_sys->mysql_trx_list);
1301 
1302 	ut_ad(only_ac_nl == (trx_list == &trx_sys->mysql_trx_list));
1303 
1304 	/* Iterate over the transaction list and add each one
1305 	to innodb_trx's cache. We also add all locks that are relevant
1306 	to each transaction into innodb_locks' and innodb_lock_waits'
1307 	caches. */
1308 
1309 	for (trx = UT_LIST_GET_FIRST(*trx_list);
1310 	     trx != NULL;
1311 	     trx =
1312 	     (trx_list == &trx_sys->mysql_trx_list
1313 	      ? UT_LIST_GET_NEXT(mysql_trx_list, trx)
1314 	      : UT_LIST_GET_NEXT(trx_list, trx))) {
1315 
1316 		i_s_trx_row_t*		trx_row;
1317 		i_s_locks_row_t*	requested_lock_row;
1318 
1319 		if (trx->state == TRX_STATE_NOT_STARTED
1320 		    || (only_ac_nl && !trx_is_autocommit_non_locking(trx))) {
1321 
1322 			continue;
1323 		}
1324 
1325 		assert_trx_nonlocking_or_in_list(trx);
1326 
1327 		ut_ad(trx->in_ro_trx_list
1328 		      == (trx_list == &trx_sys->ro_trx_list));
1329 
1330 		ut_ad(trx->in_rw_trx_list
1331 		      == (trx_list == &trx_sys->rw_trx_list));
1332 
1333 		if (!add_trx_relevant_locks_to_cache(cache, trx,
1334 						     &requested_lock_row)) {
1335 
1336 			cache->is_truncated = TRUE;
1337 			return;
1338 		}
1339 
1340 		trx_row = (i_s_trx_row_t*)
1341 			table_cache_create_empty_row(&cache->innodb_trx,
1342 						     cache);
1343 
1344 		/* memory could not be allocated */
1345 		if (trx_row == NULL) {
1346 
1347 			cache->is_truncated = TRUE;
1348 			return;
1349 		}
1350 
1351 		if (!fill_trx_row(trx_row, trx, requested_lock_row, cache)) {
1352 
1353 			/* memory could not be allocated */
1354 			cache->innodb_trx.rows_used--;
1355 			cache->is_truncated = TRUE;
1356 			return;
1357 		}
1358 	}
1359 }
1360 
1361 /*******************************************************************//**
1362 Fetches the data needed to fill the 3 INFORMATION SCHEMA tables into the
1363 table cache buffer. Cache must be locked for write. */
1364 static
1365 void
fetch_data_into_cache(trx_i_s_cache_t * cache)1366 fetch_data_into_cache(
1367 /*==================*/
1368 	trx_i_s_cache_t*	cache)	/*!< in/out: cache */
1369 {
1370 	ut_ad(lock_mutex_own());
1371 	ut_ad(mutex_own(&trx_sys->mutex));
1372 
1373 	trx_i_s_cache_clear(cache);
1374 
1375 	fetch_data_into_cache_low(cache, FALSE, &trx_sys->rw_trx_list);
1376 	fetch_data_into_cache_low(cache, FALSE, &trx_sys->ro_trx_list);
1377 
1378 	/* Only select autocommit non-locking selects because they can
1379 	only be on the MySQL transaction list (TRUE). */
1380 	fetch_data_into_cache_low(cache, TRUE, &trx_sys->mysql_trx_list);
1381 
1382 	cache->is_truncated = FALSE;
1383 }
1384 
1385 /*******************************************************************//**
1386 Update the transactions cache if it has not been read for some time.
1387 Called from handler/i_s.cc.
1388 @return	0 - fetched, 1 - not */
1389 UNIV_INTERN
1390 int
trx_i_s_possibly_fetch_data_into_cache(trx_i_s_cache_t * cache)1391 trx_i_s_possibly_fetch_data_into_cache(
1392 /*===================================*/
1393 	trx_i_s_cache_t*	cache)	/*!< in/out: cache */
1394 {
1395 	if (!can_cache_be_updated(cache)) {
1396 
1397 		return(1);
1398 	}
1399 
1400 	/* We need to read trx_sys and record/table lock queues */
1401 
1402 	lock_mutex_enter();
1403 
1404 	mutex_enter(&trx_sys->mutex);
1405 
1406 	fetch_data_into_cache(cache);
1407 
1408 	mutex_exit(&trx_sys->mutex);
1409 
1410 	lock_mutex_exit();
1411 
1412 	return(0);
1413 }
1414 
1415 /*******************************************************************//**
1416 Returns TRUE if the data in the cache is truncated due to the memory
1417 limit posed by TRX_I_S_MEM_LIMIT.
1418 @return	TRUE if truncated */
1419 UNIV_INTERN
1420 ibool
trx_i_s_cache_is_truncated(trx_i_s_cache_t * cache)1421 trx_i_s_cache_is_truncated(
1422 /*=======================*/
1423 	trx_i_s_cache_t*	cache)	/*!< in: cache */
1424 {
1425 	return(cache->is_truncated);
1426 }
1427 
1428 /*******************************************************************//**
1429 Initialize INFORMATION SCHEMA trx related cache. */
1430 UNIV_INTERN
1431 void
trx_i_s_cache_init(trx_i_s_cache_t * cache)1432 trx_i_s_cache_init(
1433 /*===============*/
1434 	trx_i_s_cache_t*	cache)	/*!< out: cache to init */
1435 {
1436 	/* The latching is done in the following order:
1437 	acquire trx_i_s_cache_t::rw_lock, X
1438 	acquire lock mutex
1439 	release lock mutex
1440 	release trx_i_s_cache_t::rw_lock
1441 	acquire trx_i_s_cache_t::rw_lock, S
1442 	acquire trx_i_s_cache_t::last_read_mutex
1443 	release trx_i_s_cache_t::last_read_mutex
1444 	release trx_i_s_cache_t::rw_lock */
1445 
1446 	rw_lock_create(trx_i_s_cache_lock_key, &cache->rw_lock,
1447 		       SYNC_TRX_I_S_RWLOCK);
1448 
1449 	cache->last_read = 0;
1450 
1451 	mutex_create(cache_last_read_mutex_key,
1452 		     &cache->last_read_mutex, SYNC_TRX_I_S_LAST_READ);
1453 
1454 	table_cache_init(&cache->innodb_trx, sizeof(i_s_trx_row_t));
1455 	table_cache_init(&cache->innodb_locks, sizeof(i_s_locks_row_t));
1456 	table_cache_init(&cache->innodb_lock_waits,
1457 			 sizeof(i_s_lock_waits_row_t));
1458 
1459 	cache->locks_hash = hash_create(LOCKS_HASH_CELLS_NUM);
1460 
1461 	cache->storage = ha_storage_create(CACHE_STORAGE_INITIAL_SIZE,
1462 					   CACHE_STORAGE_HASH_CELLS);
1463 
1464 	cache->mem_allocd = 0;
1465 
1466 	cache->is_truncated = FALSE;
1467 }
1468 
1469 /*******************************************************************//**
1470 Free the INFORMATION SCHEMA trx related cache. */
1471 UNIV_INTERN
1472 void
trx_i_s_cache_free(trx_i_s_cache_t * cache)1473 trx_i_s_cache_free(
1474 /*===============*/
1475 	trx_i_s_cache_t*	cache)	/*!< in, own: cache to free */
1476 {
1477 	hash_table_free(cache->locks_hash);
1478 	ha_storage_free(cache->storage);
1479 	table_cache_free(&cache->innodb_trx);
1480 	table_cache_free(&cache->innodb_locks);
1481 	table_cache_free(&cache->innodb_lock_waits);
1482 	memset(cache, 0, sizeof *cache);
1483 }
1484 
1485 /*******************************************************************//**
1486 Issue a shared/read lock on the tables cache. */
1487 UNIV_INTERN
1488 void
trx_i_s_cache_start_read(trx_i_s_cache_t * cache)1489 trx_i_s_cache_start_read(
1490 /*=====================*/
1491 	trx_i_s_cache_t*	cache)	/*!< in: cache */
1492 {
1493 	rw_lock_s_lock(&cache->rw_lock);
1494 }
1495 
1496 /*******************************************************************//**
1497 Release a shared/read lock on the tables cache. */
1498 UNIV_INTERN
1499 void
trx_i_s_cache_end_read(trx_i_s_cache_t * cache)1500 trx_i_s_cache_end_read(
1501 /*===================*/
1502 	trx_i_s_cache_t*	cache)	/*!< in: cache */
1503 {
1504 	ullint	now;
1505 
1506 #ifdef UNIV_SYNC_DEBUG
1507 	ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_SHARED));
1508 #endif
1509 
1510 	/* update cache last read time */
1511 	now = ut_time_us(NULL);
1512 	mutex_enter(&cache->last_read_mutex);
1513 	cache->last_read = now;
1514 	mutex_exit(&cache->last_read_mutex);
1515 
1516 	rw_lock_s_unlock(&cache->rw_lock);
1517 }
1518 
1519 /*******************************************************************//**
1520 Issue an exclusive/write lock on the tables cache. */
1521 UNIV_INTERN
1522 void
trx_i_s_cache_start_write(trx_i_s_cache_t * cache)1523 trx_i_s_cache_start_write(
1524 /*======================*/
1525 	trx_i_s_cache_t*	cache)	/*!< in: cache */
1526 {
1527 	rw_lock_x_lock(&cache->rw_lock);
1528 }
1529 
1530 /*******************************************************************//**
1531 Release an exclusive/write lock on the tables cache. */
1532 UNIV_INTERN
1533 void
trx_i_s_cache_end_write(trx_i_s_cache_t * cache)1534 trx_i_s_cache_end_write(
1535 /*====================*/
1536 	trx_i_s_cache_t*	cache)	/*!< in: cache */
1537 {
1538 #ifdef UNIV_SYNC_DEBUG
1539 	ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
1540 #endif
1541 
1542 	rw_lock_x_unlock(&cache->rw_lock);
1543 }
1544 
1545 /*******************************************************************//**
1546 Selects a INFORMATION SCHEMA table cache from the whole cache.
1547 @return	table cache */
1548 static
1549 i_s_table_cache_t*
cache_select_table(trx_i_s_cache_t * cache,enum i_s_table table)1550 cache_select_table(
1551 /*===============*/
1552 	trx_i_s_cache_t*	cache,	/*!< in: whole cache */
1553 	enum i_s_table		table)	/*!< in: which table */
1554 {
1555 	i_s_table_cache_t*	table_cache;
1556 
1557 #ifdef UNIV_SYNC_DEBUG
1558 	ut_a(rw_lock_own(&cache->rw_lock, RW_LOCK_SHARED)
1559 	     || rw_lock_own(&cache->rw_lock, RW_LOCK_EX));
1560 #endif
1561 
1562 	switch (table) {
1563 	case I_S_INNODB_TRX:
1564 		table_cache = &cache->innodb_trx;
1565 		break;
1566 	case I_S_INNODB_LOCKS:
1567 		table_cache = &cache->innodb_locks;
1568 		break;
1569 	case I_S_INNODB_LOCK_WAITS:
1570 		table_cache = &cache->innodb_lock_waits;
1571 		break;
1572 	default:
1573 		ut_error;
1574 	}
1575 
1576 	return(table_cache);
1577 }
1578 
1579 /*******************************************************************//**
1580 Retrieves the number of used rows in the cache for a given
1581 INFORMATION SCHEMA table.
1582 @return	number of rows */
1583 UNIV_INTERN
1584 ulint
trx_i_s_cache_get_rows_used(trx_i_s_cache_t * cache,enum i_s_table table)1585 trx_i_s_cache_get_rows_used(
1586 /*========================*/
1587 	trx_i_s_cache_t*	cache,	/*!< in: cache */
1588 	enum i_s_table		table)	/*!< in: which table */
1589 {
1590 	i_s_table_cache_t*	table_cache;
1591 
1592 	table_cache = cache_select_table(cache, table);
1593 
1594 	return(table_cache->rows_used);
1595 }
1596 
1597 /*******************************************************************//**
1598 Retrieves the nth row (zero-based) in the cache for a given
1599 INFORMATION SCHEMA table.
1600 @return	row */
1601 UNIV_INTERN
1602 void*
trx_i_s_cache_get_nth_row(trx_i_s_cache_t * cache,enum i_s_table table,ulint n)1603 trx_i_s_cache_get_nth_row(
1604 /*======================*/
1605 	trx_i_s_cache_t*	cache,	/*!< in: cache */
1606 	enum i_s_table		table,	/*!< in: which table */
1607 	ulint			n)	/*!< in: row number */
1608 {
1609 	i_s_table_cache_t*	table_cache;
1610 	ulint			i;
1611 	void*			row;
1612 
1613 	table_cache = cache_select_table(cache, table);
1614 
1615 	ut_a(n < table_cache->rows_used);
1616 
1617 	row = NULL;
1618 
1619 	for (i = 0; i < MEM_CHUNKS_IN_TABLE_CACHE; i++) {
1620 
1621 		if (table_cache->chunks[i].offset
1622 		    + table_cache->chunks[i].rows_allocd > n) {
1623 
1624 			row = (char*) table_cache->chunks[i].base
1625 				+ (n - table_cache->chunks[i].offset)
1626 				* table_cache->row_size;
1627 			break;
1628 		}
1629 	}
1630 
1631 	ut_a(row != NULL);
1632 
1633 	return(row);
1634 }
1635 
1636 /*******************************************************************//**
1637 Crafts a lock id string from a i_s_locks_row_t object. Returns its
1638 second argument. This function aborts if there is not enough space in
1639 lock_id. Be sure to provide at least TRX_I_S_LOCK_ID_MAX_LEN + 1 if you
1640 want to be 100% sure that it will not abort.
1641 @return	resulting lock id */
1642 UNIV_INTERN
1643 char*
trx_i_s_create_lock_id(const i_s_locks_row_t * row,char * lock_id,ulint lock_id_size)1644 trx_i_s_create_lock_id(
1645 /*===================*/
1646 	const i_s_locks_row_t*	row,	/*!< in: innodb_locks row */
1647 	char*			lock_id,/*!< out: resulting lock_id */
1648 	ulint			lock_id_size)/*!< in: size of the lock id
1649 					buffer */
1650 {
1651 	int	res_len;
1652 
1653 	/* please adjust TRX_I_S_LOCK_ID_MAX_LEN if you change this */
1654 
1655 	if (row->lock_space != ULINT_UNDEFINED) {
1656 		/* record lock */
1657 		res_len = ut_snprintf(lock_id, lock_id_size,
1658 				      TRX_ID_FMT ":%lu:%lu:%lu",
1659 				      row->lock_trx_id, row->lock_space,
1660 				      row->lock_page, row->lock_rec);
1661 	} else {
1662 		/* table lock */
1663 		res_len = ut_snprintf(lock_id, lock_id_size,
1664 				      TRX_ID_FMT":" UINT64PF,
1665 				      row->lock_trx_id,
1666 				      row->lock_table_id);
1667 	}
1668 
1669 	/* the typecast is safe because snprintf(3) never returns
1670 	negative result */
1671 	ut_a(res_len >= 0);
1672 	ut_a((ulint) res_len < lock_id_size);
1673 
1674 	return(lock_id);
1675 }
1676