MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tsman.hpp
1 /*
2  Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #ifndef TSMAN_H
19 #define TSMAN_H
20 
21 #include <SimulatedBlock.hpp>
22 
23 #include <SLList.hpp>
24 #include <DLList.hpp>
25 #include <NodeBitmask.hpp>
26 #include <signaldata/GetTabInfo.hpp>
27 #include <SafeMutex.hpp>
28 
29 #include "lgman.hpp"
30 #include "pgman.hpp"
31 
32 class Tsman : public SimulatedBlock
33 {
34 public:
36  virtual ~Tsman();
37  BLOCK_DEFINES(Tsman);
38 
39 protected:
40 
41  void execSTTOR(Signal* signal);
42  void sendSTTORRY(Signal*);
43  void execREAD_CONFIG_REQ(Signal* signal);
44  void execDUMP_STATE_ORD(Signal* signal);
45  void execCONTINUEB(Signal* signal);
46  void execNODE_FAILREP(Signal* signal);
47 
48  void execCREATE_FILE_IMPL_REQ(Signal* signal);
49  void execCREATE_FILEGROUP_IMPL_REQ(Signal* signal);
50  void execDROP_FILE_IMPL_REQ(Signal* signal);
51  void execDROP_FILEGROUP_IMPL_REQ(Signal* signal);
52 
53  void execSTART_RECREQ(Signal*);
54 
55  void execFSWRITEREQ(Signal*);
56  void execFSOPENREF(Signal*);
57  void execFSOPENCONF(Signal*);
58  void execFSREADREF(Signal*);
59  void execFSREADCONF(Signal*);
60 
61  void execFSCLOSEREF(Signal*);
62  void execFSCLOSECONF(Signal*);
63 
66 
67  void execALLOC_PAGE_REQ(Signal* signal);
68 
69  void execLCP_FRAG_ORD(Signal*);
70  void execEND_LCP_REQ(Signal*);
71  void end_lcp(Signal*, Uint32 tablespace, Uint32 list, Uint32 file);
72 
73  void execGET_TABINFOREQ(Signal*);
74 
75  void sendGET_TABINFOREF(Signal* signal,
76  GetTabInfoReq * req,
77  GetTabInfoRef::ErrorCode errorCode);
78 
79 public:
80  struct Datafile
81  {
82  Datafile(){}
83  Datafile(const struct CreateFileImplReq*);
84 
91  Uint32 m_magic;
92  Uint32 m_file_no;
93  Uint32 m_file_id; // Used when talking to DICT
94  Uint32 m_fd; // NDBFS
95 
96  Uint32 m_tablespace_ptr_i;
97  Uint32 m_extent_size;
98  Uint16 m_state;
99  Uint16 m_ref_count;
100 
101  enum FileState
102  {
103  FS_CREATING = 0x1,
104  FS_ONLINE = 0x2,
105  FS_DROPPING = 0x4
106  };
107 
108  union {
109  struct {
110  Uint32 m_first_free_extent;
111  Uint32 m_lcp_free_extent_head; // extents freed but not LCP
112  Uint32 m_lcp_free_extent_tail;
113  Uint32 m_offset_data_pages; // 1(zero) + extent header pages
114  Uint32 m_data_pages;
115  Uint32 m_used_extent_cnt;
116  Uint32 m_extent_headers_per_extent_page;
117  } m_online;
118  struct {
119  Uint32 m_senderData;
120  Uint32 m_senderRef;
121  Uint32 m_data_pages;
122  Uint32 m_extent_pages;
123  Uint32 m_requestInfo;
124  union {
125  Uint32 m_page_ptr_i;
126  Uint32 m_loading_extent_page;
127  };
128  } m_create;
129  };
130 
131  Uint32 nextHash;
132  Uint32 prevHash;
133  Uint32 nextList;
134  union {
135  Uint32 prevList;
136  Uint32 nextPool;
137  };
138 
139  Uint32 hashValue() const {
140  return m_file_no;
141  }
142  bool equal(const Datafile& rec) const {
143  return m_file_no == rec.m_file_no;
144  }
145  };
146 
147  typedef RecordPool<Datafile, RWPool> Datafile_pool;
148  typedef DLListImpl<Datafile_pool, Datafile> Datafile_list;
149  typedef LocalDLListImpl<Datafile_pool, Datafile> Local_datafile_list;
150  typedef DLHashTableImpl<Datafile_pool, Datafile> Datafile_hash;
151 
152  struct Tablespace
153  {
154  Tablespace(){}
155  Tablespace(Tsman*, const struct CreateFilegroupImplReq*);
156 
157  Uint32 m_magic;
158  union {
159  Uint32 key;
160  Uint32 m_tablespace_id;
161  };
162  Uint32 m_version;
163  Uint16 m_state;
164  Uint16 m_ref_count; // Can't release when m_ref_count > 0
165 
166  enum TablespaceState
167  {
168  TS_CREATING = 0x1,
169  TS_ONLINE = 0x2,
170  TS_DROPPING = 0x4
171  };
172 
173  Uint32 m_extent_size; // In pages
174  Datafile_list::Head m_free_files; // Files w/ free space
175  Tsman* m_tsman;
176  Uint32 m_logfile_group_id;
177 
178  Datafile_list::Head m_full_files; // Files wo/ free space
179  Datafile_list::Head m_meta_files; // Files being created/dropped
180 
181  Uint32 nextHash;
182  Uint32 prevHash;
183  Uint32 nextList;
184  union {
185  Uint32 prevList;
186  Uint32 nextPool;
187  };
188 
189  Uint32 hashValue() const {
190  return key;
191  }
192  bool equal(const Tablespace& rec) const {
193  return key == rec.key;
194  }
195  };
196 
201 
202 private:
203  friend class Tablespace_client;
204  Datafile_pool m_file_pool;
205  Tablespace_pool m_tablespace_pool;
206 
207  bool m_lcp_ongoing;
208  Datafile_hash m_file_hash;
209  Tablespace_list m_tablespace_list;
210  Tablespace_hash m_tablespace_hash;
211  SimulatedBlock * m_pgman;
212  Lgman * m_lgman;
213  SimulatedBlock * m_tup;
214 
215  SafeMutex m_client_mutex;
216  void client_lock(BlockNumber block, int line);
217  void client_unlock(BlockNumber block, int line);
218 
220  SectionHandle* handle);
221  void load_extent_pages(Signal* signal, Ptr<Datafile> ptr);
222  void load_extent_page_callback(Signal*, Uint32, Uint32);
223  void create_file_ref(Signal*, Ptr<Tablespace>, Ptr<Datafile>,
224  Uint32,Uint32,Uint32);
225  int update_page_free_bits(Signal*, Local_key*, unsigned committed_bits);
226 
227  int get_page_free_bits(Signal*, Local_key*, unsigned*, unsigned*);
228  int unmap_page(Signal*, Local_key*, unsigned uncommitted_bits);
229  int restart_undo_page_free_bits(Signal*, Uint32, Uint32, Local_key*,
230  unsigned committed_bits);
231 
232  int alloc_extent(Signal* signal, Uint32 tablespace, Local_key* key);
233  int alloc_page_from_extent(Signal*, Uint32, Local_key*, Uint32 bits);
234 
235  void scan_tablespace(Signal*, Uint32 ptrI);
236  void scan_datafile(Signal*, Uint32, Uint32);
237  void scan_extent_headers(Signal*, Ptr<Datafile>);
238 
239  bool find_file_by_id(Ptr<Datafile>&, Datafile_list::Head&, Uint32 id);
240  void create_file_abort(Signal* signal, Ptr<Datafile>);
241 
242  void release_extent_pages(Signal* signal, Ptr<Datafile> ptr);
243  void release_extent_pages_callback(Signal*, Uint32, Uint32);
244 
245  struct req
246  {
247  Uint32 m_extent_pages;
248  Uint32 m_extent_size;
249  Uint32 m_extent_no; // on extent page
250  Uint32 m_extent_page_no;
251  };
252 
253  struct req lookup_extent(Uint32 page_no, const Datafile*) const;
254  Uint32 calc_page_no_in_extent(Uint32 page_no, const struct req* val) const;
255 };
256 
257 inline
258 Tsman::req
259 Tsman::lookup_extent(Uint32 page_no, const Datafile * filePtrP) const
260 {
261  struct req val;
262  val.m_extent_size = filePtrP->m_extent_size;
263  val.m_extent_pages = filePtrP->m_online.m_offset_data_pages;
264  Uint32 per_page = filePtrP->m_online.m_extent_headers_per_extent_page;
265 
266  Uint32 extent =
267  (page_no - val.m_extent_pages) / val.m_extent_size + per_page;
268 
269  val.m_extent_page_no = extent / per_page;
270  val.m_extent_no = extent % per_page;
271  return val;
272 }
273 
274 inline
275 Uint32
276 Tsman::calc_page_no_in_extent(Uint32 page_no, const Tsman::req* val) const
277 {
278  return (page_no - val->m_extent_pages) % val->m_extent_size;
279 }
280 
282 {
283 public:
284  Uint32 m_block;
285  Tsman * m_tsman;
286  Signal* m_signal;
287  Uint32 m_table_id;
288  Uint32 m_fragment_id;
289  Uint32 m_tablespace_id;
290  bool m_lock;
291  DEBUG_OUT_DEFINES(TSMAN);
292 
293 public:
295  Uint32 table, Uint32 fragment, Uint32 tablespaceId,
296  bool lock = true) {
297  Uint32 bno = block->number();
298  Uint32 ino = block->instance();
299  m_block= numberToBlock(bno, ino);
300  m_tsman= tsman;
301  m_signal= signal;
302  m_table_id= table;
303  m_fragment_id= fragment;
304  m_tablespace_id= tablespaceId;
305  m_lock = lock;
306 
307  D("client ctor " << bno << "/" << ino
308  << V(m_table_id) << V(m_fragment_id) << V(m_tablespace_id));
309  if (m_lock)
310  m_tsman->client_lock(m_block, 0);
311  }
312 
313  Tablespace_client(Signal* signal, Tsman* tsman, Local_key* key);//undef
314 
315  ~Tablespace_client() {
316 #ifdef VM_TRACE
317  Uint32 bno = blockToMain(m_block);
318  Uint32 ino = blockToInstance(m_block);
319 #endif
320  D("client dtor " << bno << "/" << ino);
321  if (m_lock)
322  m_tsman->client_unlock(m_block, 0);
323  }
324 
329  int alloc_extent(Local_key* key);
330 
349  int alloc_page_from_extent(Local_key* key, unsigned bits);
350 
354  int free_extent(Local_key* key, Uint64 lsn);
355 
359  int update_page_free_bits(Local_key*, unsigned bits);
360 
365  unsigned* uncommitted, unsigned* committed);
366 
370  int unmap_page(Local_key*, Uint32 bits);
371 
375  int restart_undo_page_free_bits(Local_key*, unsigned bits);
376 
386 
390  int update_lsn(Local_key* key, Uint64 lsn);
391 };
392 
393 #include <signaldata/Extent.hpp>
394 
395 inline
396 int
398 {
399  AllocExtentReq* req = (AllocExtentReq*)m_signal->theData;
400  req->request.table_id = m_table_id;
401  req->request.fragment_id = m_fragment_id;
402  req->request.tablespace_id = m_tablespace_id;
403  m_tsman->execALLOC_EXTENT_REQ(m_signal);
404 
405  if(req->reply.errorCode == 0){
406  * key = req->reply.page_id;
407  D("alloc_extent" << V(*key) << V(req->reply.page_count));
408  return req->reply.page_count;
409  } else {
410  return -(int)req->reply.errorCode;
411  }
412 }
413 
414 inline
415 int
417 {
418  AllocPageReq* req = (AllocPageReq*)m_signal->theData;
419  req->key= *key;
420  req->bits= bits;
421  req->request.table_id = m_table_id;
422  req->request.fragment_id = m_fragment_id;
423  req->request.tablespace_id = m_tablespace_id;
424  m_tsman->execALLOC_PAGE_REQ(m_signal);
425 
426  if(req->reply.errorCode == 0){
427  *key = req->key;
428  D("alloc_page_from_extent" << V(*key) << V(bits) << V(req->bits));
429  return req->bits;
430  } else {
431  return -(int)req->reply.errorCode;
432  }
433 }
434 
435 inline
436 int
438 {
439  FreeExtentReq* req = (FreeExtentReq*)m_signal->theData;
440  req->request.key = *key;
441  req->request.table_id = m_table_id;
442  req->request.tablespace_id = m_tablespace_id;
443  req->request.lsn_hi = (Uint32)(lsn >> 32);
444  req->request.lsn_lo = (Uint32)(lsn & 0xFFFFFFFF);
445  m_tsman->execFREE_EXTENT_REQ(m_signal);
446 
447  if(req->reply.errorCode == 0){
448  D("free_extent" << V(*key) << V(lsn));
449  return 0;
450  } else {
451  return -(int)req->reply.errorCode;
452  }
453 }
454 
455 inline
456 int
458  unsigned committed_bits)
459 {
460  D("update_page_free_bits" << V(*key) << V(committed_bits));
461  return m_tsman->update_page_free_bits(m_signal, key, committed_bits);
462 }
463 
464 inline
465 int
467  unsigned* uncommited,
468  unsigned* commited)
469 {
470  return m_tsman->get_page_free_bits(m_signal, key, uncommited, commited);
471 }
472 
473 inline
474 int
475 Tablespace_client::unmap_page(Local_key *key, unsigned uncommitted_bits)
476 {
477  return m_tsman->unmap_page(m_signal, key, uncommitted_bits);
478 }
479 
480 inline
481 int
483  unsigned committed_bits)
484 {
485  return m_tsman->restart_undo_page_free_bits(m_signal,
486  m_table_id,
487  m_fragment_id,
488  key,
489  committed_bits);
490 }
491 
492 #endif