MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
lgman.hpp
1 /*
2  Copyright (C) 2005-2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 #ifndef LGMAN_H
20 #define LGMAN_H
21 
22 #include <SimulatedBlock.hpp>
23 
24 #include <SLList.hpp>
25 #include <DLList.hpp>
26 #include <DLFifoList.hpp>
27 #include <KeyTable.hpp>
28 #include <DLHashTable.hpp>
29 #include <NodeBitmask.hpp>
30 #include "diskpage.hpp"
31 #include <signaldata/GetTabInfo.hpp>
32 
33 #include <WOPool.hpp>
34 #include <SLFifoList.hpp>
35 #include <SafeMutex.hpp>
36 
37 class Lgman : public SimulatedBlock
38 {
39 public:
40  Lgman(Block_context& ctx);
41  virtual ~Lgman();
42  BLOCK_DEFINES(Lgman);
43 
44 protected:
45 
46  void execSTTOR(Signal* signal);
47  void sendSTTORRY(Signal*);
48  void execREAD_CONFIG_REQ(Signal* signal);
49  void execDUMP_STATE_ORD(Signal* signal);
50  void execDBINFO_SCANREQ(Signal* signal);
51  void execCONTINUEB(Signal* signal);
52  void execNODE_FAILREP(Signal* signal);
53 
54  void execCREATE_FILE_IMPL_REQ(Signal* signal);
55  void execCREATE_FILEGROUP_IMPL_REQ(Signal* signal);
56  void execDROP_FILE_IMPL_REQ(Signal* signal);
57  void execDROP_FILEGROUP_IMPL_REQ(Signal* signal);
58 
59  void execFSWRITEREQ(Signal*);
60  void execFSWRITEREF(Signal*);
61  void execFSWRITECONF(Signal*);
62 
63  void execFSOPENREF(Signal*);
64  void execFSOPENCONF(Signal*);
65 
66  void execFSCLOSEREF(Signal*);
67  void execFSCLOSECONF(Signal*);
68 
69  void execFSREADREF(Signal*);
70  void execFSREADCONF(Signal*);
71 
72  void execLCP_FRAG_ORD(Signal*);
73  void execEND_LCP_REQ(Signal*);
75 
76  void execSTART_RECREQ(Signal*);
77  void execEND_LCP_CONF(Signal*);
78 
79  void execGET_TABINFOREQ(Signal*);
80 
81  void sendGET_TABINFOREF(Signal* signal,
82  GetTabInfoReq * req,
83  GetTabInfoRef::ErrorCode errorCode);
84 
85  void exec_lcp_frag_ord(Signal*, SimulatedBlock* client_block);
86 
87 public:
88  struct Log_waiter
89  {
90  CallbackPtr m_callback;
91  union {
92  Uint32 m_size;
93  Uint64 m_sync_lsn;
94  };
95  Uint32 m_block; // includes instance
96  Uint32 nextList;
97  Uint32 m_magic;
98  };
99 
103 
104  struct Undofile
105  {
106  Undofile(){}
107  Undofile(const struct CreateFileImplReq*, Uint32 lg_ptr_i);
108 
109  Uint32 m_magic;
110  Uint32 m_file_id; // Dict obj id
111  Uint32 m_logfile_group_ptr_i;
112 
113  Uint32 m_file_size;
114  Uint32 m_state;
115  Uint32 m_fd; // When speaking to NDBFS
116 
117  enum FileState
118  {
119  FS_CREATING = 0x1 // File is being created
120  ,FS_DROPPING = 0x2 // File is being dropped
121  ,FS_ONLINE = 0x4 // File is online
122  ,FS_OPENING = 0x8 // File is being opened during SR
123  ,FS_SORTING = 0x10 // Files in group are being sorted
124  ,FS_SEARCHING = 0x20 // File is being searched for end of log
125  ,FS_EXECUTING = 0x40 // File is used for executing UNDO log
126  ,FS_EMPTY = 0x80 // File is empty (used when online)
127  ,FS_OUTSTANDING = 0x100 // File has outstanding request
128  ,FS_MOVE_NEXT = 0x200 // When receiving reply move to next file
129  };
130 
131  union {
132  struct {
133  Uint32 m_outstanding; // Outstaning pages
134  Uint64 m_lsn; // Used when finding log head
135  } m_online;
136  struct {
137  Uint32 m_senderData;
138  Uint32 m_senderRef;
139  Uint32 m_logfile_group_id;
140  Uint32 m_logfile_group_version;
141  } m_create;
142  };
143 
144  Uint32 nextList;
145  union {
146  Uint32 prevList;
147  Uint32 nextPool;
148  };
149  };
150 
155 
156  struct Buffer_idx
157  {
158  Uint32 m_ptr_i;
159  Uint32 m_idx;
160  bool operator== (const Buffer_idx& bi) const {
161  return (m_ptr_i == bi.m_ptr_i && m_idx == bi.m_idx);
162  }
163  };
164 
166  {
167  Logfile_group(){}
168  Logfile_group(const struct CreateFilegroupImplReq*);
169 
170  Uint32 m_magic;
171  union {
172  Uint32 key;
173  Uint32 m_logfile_group_id;
174  };
175  Uint32 m_version;
176  Uint16 m_state;
177  Uint16 m_outstanding_fs;
178  Uint32 m_next_reply_ptr_i;
179 
180  enum Logfile_group_state
181  {
182  LG_ONLINE = 0x001
183  ,LG_SORTING = 0x002 // Sorting files
184  ,LG_SEARCHING = 0x004 // Searching in last file
185  ,LG_EXEC_THREAD = 0x008 // Execute thread is running
186  ,LG_READ_THREAD = 0x010 // Read thread is running
187  ,LG_FORCE_SYNC_THREAD = 0x020
188  ,LG_SYNC_WAITERS_THREAD = 0x040
189  ,LG_CUT_LOG_THREAD = 0x080
190  ,LG_WAITERS_THREAD = 0x100
191  ,LG_FLUSH_THREAD = 0x200
192  ,LG_DROPPING = 0x400
193  ,LG_STARTING = 0x800
194  };
195 
196  static const Uint32 LG_THREAD_MASK = Logfile_group::LG_FORCE_SYNC_THREAD |
197  Logfile_group::LG_SYNC_WAITERS_THREAD |
198  Logfile_group::LG_CUT_LOG_THREAD |
199  Logfile_group::LG_WAITERS_THREAD |
200  Logfile_group::LG_FLUSH_THREAD;
201 
202  Uint64 m_last_lsn;
203  Uint64 m_last_sync_req_lsn; // Outstanding
204  Uint64 m_last_synced_lsn; //
205  Uint64 m_max_sync_req_lsn; // User requested lsn
206  union {
207  Uint64 m_last_read_lsn;
208  Uint64 m_last_lcp_lsn;
209  };
210  Log_waiter_list::Head m_log_sync_waiters;
211 
212  Buffer_idx m_tail_pos[3]; // 0 is cut, 1 is saved, 2 is current
213  Buffer_idx m_file_pos[2]; // 0 tail, 1 head = { file_ptr_i, page_no }
214  Uint64 m_free_file_words; // Free words in logfile group
215 
216  Undofile_list::Head m_files; // Files in log
217  Undofile_list::Head m_meta_files;// Files being created or dropped
218 
219  Uint32 m_total_buffer_words; // Total buffer page words
220  Uint32 m_free_buffer_words; // Free buffer page words
221  Uint32 m_callback_buffer_words; // buffer words that has been
222  // returned to user, but not yet consumed
223  Log_waiter_list::Head m_log_buffer_waiters;
224  Page_map::Head m_buffer_pages; // Pairs of { ptr.i, count }
225  struct Position {
226  Buffer_idx m_current_page; // { m_buffer_pages.i, left in range }
227  Buffer_idx m_current_pos; // { page ptr.i, m_words_used }
228  } m_pos[2]; // 0 is reader (lgman) 1 is writer (tup)
229 
230  Uint32 nextHash;
231  Uint32 prevHash;
232  Uint32 nextList;
233  union {
234  Uint32 prevList;
235  Uint32 nextPool;
236  };
237  Uint32 hashValue() const {
238  return key;
239  }
240  bool equal(const Logfile_group& rec) const {
241  return key == rec.key;
242  }
243  };
244 
245  typedef RecordPool<Logfile_group, RWPool> Logfile_group_pool;
246  typedef DLFifoListImpl<Logfile_group_pool, Logfile_group> Logfile_group_list;
247  typedef LocalDLFifoListImpl<Logfile_group_pool, Logfile_group> Local_logfile_group_list;
248  typedef KeyTableImpl<Logfile_group_pool, Logfile_group> Logfile_group_hash;
249  typedef KeyTableImpl<Logfile_group_pool, Logfile_group>::Iterator Logfile_group_hash_iterator;
250  enum CallbackIndex {
251  // lgman
252  ENDLCP_CALLBACK = 1,
253  COUNT_CALLBACKS = 2
254  };
255  CallbackEntry m_callbackEntry[COUNT_CALLBACKS];
256  CallbackTable m_callbackTable;
257 
258 private:
259  friend class Logfile_client;
260  SimulatedBlock* m_tup;
261 
268  int alloc_log_space(Uint32 logfile_ref, Uint32 words);
269  int free_log_space(Uint32 logfile_ref, Uint32 words);
270 
271  Undofile_pool m_file_pool;
272  Logfile_group_pool m_logfile_group_pool;
273  Log_waiter_pool m_log_waiter_pool;
274 
275  Page_map::DataBufferPool m_data_buffer_pool;
276 
277  Uint64 m_last_lsn;
278  Uint32 m_latest_lcp;
279  Logfile_group_list m_logfile_group_list;
280  Logfile_group_hash m_logfile_group_hash;
281  Uint32 m_end_lcp_senderdata;
282 
283  SafeMutex m_client_mutex;
284  void client_lock(BlockNumber block, int line);
285  void client_unlock(BlockNumber block, int line);
286 
287  bool alloc_logbuffer_memory(Ptr<Logfile_group>, Uint32 pages);
288  void init_logbuffer_pointers(Ptr<Logfile_group>);
289  void free_logbuffer_memory(Ptr<Logfile_group>);
290  Uint32 compute_free_file_pages(Ptr<Logfile_group>);
291  Uint32* get_log_buffer(Ptr<Logfile_group>, Uint32 sz);
292  void process_log_buffer_waiters(Signal* signal, Ptr<Logfile_group>);
293  Uint32 next_page(Logfile_group* ptrP, Uint32 i);
294 
295  void force_log_sync(Signal*, Ptr<Logfile_group>, Uint32 lsnhi, Uint32 lnslo);
296  void process_log_sync_waiters(Signal* signal, Ptr<Logfile_group>);
297 
298  void cut_log_tail(Signal*, Ptr<Logfile_group> ptr);
299  void endlcp_callback(Signal*, Uint32, Uint32);
300  void open_file(Signal*, Ptr<Undofile>, Uint32, SectionHandle*);
301 
302  void flush_log(Signal*, Ptr<Logfile_group>, Uint32 force);
303  Uint32 write_log_pages(Signal*, Ptr<Logfile_group>,
304  Uint32 pageId, Uint32 pages);
305 
306  void find_log_head(Signal* signal, Ptr<Logfile_group> ptr);
307  void find_log_head_in_file(Signal*, Ptr<Logfile_group>,Ptr<Undofile>,Uint64);
308 
309  void init_run_undo_log(Signal*);
310  void read_undo_log(Signal*, Ptr<Logfile_group> ptr);
311  Uint32 read_undo_pages(Signal*, Ptr<Logfile_group>,
312  Uint32 pageId, Uint32 pages);
313 
314  void execute_undo_record(Signal*);
315  const Uint32* get_next_undo_record(Uint64* lsn);
316  void stop_run_undo_log(Signal* signal);
317  void init_tail_ptr(Signal* signal, Ptr<Logfile_group> ptr);
318 
319  bool find_file_by_id(Ptr<Undofile>&, Undofile_list::Head&, Uint32 id);
320  void create_file_commit(Signal* signal, Ptr<Logfile_group>, Ptr<Undofile>);
321  void create_file_abort(Signal* signal, Ptr<Logfile_group>, Ptr<Undofile>);
322 
323 #ifdef VM_TRACE
324  void validate_logfile_group(Ptr<Logfile_group> ptr, const char * = 0);
325 #else
326  void validate_logfile_group(Ptr<Logfile_group> ptr, const char * = 0) {}
327 #endif
328 
329  void drop_filegroup_drop_files(Signal*, Ptr<Logfile_group>,
330  Uint32 ref, Uint32 data);
331 };
332 
334  SimulatedBlock *m_client_block;
335  Uint32 m_block; // includes instance
336  Lgman * m_lgman;
337  bool m_lock;
338  DEBUG_OUT_DEFINES(LGMAN);
339 public:
340  Uint32 m_logfile_group_id;
341 
342  Logfile_client(SimulatedBlock* block, Lgman*, Uint32 logfile_group_id,
343  bool lock = true);
344  ~Logfile_client();
345 
346  struct Request
347  {
348  SimulatedBlock::CallbackPtr m_callback;
349  };
350 
355  {
356  };
357 
364  int sync_lsn(Signal*, Uint64, Request*, Uint32 flags);
365 
369  struct Change
370  {
371  const void * ptr;
372  Uint32 len;
373  };
374 
375  Uint64 add_entry(const void*, Uint32 len);
376  Uint64 add_entry(const Change*, Uint32 cnt);
377 
378  Uint64 add_entry(Local_key, void * base, Change*);
379  Uint64 add_entry(Local_key, Uint32 off, Uint32 change);
380 
389 
390  int alloc_log_space(Uint32 words) {
391  return m_lgman->alloc_log_space(m_logfile_group_id, words);
392  }
393 
394  int free_log_space(Uint32 words) {
395  return m_lgman->free_log_space(m_logfile_group_id, words);
396  }
397 
398  void exec_lcp_frag_ord(Signal* signal) {
399  m_lgman->exec_lcp_frag_ord(signal, m_client_block);
400  }
401 
402 private:
403  Uint32* get_log_buffer(Uint32 sz);
404 };
405 
406 
407 #endif