1 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
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
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /* open a heap-database */
24
25 #include "heapdef.h"
26 #include "my_sys.h"
27
28 /*
29 Open heap table based on HP_SHARE structure
30
31 NOTE
32 This doesn't register the table in the open table list.
33 */
34
heap_open_from_share(HP_SHARE * share,int mode)35 HP_INFO *heap_open_from_share(HP_SHARE *share, int mode)
36 {
37 HP_INFO *info;
38 DBUG_ENTER("heap_open_from_share");
39
40 if (!(info= (HP_INFO*) my_malloc(hp_key_memory_HP_INFO,
41 (uint) sizeof(HP_INFO) +
42 2 * share->max_key_length,
43 MYF(MY_ZEROFILL))))
44 {
45 DBUG_RETURN(0);
46 }
47 share->open_count++;
48 /*
49 Don't initialize THR_LOCK_DATA for internal temporary tables as it
50 is not used for them anyway (and THR_LOCK is not initialized for them
51 too).
52 */
53 if (share->open_list.data != NULL)
54 thr_lock_data_init(&share->lock, &info->lock, NULL);
55 info->s= share;
56 info->lastkey= (uchar*) (info + 1);
57 info->recbuf= (uchar*) (info->lastkey + share->max_key_length);
58 info->mode= mode;
59 info->current_record= (ulong) ~0L; /* No current record */
60 info->lastinx= info->errkey= -1;
61 #ifndef NDEBUG
62 info->opt_flag= READ_CHECK_USED; /* Check when changing */
63 #endif
64 DBUG_PRINT("exit",("heap: 0x%lx reclength: %d records_in_block: %d",
65 (long) info, share->reclength,
66 share->block.records_in_block));
67 DBUG_RETURN(info);
68 }
69
70
71 /*
72 Open heap table based on HP_SHARE structure and register it
73 */
74
heap_open_from_share_and_register(HP_SHARE * share,int mode)75 HP_INFO *heap_open_from_share_and_register(HP_SHARE *share, int mode)
76 {
77 HP_INFO *info;
78 DBUG_ENTER("heap_open_from_share_and_register");
79
80 mysql_mutex_lock(&THR_LOCK_heap);
81 if ((info= heap_open_from_share(share, mode)))
82 {
83 info->open_list.data= (void*) info;
84 heap_open_list= list_add(heap_open_list,&info->open_list);
85 /* Unpin the share, it is now pinned by the file. */
86 share->open_count--;
87 }
88 mysql_mutex_unlock(&THR_LOCK_heap);
89 DBUG_RETURN(info);
90 }
91
92
93 /**
94 Dereference a HEAP share and free it if it's not referenced.
95 We don't check open_count for internal tables since they
96 are always thread-local, i.e. referenced by a single thread.
97 */
heap_release_share(HP_SHARE * share,my_bool internal_table)98 void heap_release_share(HP_SHARE *share, my_bool internal_table)
99 {
100 /* Couldn't open table; Remove the newly created table */
101 if (internal_table)
102 hp_free(share);
103 else
104 {
105 mysql_mutex_lock(&THR_LOCK_heap);
106 if (--share->open_count == 0)
107 hp_free(share);
108 mysql_mutex_unlock(&THR_LOCK_heap);
109 }
110 }
111
112 /*
113 Open heap table based on name
114
115 NOTE
116 This register the table in the open table list. so that it can be
117 found by future heap_open() calls.
118 */
119
heap_open(const char * name,int mode)120 HP_INFO *heap_open(const char *name, int mode)
121 {
122 HP_INFO *info;
123 HP_SHARE *share;
124 DBUG_ENTER("heap_open");
125
126 mysql_mutex_lock(&THR_LOCK_heap);
127 if (!(share= hp_find_named_heap(name)))
128 {
129 set_my_errno(ENOENT);
130 mysql_mutex_unlock(&THR_LOCK_heap);
131 DBUG_RETURN(0);
132 }
133 if ((info= heap_open_from_share(share, mode)))
134 {
135 info->open_list.data= (void*) info;
136 heap_open_list= list_add(heap_open_list,&info->open_list);
137 }
138 mysql_mutex_unlock(&THR_LOCK_heap);
139 DBUG_RETURN(info);
140 }
141
142
143 /* map name to a heap-nr. If name isn't found return 0 */
144
hp_find_named_heap(const char * name)145 HP_SHARE *hp_find_named_heap(const char *name)
146 {
147 LIST *pos;
148 HP_SHARE *info;
149 DBUG_ENTER("heap_find");
150 DBUG_PRINT("enter",("name: %s",name));
151
152 for (pos= heap_share_list; pos; pos= pos->next)
153 {
154 info= (HP_SHARE*) pos->data;
155 if (!strcmp(name, info->name))
156 {
157 DBUG_PRINT("exit", ("Old heap_database: 0x%lx", (long) info));
158 DBUG_RETURN(info);
159 }
160 }
161 DBUG_RETURN((HP_SHARE *) 0);
162 }
163
164
165