~drizzle-trunk/drizzle/development

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