1 /* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22
23 // First include (the generated) my_config.h, to get correct platform defines.
24 #include "my_config.h"
25 #include <gtest/gtest.h>
26 #include "test_utils.h"
27
28 #include "table_cache.h"
29
30 #include "ha_example.h"
31
32 /*
33 We need example_hton to be able short-cut creation of example
34 handler instances for mock TABLE objects.
35 */
36 extern handlerton *example_hton;
37
38 namespace table_cache_unittest {
39
40 using my_testing::Server_initializer;
41
42
43 /**
44 Test fixture for basic tests involving Table_cache
45 and Table_cache_manager classes.
46
47 Unlike more advanced fixture it doesn't initialize
48 table cache manager, but only prepares THD objects
49 necessary for testing.
50 */
51
52 class TableCacheBasicTest : public ::testing::Test
53 {
54 protected:
55 static const uint MAX_THREADS= 3;
56
SetUp()57 virtual void SetUp()
58 {
59 for (uint i= 0; i < MAX_THREADS; ++i)
60 {
61 initializer[i].SetUp();
62 initializer[i].thd()->thread_id= i + 1;
63 }
64
65 ::testing::FLAGS_gtest_death_test_style = "threadsafe";
66 }
TearDown()67 virtual void TearDown()
68 {
69 for (uint i= 0; i < MAX_THREADS; ++i)
70 initializer[i].TearDown();
71 }
72
get_thd(uint index)73 THD *get_thd(uint index) { return initializer[index].thd(); }
74
75 Server_initializer initializer[MAX_THREADS];
76 };
77
78
79 /**
80 A more advanced fixture that also initializes table_cache_manager
81 with one Table_cache instance and TDC.
82 */
83
84 class TableCacheSingleCacheTest : public TableCacheBasicTest
85 {
86 protected:
CachesNumber()87 virtual uint CachesNumber() { return 1; }
SetUp()88 virtual void SetUp()
89 {
90 TableCacheBasicTest::SetUp();
91
92 /*
93 In addition to table_cache_manager we want to have initialized
94 TDC so we can use its HASH object for calculating hash values
95 and be able to free TABLE objects correctly (we need LOCK_open
96 initialized for this).
97 */
98 table_cache_instances= CachesNumber();
99 table_cache_size_per_instance= 100;
100 ASSERT_FALSE(table_def_init());
101 }
TearDown()102 virtual void TearDown()
103 {
104 table_def_free();
105 TableCacheBasicTest::TearDown();
106 }
107 };
108
109
110 /**
111 Another advanced fixture that also initializes table_cache_manager
112 with two Table_cache instances and TDC.
113 */
114
115 class TableCacheDoubleCacheTest : public TableCacheSingleCacheTest
116 {
117 protected:
CachesNumber()118 virtual uint CachesNumber() { return 2; }
119 };
120
121
122 /**
123 Class for mock TABLE_SHARE object which also allows to create
124 associated TABLE objects which are usable with Table_cache.
125 */
126
127 class Mock_share : public TABLE_SHARE
128 {
129 MEM_ROOT m_mem_root;
130 Table_cache_element *cache_element_arr[Table_cache_manager::MAX_TABLE_CACHES];
131
132 public:
Mock_share(const char * key)133 Mock_share(const char *key)
134 {
135 memset(static_cast<void*>(this), 0, sizeof(TABLE_SHARE));
136 /*
137 Both table_cache_key and cache_element array are used by
138 Table_cache code.
139 */
140 table_cache_key.str= (char*)key;
141 table_cache_key.length= strlen(key);
142 memset(cache_element_arr, 0, sizeof(cache_element_arr));
143 cache_element= cache_element_arr;
144 // MEM_ROOT is used for constructing ha_example() instances.
145 init_alloc_root(&m_mem_root, 1024, 0);
146 /*
147 Assertion in some of Table_cache methods check that version of
148 the share is up-to-date.
149 */
150 version= refresh_version;
151 // Ensure that share is never destroyed.
152 ref_count= UINT_MAX;
153 }
154
~Mock_share()155 ~Mock_share()
156 {
157 free_root(&m_mem_root, MYF(0));
158 }
159
create_table(THD * thd)160 TABLE *create_table(THD *thd)
161 {
162 TABLE *result= (TABLE *)my_malloc(sizeof(TABLE), MYF(0));
163
164 memset(static_cast<void*>(result), 0, sizeof(TABLE));
165 result->s= this;
166 // We create TABLE which is already marked as used
167 result->in_use= thd;
168 /*
169 Assertions in some of Table_cache methods need non-NULL
170 TABLE::file and TABLE::db_stat. Code that frees unused
171 TABLE objects needs proper "handler" instance.
172 */
173 result->file= new (&m_mem_root) ha_example(example_hton, this);
174 result->db_stat= HA_READ_ONLY;
175
176 return result;
177 }
178
destroy_table(TABLE * table)179 void destroy_table(TABLE *table)
180 {
181 my_free(table);
182 }
183 };
184
185 // Google Test recommends DeathTest suffix for classes used in death tests.
186 typedef TableCacheBasicTest TableCacheBasicDeathTest;
187 typedef TableCacheDoubleCacheTest TableCacheDoubleCacheDeathTest;
188
189 /*
190 Test initilization/destruction of Table_cache.
191 */
192
TEST_F(TableCacheBasicDeathTest,CacheCreateAndDestroy)193 TEST_F(TableCacheBasicDeathTest, CacheCreateAndDestroy)
194 {
195 Table_cache table_cache;
196
197 ASSERT_FALSE(table_cache.init());
198
199 // Cache should be empty after creation
200 EXPECT_EQ(0U, table_cache.cached_tables());
201
202 // Cache should be not locked after creation
203 #ifdef SAFE_MUTEX
204 MY_EXPECT_DEATH_IF_SUPPORTED(table_cache.assert_owner(),
205 ".*Assertion.*count > 0.*pthread_equal.*");
206 #endif
207 table_cache.destroy();
208 }
209
210
211 /*
212 Test locking for Table_cache object.
213 */
214
TEST_F(TableCacheBasicDeathTest,CacheLockAndUnlock)215 TEST_F(TableCacheBasicDeathTest, CacheLockAndUnlock)
216 {
217 Table_cache table_cache;
218
219 ASSERT_FALSE(table_cache.init());
220
221 #ifdef SAFE_MUTEX
222 // Cache should not be locked after creation
223 MY_EXPECT_DEATH_IF_SUPPORTED(table_cache.assert_owner(),
224 ".*Assertion.*count > 0.*pthread_equal.*");
225 #endif
226
227 // And get locked after we call its lock() method
228 table_cache.lock();
229 table_cache.assert_owner();
230
231 // And get unlocked after we call its unlock() method
232 table_cache.unlock();
233 #ifdef SAFE_MUTEX
234 MY_EXPECT_DEATH_IF_SUPPORTED(table_cache.assert_owner(),
235 ".*Assertion.*count > 0.*pthread_equal.*");
236 #endif
237
238 table_cache.destroy();
239 }
240
241
242 /*
243 Tests for the rest of methods of Table_cache need to use an
244 object controlled by the global instance of Table_cache_manager.
245 Let us start testing of Table_cache_manager with test for
246 its initialization/destruction. This test also covers well
247 Table_cache_manager::get_cache() method.
248 */
249
TEST_F(TableCacheBasicDeathTest,ManagerCreateAndDestroy)250 TEST_F(TableCacheBasicDeathTest, ManagerCreateAndDestroy)
251 {
252 // Request two instances of Table_cache
253 table_cache_instances= 2;
254
255 ASSERT_FALSE(table_cache_manager.init());
256
257 // All caches are empty after creation
258 EXPECT_EQ(0U, table_cache_manager.cached_tables());
259
260 // There should be two different caches in the manager
261 Table_cache *cache_1, *cache_2, *cache_3;
262 cache_1= table_cache_manager.get_cache(get_thd(0));
263 cache_2= table_cache_manager.get_cache(get_thd(1));
264 cache_3= table_cache_manager.get_cache(get_thd(2));
265 EXPECT_TRUE(cache_1 != cache_2);
266 // And not three !
267 EXPECT_TRUE(cache_3 == cache_1);
268
269 // Both caches should be empty
270 EXPECT_EQ(0U, cache_1->cached_tables());
271 EXPECT_EQ(0U, cache_2->cached_tables());
272
273 // And not locked
274 #ifdef SAFE_MUTEX
275 MY_EXPECT_DEATH_IF_SUPPORTED(cache_1->assert_owner(),
276 ".*Assertion.*count > 0.*pthread_equal.*");
277 MY_EXPECT_DEATH_IF_SUPPORTED(cache_2->assert_owner(),
278 ".*Assertion.*count > 0.*pthread_equal.*");
279 #endif
280
281 table_cache_manager.destroy();
282 }
283
284
285 /*
286 Test addition and removal of TABLE objects to/from the table cache.
287 */
288
TEST_F(TableCacheSingleCacheTest,CacheAddAndRemove)289 TEST_F(TableCacheSingleCacheTest, CacheAddAndRemove)
290 {
291 THD *thd= get_thd(0);
292
293 Mock_share share_1("share_1");
294 TABLE *table_1= share_1.create_table(thd);
295
296 Table_cache *table_cache= table_cache_manager.get_cache(thd);
297 table_cache->lock();
298 EXPECT_FALSE(table_cache->add_used_table(thd, table_1));
299
300 // There should be one TABLE in the cache after we have added table_1.
301 EXPECT_EQ(1U, table_cache->cached_tables());
302
303 // There should be no unused TABLE objects for the same table in the
304 // cache. OTOH it should contain info about table share of table_1.
305 my_hash_value_type hash_value= my_calc_hash(&table_def_cache,
306 (uchar*)share_1.table_cache_key.str,
307 share_1.table_cache_key.length);
308 TABLE *table_2;
309 TABLE_SHARE *share_2;
310 table_2= table_cache->get_table(thd, hash_value,
311 share_1.table_cache_key.str,
312 share_1.table_cache_key.length,
313 &share_2);
314 EXPECT_TRUE(table_2 == NULL);
315 EXPECT_TRUE(share_2 == &share_1);
316
317 // Table_cache_iterator should be able to find only one TABLE instance
318 // in all caches. And this instance should be table_1.
319 Table_cache_iterator it(&share_1);
320 EXPECT_TRUE(it++ == table_1);
321 EXPECT_TRUE(it++ == NULL);
322
323 // We must be able to release TABLE into table cache and reuse it after
324 // this.
325 table_cache->release_table(thd, table_1);
326 table_2= table_cache->get_table(thd, hash_value,
327 share_1.table_cache_key.str,
328 share_1.table_cache_key.length,
329 &share_2);
330 EXPECT_TRUE(table_2 == table_1);
331 EXPECT_TRUE(share_2 == &share_1);
332
333 table_cache->remove_table(table_1);
334
335 // Once TABLE is removed from the cache the latter should become empty.
336 EXPECT_EQ(0U, table_cache->cached_tables());
337
338 table_2= table_cache->get_table(thd, hash_value,
339 share_1.table_cache_key.str,
340 share_1.table_cache_key.length,
341 &share_2);
342 EXPECT_TRUE(table_2 == NULL);
343 EXPECT_TRUE(share_2 == NULL);
344
345 it.rewind();
346 EXPECT_TRUE(it++ == NULL);
347
348 // Also it should be possible to remove unused TABLE from the cache
349 // Add TABLE instance and mark it as unused
350 EXPECT_FALSE(table_cache->add_used_table(thd, table_1));
351 table_cache->release_table(thd, table_1);
352
353 table_cache->remove_table(table_1);
354
355 // Once TABLE is removed from cache the latter should become empty.
356 EXPECT_EQ(0U, table_cache->cached_tables());
357
358 table_2= table_cache->get_table(thd, hash_value,
359 share_1.table_cache_key.str,
360 share_1.table_cache_key.length,
361 &share_2);
362 EXPECT_TRUE(table_2 == NULL);
363 EXPECT_TRUE(share_2 == NULL);
364
365 table_cache->unlock();
366
367 share_1.destroy_table(table_1);
368 }
369
370
371 /*
372 Now let us test how Table_cache handles overflows.
373 */
374
TEST_F(TableCacheSingleCacheTest,CacheOverflow)375 TEST_F(TableCacheSingleCacheTest, CacheOverflow)
376 {
377 THD *thd= get_thd(0);
378
379 // Set cache size low so it will overflow quickly.
380 table_cache_size_per_instance= 2;
381
382 Mock_share share_1("share_1");
383 Mock_share share_2("share_2");
384 TABLE *table_1= share_1.create_table(thd);
385 TABLE *table_2= share_1.create_table(thd);
386 TABLE *table_3= share_2.create_table(thd);
387
388 Table_cache *table_cache= table_cache_manager.get_cache(thd);
389
390 table_cache->lock();
391 table_cache->add_used_table(thd, table_1);
392 table_cache->add_used_table(thd, table_2);
393
394 // There should be two TABLE instances in the cache.
395 EXPECT_EQ(2U, table_cache->cached_tables());
396
397 table_cache->release_table(thd, table_1);
398 table_cache->release_table(thd, table_2);
399
400 // Still there should be two TABLE instances in the cache.
401 EXPECT_EQ(2U, table_cache->cached_tables());
402
403 table_cache->add_used_table(thd, table_3);
404
405 // One TABLE was added and one expelled (table_1), so still two TABLE objects.
406 EXPECT_EQ(2U, table_cache->cached_tables());
407
408 // Old value of table_1 points to garbage thanks to expelling
409 table_1= share_1.create_table(thd);
410 table_cache->add_used_table(thd, table_1);
411
412 // Still two TABLE instances (table_2 was expelled).
413 EXPECT_EQ(2U, table_cache->cached_tables());
414
415 // Old value of table_2 points to garbage thanks to expelling
416 table_2= share_1.create_table(thd);
417 table_cache->add_used_table(thd, table_2);
418
419 /*
420 Now we should have three TABLE instances in cache since all
421 of them are used.
422 */
423 EXPECT_EQ(3U, table_cache->cached_tables());
424
425 table_cache->release_table(thd, table_2);
426
427 // The first table that gets released is expelled.
428 EXPECT_EQ(2U, table_cache->cached_tables());
429
430 table_cache->remove_table(table_1);
431 table_cache->remove_table(table_3);
432
433 // Cache should be empty after that
434 EXPECT_EQ(0U, table_cache->cached_tables());
435
436 table_cache->unlock();
437
438 share_1.destroy_table(table_1);
439 share_1.destroy_table(table_3);
440 }
441
442
TEST_F(TableCacheSingleCacheTest,CacheGetAndRelease)443 TEST_F(TableCacheSingleCacheTest, CacheGetAndRelease)
444 {
445 THD *thd= get_thd(0);
446
447 Table_cache *table_cache= table_cache_manager.get_cache(thd);
448
449 table_cache->lock();
450
451 TABLE *table_1, *table_2, *table_3;
452 Mock_share share_1("share_1"), share_0("share_0");
453 TABLE_SHARE *share_2;
454
455 // There should be no TABLE in cache, nor information about share.
456 my_hash_value_type hash_value_1= my_calc_hash(&table_def_cache,
457 (uchar*)share_1.table_cache_key.str,
458 share_1.table_cache_key.length);
459 table_1= table_cache->get_table(thd, hash_value_1,
460 share_1.table_cache_key.str,
461 share_1.table_cache_key.length,
462 &share_2);
463 EXPECT_TRUE(table_1 == NULL);
464 EXPECT_TRUE(share_2 == NULL);
465
466 table_1= share_1.create_table(thd);
467 table_cache->add_used_table(thd, table_1);
468
469 // There should be no unused TABLE in cache, but there should be
470 // information about the share.
471 table_2= table_cache->get_table(thd, hash_value_1,
472 share_1.table_cache_key.str,
473 share_1.table_cache_key.length,
474 &share_2);
475 EXPECT_TRUE(table_2 == NULL);
476 EXPECT_TRUE(share_2 == &share_1);
477
478 // There should be even no information about the share for which
479 // TABLE was not added to cache.
480 my_hash_value_type hash_value_0= my_calc_hash(&table_def_cache,
481 (uchar*)share_0.table_cache_key.str,
482 share_0.table_cache_key.length);
483 table_2= table_cache->get_table(thd, hash_value_0,
484 share_0.table_cache_key.str,
485 share_0.table_cache_key.length,
486 &share_2);
487 EXPECT_TRUE(table_2 == NULL);
488 EXPECT_TRUE(share_2 == NULL);
489
490 table_2= share_1.create_table(thd);
491 table_cache->add_used_table(thd, table_2);
492
493 // Still there should be no unused TABLE in cache, but there should
494 // be information about the share.
495 table_3= table_cache->get_table(thd, hash_value_1,
496 share_1.table_cache_key.str,
497 share_1.table_cache_key.length,
498 &share_2);
499 EXPECT_TRUE(table_3 == NULL);
500 EXPECT_TRUE(share_2 == &share_1);
501
502 table_cache->release_table(thd, table_1);
503
504 // After releasing one of TABLE objects it should be possible to get
505 // unused TABLE from cache.
506 table_3= table_cache->get_table(thd, hash_value_1,
507 share_1.table_cache_key.str,
508 share_1.table_cache_key.length,
509 &share_2);
510 EXPECT_TRUE(table_3 == table_1);
511 EXPECT_TRUE(share_2 == &share_1);
512
513 // But only once!
514 table_3= table_cache->get_table(thd, hash_value_1,
515 share_1.table_cache_key.str,
516 share_1.table_cache_key.length,
517 &share_2);
518 EXPECT_TRUE(table_3 == NULL);
519 EXPECT_TRUE(share_2 == &share_1);
520
521 // After releasing of both TABLE objects it should be possible to
522 // get two unused TABLE objects from cache (for 'share_1').
523 // There should be nothing for 'share_0'.
524 table_cache->release_table(thd, table_1);
525 table_cache->release_table(thd, table_2);
526
527 table_3= table_cache->get_table(thd, hash_value_0,
528 share_0.table_cache_key.str,
529 share_0.table_cache_key.length,
530 &share_2);
531 EXPECT_TRUE(table_3 == NULL);
532 EXPECT_TRUE(share_2 == NULL);
533
534
535 table_3= table_cache->get_table(thd, hash_value_1,
536 share_1.table_cache_key.str,
537 share_1.table_cache_key.length,
538 &share_2);
539 EXPECT_TRUE(table_3 != NULL);
540 EXPECT_TRUE(share_2 == &share_1);
541 table_3= table_cache->get_table(thd, hash_value_1,
542 share_1.table_cache_key.str,
543 share_1.table_cache_key.length,
544 &share_2);
545 EXPECT_TRUE(table_3 != NULL);
546 EXPECT_TRUE(share_2 == &share_1);
547 table_3= table_cache->get_table(thd, hash_value_1,
548 share_1.table_cache_key.str,
549 share_1.table_cache_key.length,
550 &share_2);
551 EXPECT_TRUE(table_3 == NULL);
552 EXPECT_TRUE(share_2 == &share_1);
553
554 // Clean-up
555 table_cache->remove_table(table_1);
556 table_cache->remove_table(table_2);
557
558 share_1.destroy_table(table_1);
559 share_1.destroy_table(table_2);
560
561 table_cache->unlock();
562 }
563
564
565 /*
566 Test for Table_cache_manager/Table_cache::free_all_unused_tables().
567 */
568
TEST_F(TableCacheDoubleCacheTest,ManagerFreeAllUnused)569 TEST_F(TableCacheDoubleCacheTest, ManagerFreeAllUnused)
570 {
571 THD *thd_1= get_thd(0);
572 THD *thd_2= get_thd(1);
573
574 Table_cache *table_cache_1= table_cache_manager.get_cache(thd_1);
575 Table_cache *table_cache_2= table_cache_manager.get_cache(thd_2);
576
577 // There should be no TABLE instances in all cachea.
578 EXPECT_EQ(0U, table_cache_manager.cached_tables());
579
580 Mock_share share_1("share_1");
581 Mock_share share_2("share_2");
582 Mock_share share_3("share_2");
583 TABLE *table_1= share_1.create_table(thd_1);
584 TABLE *table_2= share_1.create_table(thd_1);
585 TABLE *table_3= share_2.create_table(thd_1);
586 TABLE *table_4= share_2.create_table(thd_1);
587 TABLE *table_5= share_1.create_table(thd_2);
588 TABLE *table_6= share_3.create_table(thd_2);
589
590 table_cache_manager.lock_all_and_tdc();
591
592 table_cache_1->add_used_table(thd_1, table_1);
593 table_cache_1->add_used_table(thd_1, table_2);
594 table_cache_1->add_used_table(thd_1, table_3);
595 table_cache_1->add_used_table(thd_1, table_4);
596 table_cache_2->add_used_table(thd_2, table_5);
597 table_cache_2->add_used_table(thd_2, table_6);
598
599 EXPECT_EQ(4U, table_cache_1->cached_tables());
600 EXPECT_EQ(2U, table_cache_2->cached_tables());
601 EXPECT_EQ(6U, table_cache_manager.cached_tables());
602
603 table_cache_manager.free_all_unused_tables();
604
605 // All TABLE instances should stay around in caches as
606 // all of them are used.
607 EXPECT_EQ(4U, table_cache_1->cached_tables());
608 EXPECT_EQ(2U, table_cache_2->cached_tables());
609 EXPECT_EQ(6U, table_cache_manager.cached_tables());
610
611 table_cache_1->release_table(thd_1, table_1);
612
613 table_cache_manager.free_all_unused_tables();
614
615 // One table should be freed. So there should be 3 + 2 TABLE instances.
616 EXPECT_EQ(3U, table_cache_1->cached_tables());
617 EXPECT_EQ(2U, table_cache_2->cached_tables());
618 EXPECT_EQ(5U, table_cache_manager.cached_tables());
619
620 table_cache_1->release_table(thd_1, table_2);
621 table_cache_1->release_table(thd_1, table_3);
622 table_cache_2->release_table(thd_2, table_5);
623
624 table_cache_manager.free_all_unused_tables();
625
626 // Now there should be 1 + 1 used TABLE instances left.
627 EXPECT_EQ(1U, table_cache_1->cached_tables());
628 EXPECT_EQ(1U, table_cache_2->cached_tables());
629 EXPECT_EQ(2U, table_cache_manager.cached_tables());
630
631 table_cache_1->release_table(thd_1, table_4);
632
633 table_cache_manager.free_all_unused_tables();
634
635 // There should be 0 + 1 TABLE instances around.
636 EXPECT_EQ(0U, table_cache_1->cached_tables());
637 EXPECT_EQ(1U, table_cache_2->cached_tables());
638 EXPECT_EQ(1U, table_cache_manager.cached_tables());
639
640 table_cache_2->release_table(thd_2, table_6);
641
642 table_cache_manager.free_all_unused_tables();
643
644 // All caches should become empty.
645 EXPECT_EQ(0U, table_cache_1->cached_tables());
646 EXPECT_EQ(0U, table_cache_2->cached_tables());
647 EXPECT_EQ(0U, table_cache_manager.cached_tables());
648
649 table_cache_manager.unlock_all_and_tdc();
650 }
651
652
653 /*
654 Test for Table_cache_manager/Table_cache::cached_tables().
655 */
656
TEST_F(TableCacheDoubleCacheTest,ManagerCachedTables)657 TEST_F(TableCacheDoubleCacheTest, ManagerCachedTables)
658 {
659 THD *thd_1= get_thd(0);
660 THD *thd_2= get_thd(1);
661
662 Table_cache *table_cache_1= table_cache_manager.get_cache(thd_1);
663 Table_cache *table_cache_2= table_cache_manager.get_cache(thd_2);
664
665 // There should be no TABLE instances in all cachea.
666 EXPECT_EQ(0U, table_cache_1->cached_tables());
667 EXPECT_EQ(0U, table_cache_2->cached_tables());
668 EXPECT_EQ(0U, table_cache_manager.cached_tables());
669
670 Mock_share share_1("share_1");
671 Mock_share share_2("share_2");
672 TABLE *table_1= share_1.create_table(thd_1);
673 TABLE *table_2= share_1.create_table(thd_1);
674 TABLE *table_3= share_2.create_table(thd_1);
675 TABLE *table_4= share_1.create_table(thd_2);
676 TABLE *table_5= share_2.create_table(thd_2);
677
678 table_cache_manager.lock_all_and_tdc();
679
680 table_cache_1->add_used_table(thd_1, table_1);
681 table_cache_1->add_used_table(thd_1, table_2);
682 table_cache_1->add_used_table(thd_1, table_3);
683
684 // There should be 3 + 0 TABLE objects in cache
685 EXPECT_EQ(3U, table_cache_1->cached_tables());
686 EXPECT_EQ(0U, table_cache_2->cached_tables());
687 EXPECT_EQ(3U, table_cache_manager.cached_tables());
688
689 table_cache_2->add_used_table(thd_2, table_4);
690 table_cache_2->add_used_table(thd_2, table_5);
691
692 // There should be 3 + 2 TABLE objects in cache
693 EXPECT_EQ(3U, table_cache_1->cached_tables());
694 EXPECT_EQ(2U, table_cache_2->cached_tables());
695 EXPECT_EQ(5U, table_cache_manager.cached_tables());
696
697 table_cache_1->release_table(thd_1, table_1);
698 table_cache_2->release_table(thd_2, table_4);
699
700 // There should be the same number of TABLE objects - 3 + 2
701 EXPECT_EQ(3U, table_cache_1->cached_tables());
702 EXPECT_EQ(2U, table_cache_2->cached_tables());
703 EXPECT_EQ(5U, table_cache_manager.cached_tables());
704
705 table_cache_2->remove_table(table_5);
706
707 // There should be 3 + 1 TABLE objects in cache
708 EXPECT_EQ(3U, table_cache_1->cached_tables());
709 EXPECT_EQ(1U, table_cache_2->cached_tables());
710 EXPECT_EQ(4U, table_cache_manager.cached_tables());
711
712 table_cache_1->remove_table(table_1);
713 table_cache_2->remove_table(table_4);
714
715 // There should be 2 + 0 TABLE objects in cache
716 EXPECT_EQ(2U, table_cache_1->cached_tables());
717 EXPECT_EQ(0U, table_cache_2->cached_tables());
718 EXPECT_EQ(2U, table_cache_manager.cached_tables());
719
720 table_cache_1->remove_table(table_2);
721 table_cache_1->remove_table(table_3);
722
723 // Caches should be empty
724 EXPECT_EQ(0U, table_cache_1->cached_tables());
725 EXPECT_EQ(0U, table_cache_2->cached_tables());
726 EXPECT_EQ(0U, table_cache_manager.cached_tables());
727
728 table_cache_manager.unlock_all_and_tdc();
729
730 share_1.destroy_table(table_1);
731 share_1.destroy_table(table_2);
732 share_2.destroy_table(table_3);
733 share_1.destroy_table(table_4);
734 share_2.destroy_table(table_5);
735 }
736
737
738 /*
739 Coverage for lock and unlock methods of Table_cache_manager class.
740 */
741
TEST_F(TableCacheDoubleCacheDeathTest,ManagerLockAndUnlock)742 TEST_F(TableCacheDoubleCacheDeathTest, ManagerLockAndUnlock)
743 {
744 // Nor caches nor LOCK_open should not be locked after initialization
745 #ifdef SAFE_MUTEX
746 MY_EXPECT_DEATH_IF_SUPPORTED(table_cache_manager.assert_owner_all(),
747 ".*Assertion.*count > 0.*pthread_equal.*");
748 MY_EXPECT_DEATH_IF_SUPPORTED(table_cache_manager.assert_owner_all_and_tdc(),
749 ".*Assertion.*count > 0.*pthread_equal.*");
750 #endif
751
752 // And get locked after we call its lock_all_and_tdc() method.
753 table_cache_manager.lock_all_and_tdc();
754 table_cache_manager.assert_owner_all();
755 table_cache_manager.assert_owner_all_and_tdc();
756
757 // In addition to Table_cache_manager method we check this by
758 // calling Table_cache methods and asserting state of LOCK_open.
759 Table_cache *cache_1= table_cache_manager.get_cache(get_thd(0));
760 Table_cache *cache_2= table_cache_manager.get_cache(get_thd(1));
761
762 cache_1->assert_owner();
763 cache_2->assert_owner();
764 mysql_mutex_assert_owner(&LOCK_open);
765
766 // Locks should be unlocked after we call unlock method
767 table_cache_manager.unlock_all_and_tdc();
768
769 #ifdef SAFE_MUTEX
770 MY_EXPECT_DEATH_IF_SUPPORTED(table_cache_manager.assert_owner_all(),
771 ".*Assertion.*count > 0.*pthread_equal.*");
772 MY_EXPECT_DEATH_IF_SUPPORTED(table_cache_manager.assert_owner_all_and_tdc(),
773 ".*Assertion.*count > 0.*pthread_equal.*");
774 #endif
775 }
776
777
778 /*
779 Coverage for Table_cache_manager::free_table();
780 */
781
TEST_F(TableCacheDoubleCacheDeathTest,ManagerFreeTable)782 TEST_F(TableCacheDoubleCacheDeathTest, ManagerFreeTable)
783 {
784 THD *thd_1= get_thd(0);
785 THD *thd_2= get_thd(1);
786
787 Table_cache *table_cache_1= table_cache_manager.get_cache(thd_1);
788 Table_cache *table_cache_2= table_cache_manager.get_cache(thd_2);
789
790 Mock_share share_1("share_1");
791 Mock_share share_2("share_2");
792 TABLE *table_1= share_1.create_table(thd_1);
793 TABLE *table_2= share_1.create_table(thd_1);
794 TABLE *table_3= share_2.create_table(thd_1);
795 TABLE *table_4= share_1.create_table(thd_2);
796 TABLE *table_5= share_2.create_table(thd_2);
797
798 table_cache_manager.lock_all_and_tdc();
799
800 /*
801 Coverage for TDC_RT_REMOVE_ALL case.
802 */
803 table_cache_1->add_used_table(thd_1, table_1);
804 table_cache_1->add_used_table(thd_1, table_2);
805 table_cache_1->release_table(thd_1, table_2);
806 table_cache_1->add_used_table(thd_1, table_3);
807 table_cache_2->add_used_table(thd_2, table_4);
808 table_cache_2->add_used_table(thd_2, table_5);
809
810 EXPECT_EQ(5U, table_cache_manager.cached_tables());
811
812 // There should be assert failure since we are trying
813 // to free all tables for share_1, while some tables
814 // are in use.
815 #ifndef DBUG_OFF
816 MY_EXPECT_DEATH_IF_SUPPORTED(table_cache_manager.free_table(thd_1,
817 TDC_RT_REMOVE_ALL,
818 &share_1),
819 ".*Assertion.*is_empty.*");
820 #endif
821
822 table_cache_1->release_table(thd_1, table_1);
823 table_cache_2->release_table(thd_2, table_4);
824
825 // After all tables for share_1 marked as unused freeing
826 // all tables should succeed.
827 table_cache_manager.free_table(thd_1, TDC_RT_REMOVE_ALL, &share_1);
828
829 // We still should have 2 TABLE objects for share_2.
830 EXPECT_EQ(2U, table_cache_manager.cached_tables());
831
832 /*
833 Coverage for TDC_RT_REMOVE_NOT_OWN case.
834 */
835 table_1= share_1.create_table(thd_1);
836 table_2= share_1.create_table(thd_1);
837 table_4= share_1.create_table(thd_2);
838
839 table_cache_1->add_used_table(thd_1, table_1);
840 table_cache_1->add_used_table(thd_1, table_2);
841 table_cache_1->release_table(thd_1, table_2);
842 table_cache_2->add_used_table(thd_2, table_4);
843
844 EXPECT_EQ(5U, table_cache_manager.cached_tables());
845
846 // There should be assert failure since we are trying
847 // to free all not own TABLEs for share_1, while thd_2
848 // has a TABLE object for it in used
849 #ifndef DBUG_OFF
850 MY_EXPECT_DEATH_IF_SUPPORTED(table_cache_manager.free_table(thd_1,
851 TDC_RT_REMOVE_NOT_OWN,
852 &share_1),
853 ".*Assertion.*0.*");
854 #endif
855
856 table_cache_2->release_table(thd_2, table_4);
857
858 // After TABLE owned by thd_2 is marked as unused, the below
859 // call should succeed.
860 table_cache_manager.free_table(thd_1, TDC_RT_REMOVE_NOT_OWN, &share_1);
861
862 // We still have 1 TABLE object for share_1 in thd_1 and
863 // 2 TABLE objects for share_2.
864 EXPECT_EQ(3U, table_cache_manager.cached_tables());
865
866 /*
867 Coverage for TDC_RT_REMOVE_UNUSED case.
868 */
869 table_2= share_1.create_table(thd_1);
870 table_4= share_1.create_table(thd_2);
871
872 table_cache_1->add_used_table(thd_1, table_2);
873 table_cache_1->release_table(thd_1, table_2);
874 table_cache_2->add_used_table(thd_2, table_4);
875
876 EXPECT_EQ(5U, table_cache_manager.cached_tables());
877
878 table_cache_manager.free_table(thd_1, TDC_RT_REMOVE_UNUSED, &share_1);
879
880 // The above call should have been freed only 1 table.
881 EXPECT_EQ(4U, table_cache_manager.cached_tables());
882
883 // Mark all remaining TABLE objects for share_1 as unused
884 table_cache_1->release_table(thd_1, table_1);
885 table_cache_2->release_table(thd_2, table_4);
886
887 table_cache_manager.free_table(thd_1, TDC_RT_REMOVE_UNUSED, &share_1);
888
889 // The above call should free all unused TABLE objects for share_1.
890 // Therefore only 2 objects for share_2 should be remaining
891 EXPECT_EQ(2U, table_cache_manager.cached_tables());
892
893 // Clean-up.
894 table_cache_1->remove_table(table_3);
895 table_cache_2->remove_table(table_5);
896
897 share_2.destroy_table(table_3);
898 share_2.destroy_table(table_5);
899
900 table_cache_manager.unlock_all_and_tdc();
901 }
902
903
904 /*
905 Coverage for Table_cache_iterator
906 */
907
TEST_F(TableCacheDoubleCacheTest,Iterator)908 TEST_F(TableCacheDoubleCacheTest, Iterator)
909 {
910 THD *thd_1= get_thd(0);
911 THD *thd_2= get_thd(1);
912
913 table_cache_manager.lock_all_and_tdc();
914
915 Mock_share share_1("share_1");
916 Mock_share share_2("share_2");
917
918 // There is no TABLE objects for share_1 so the below iterator
919 // should not find anything.
920 Table_cache_iterator it(&share_1);
921 EXPECT_TRUE(it++ == NULL);
922 // Attempt to iterate behind the end should not give anything.
923 EXPECT_TRUE(it++ == NULL);
924
925 Table_cache *table_cache_1= table_cache_manager.get_cache(thd_1);
926 Table_cache *table_cache_2= table_cache_manager.get_cache(thd_2);
927 TABLE *table_1= share_1.create_table(thd_1);
928 TABLE *table_2= share_1.create_table(thd_1);
929 TABLE *table_3= share_2.create_table(thd_1);
930 TABLE *table_4= share_1.create_table(thd_2);
931 TABLE *table_5= share_2.create_table(thd_2);
932
933 table_cache_2->add_used_table(thd_2, table_4);
934
935 // Now the iterato should see table_4.
936 it.rewind();
937 TABLE *table_r1= it++;
938 EXPECT_TRUE(table_r1 == table_4);
939 // But only it.
940 EXPECT_TRUE(it++ == NULL);
941 EXPECT_TRUE(it++ == NULL);
942
943 table_cache_1->add_used_table(thd_1, table_1);
944
945 // Now we should see two tables:
946 it.rewind();
947 table_r1= it++;
948 EXPECT_TRUE(table_r1 != NULL);
949 TABLE *table_r2= it++;
950 EXPECT_TRUE(table_r2 != NULL);
951 EXPECT_TRUE(table_r1 != table_r2);
952 EXPECT_TRUE(it++ == NULL);
953 EXPECT_TRUE(it++ == NULL);
954
955 table_cache_1->add_used_table(thd_1, table_2);
956
957 // And now three !
958 it.rewind();
959 table_r1= it++;
960 EXPECT_TRUE(table_r1 != NULL);
961 table_r2= it++;
962 EXPECT_TRUE(table_r2 != NULL);
963 TABLE *table_r3= it++;
964 EXPECT_TRUE(table_r3 != NULL);
965 EXPECT_TRUE(table_r1 != table_r2 && table_r1 != table_r3 && table_r2 != table_r3);
966 EXPECT_TRUE(it++ == NULL);
967 EXPECT_TRUE(it++ == NULL);
968
969 table_cache_1->release_table(thd_1, table_1);
970
971 // We should be seeing only used TABLE objects, so two tables now
972 it.rewind();
973 table_r1= it++;
974 EXPECT_TRUE(table_r1 != NULL);
975 table_r2= it++;
976 EXPECT_TRUE(table_r2 != NULL);
977 EXPECT_TRUE(table_r1 != table_r2);
978 EXPECT_TRUE(it++ == NULL);
979 EXPECT_TRUE(it++ == NULL);
980
981 table_cache_1->add_used_table(thd_1, table_3);
982 table_cache_2->add_used_table(thd_2, table_5);
983
984 // We also should not be seeing TABLE objects for share_2
985 it.rewind();
986 table_r1= it++;
987 EXPECT_TRUE(table_r1 != NULL);
988 table_r2= it++;
989 EXPECT_TRUE(table_r2 != NULL);
990 EXPECT_TRUE(table_r1 != table_r2);
991 EXPECT_TRUE(it++ == NULL);
992 EXPECT_TRUE(it++ == NULL);
993
994 table_cache_1->remove_table(table_2);
995
996 // Now we should se only one used TABLE
997 it.rewind();
998 table_r1= it++;
999 EXPECT_TRUE(table_r1 == table_4);
1000 EXPECT_TRUE(it++ == NULL);
1001 EXPECT_TRUE(it++ == NULL);
1002
1003 table_cache_1->remove_table(table_4);
1004
1005 // And now no used TABLE objects for share_1 at all
1006 it.rewind();
1007 EXPECT_TRUE(it++ == NULL);
1008 EXPECT_TRUE(it++ == NULL);
1009
1010 table_cache_1->remove_table(table_1);
1011
1012 // Still the same
1013 it.rewind();
1014 EXPECT_TRUE(it++ == NULL);
1015 EXPECT_TRUE(it++ == NULL);
1016
1017 table_cache_1->remove_table(table_3);
1018 table_cache_2->remove_table(table_5);
1019
1020 // Cache is empty so iterator should not show any TABLE objects.
1021 it.rewind();
1022 EXPECT_TRUE(it++ == NULL);
1023 EXPECT_TRUE(it++ == NULL);
1024
1025 table_cache_manager.unlock_all_and_tdc();
1026
1027 share_1.destroy_table(table_1);
1028 share_1.destroy_table(table_2);
1029 share_2.destroy_table(table_3);
1030 share_1.destroy_table(table_4);
1031 share_2.destroy_table(table_5);
1032 }
1033
1034 }
1035