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