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