19 #include <signaldata/FsRef.hpp>
20 #include <signaldata/FsConf.hpp>
21 #include <signaldata/FsReadWriteReq.hpp>
22 #include <signaldata/PgmanContinueB.hpp>
23 #include <signaldata/LCP.hpp>
24 #include <signaldata/DataFileOrd.hpp>
25 #include <signaldata/ReleasePages.hpp>
27 #include <dbtup/Dbtup.hpp>
29 #include <DebuggerNames.hpp>
30 #include <md5_hash.hpp>
35 #define DIRTY_FLAGS (Page_request::COMMIT_REQ | \
36 Page_request::DIRTY_REQ | \
37 Page_request::ALLOC_REQ)
39 static bool g_dbg_lcp =
false;
43 #define DBG_LCP(x) if(g_dbg_lcp) ndbout << x
48 m_file_map(m_data_buffer_pool),
49 m_page_hashlist(m_page_entry_pool),
50 m_page_stack(m_page_entry_pool),
51 m_page_queue(m_page_entry_pool)
54 ,debugSummaryFlag(false)
57 BLOCK_CONSTRUCTOR(
Pgman);
60 addRecSignal(GSN_STTOR, &Pgman::execSTTOR);
61 addRecSignal(GSN_READ_CONFIG_REQ, &Pgman::execREAD_CONFIG_REQ);
62 addRecSignal(GSN_DUMP_STATE_ORD, &Pgman::execDUMP_STATE_ORD);
63 addRecSignal(GSN_CONTINUEB, &Pgman::execCONTINUEB);
64 addRecSignal(GSN_FSREADREF, &Pgman::execFSREADREF,
true);
65 addRecSignal(GSN_FSREADCONF, &Pgman::execFSREADCONF);
66 addRecSignal(GSN_FSWRITEREF, &Pgman::execFSWRITEREF,
true);
67 addRecSignal(GSN_FSWRITECONF, &Pgman::execFSWRITECONF);
69 addRecSignal(GSN_LCP_FRAG_ORD, &Pgman::execLCP_FRAG_ORD);
70 addRecSignal(GSN_END_LCP_REQ, &Pgman::execEND_LCP_REQ);
72 addRecSignal(GSN_DATA_FILE_ORD, &Pgman::execDATA_FILE_ORD);
73 addRecSignal(GSN_RELEASE_PAGES_REQ, &Pgman::execRELEASE_PAGES_REQ);
74 addRecSignal(GSN_DBINFO_SCANREQ, &Pgman::execDBINFO_SCANREQ);
77 m_stats_loop_on =
false;
78 m_busy_loop_on =
false;
79 m_cleanup_loop_on =
false;
82 m_lcp_state = LS_LCP_OFF;
84 m_last_lcp_complete = 0;
85 m_lcp_curr_bucket = ~(Uint32)0;
86 m_lcp_outstanding = 0;
89 m_cleanup_ptr.i = RNIL;
92 m_data_buffer_pool.setSize(16);
93 m_page_hashlist.setSize(512);
95 for (Uint32 k = 0; k < Page_entry::SUBLIST_COUNT; k++)
96 m_page_sublist[k] =
new Page_sublist(m_page_entry_pool);
99 CallbackEntry& ce = m_callbackEntry[THE_NULL_CALLBACK];
100 ce.m_function = TheNULLCallback.m_callbackFunction;
104 CallbackEntry& ce = m_callbackEntry[LOGSYNC_CALLBACK];
105 ce.m_function = safe_cast(&Pgman::logsync_callback);
109 CallbackTable& ct = m_callbackTable;
110 ct.m_count = COUNT_CALLBACKS;
111 ct.m_entry = m_callbackEntry;
112 m_callbackTableAddr = &ct;
118 for (Uint32 k = 0; k < Page_entry::SUBLIST_COUNT; k++)
119 delete m_page_sublist[k];
122 BLOCK_FUNCTIONS(
Pgman)
131 Uint32 ref = req->senderRef;
132 Uint32 senderData = req->senderData;
135 m_ctx.m_config.getOwnConfigIterator();
138 Uint64 page_buffer = 64*1024*1024;
139 ndb_mgm_get_int64_parameter(p, CFG_DB_DISK_PAGE_BUFFER_MEMORY, &page_buffer);
146 Uint32 workers = getLqhWorkers() + 1;
147 page_buffer = page_buffer / workers;
148 Uint32 min_buffer = 4*1024*1024;
149 if (page_buffer < min_buffer)
150 page_buffer = min_buffer;
153 Uint32 page_cnt = Uint32((page_buffer + GLOBAL_PAGE_SIZE - 1) / GLOBAL_PAGE_SIZE);
155 if (ERROR_INSERTED(11009))
158 ndbout_c(
"Setting page_cnt = %u", page_cnt);
161 m_param.m_max_pages = page_cnt;
162 m_page_entry_pool.setSize(m_param.m_lirs_stack_mult * page_cnt);
163 m_param.m_max_hot_pages = (page_cnt * 9) / 10;
164 ndbrequire(m_param.m_max_hot_pages >= 1);
169 m_page_request_pool.wo_pool_init(RT_PGMAN_PAGE_REQUEST, pc);
172 conf->senderRef = reference();
173 conf->senderData = senderData;
174 sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
175 ReadConfigConf::SignalLength, JBB);
178 Pgman::Param::Param() :
180 m_lirs_stack_mult(10),
182 m_max_loop_count(256),
184 m_stats_loop_delay(1000),
185 m_cleanup_loop_delay(200),
191 Pgman::execSTTOR(
Signal* signal)
195 const Uint32 startPhase = signal->theData[1];
197 switch (startPhase) {
201 c_tup = (
Dbtup*)globalData.getBlock(DBTUP);
202 }
else if (instance() <= getLqhWorkers()) {
203 c_tup = (
Dbtup*)globalData.getBlock(DBTUP, instance());
204 ndbrequire(c_tup != 0);
209 c_lgman = (
Lgman*)globalData.getBlock(LGMAN);
210 c_tsman = (
Tsman*)globalData.getBlock(TSMAN);
216 do_stats_loop(signal);
217 do_cleanup_loop(signal);
218 m_stats_loop_on =
true;
219 m_cleanup_loop_on =
true;
232 Pgman::sendSTTORRY(
Signal* signal)
234 signal->theData[0] = 0;
235 signal->theData[3] = 1;
236 signal->theData[4] = 3;
237 signal->theData[5] = 7;
238 signal->theData[6] = 255;
239 BlockReference cntrRef = !isNdbMtLqh() ? NDBCNTR_REF : PGMAN_REF;
240 sendSignal(cntrRef, GSN_STTORRY, signal, 7, JBB);
244 Pgman::execCONTINUEB(
Signal* signal)
247 Uint32 data1 = signal->theData[1];
249 switch (signal->theData[0]) {
250 case PgmanContinueB::STATS_LOOP:
252 do_stats_loop(signal);
254 case PgmanContinueB::BUSY_LOOP:
256 do_busy_loop(signal);
258 case PgmanContinueB::CLEANUP_LOOP:
260 do_cleanup_loop(signal);
262 case PgmanContinueB::LCP_LOOP:
266 case PgmanContinueB::LCP_LOCKED:
270 Page_sublist& pl = *m_page_sublist[Page_entry::SL_LOCKED];
274 pl.getPtr(ptr, data1);
275 process_lcp_locked(signal, ptr);
280 if (ERROR_INSERTED(11007))
282 ndbout <<
"No more writes..." << endl;
283 SET_ERROR_INSERT_VALUE(11008);
284 signal->theData[0] = 9999;
285 sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 10000, 1);
288 conf->senderData = m_end_lcp_req.senderData;
289 conf->senderRef = reference();
290 sendSignal(m_end_lcp_req.senderRef, GSN_END_LCP_CONF,
291 signal, EndLcpConf::SignalLength, JBB);
292 m_lcp_state = LS_LCP_OFF;
304 Pgman::Page_entry::Page_entry(Uint32 file_no, Uint32 page_no) :
321 Pgman::get_sublist_no(Page_state state)
323 if (state & Page_entry::REQUEST)
325 if (! (state & Page_entry::BOUND))
327 return Page_entry::SL_BIND;
329 if (! (state & Page_entry::MAPPED))
331 if (! (state & Page_entry::PAGEIN))
333 return Page_entry::SL_MAP;
335 return Page_entry::SL_MAP_IO;
337 if (! (state & Page_entry::PAGEOUT))
339 return Page_entry::SL_CALLBACK;
341 return Page_entry::SL_CALLBACK_IO;
343 if (state & Page_entry::BUSY)
345 return Page_entry::SL_BUSY;
347 if (state & Page_entry::LOCKED)
349 return Page_entry::SL_LOCKED;
351 if (state == Page_entry::ONSTACK) {
352 return Page_entry::SL_IDLE;
356 return Page_entry::SL_OTHER;
364 D(
">set_page_state: state=" << hex << new_state);
365 D(ptr <<
": before");
367 Page_state old_state = ptr.p->m_state;
368 if (old_state != new_state)
370 Uint32 old_list_no = get_sublist_no(old_state);
371 Uint32 new_list_no = get_sublist_no(new_state);
374 ndbrequire(old_list_no != ZNIL);
375 if (old_list_no != new_list_no)
377 Page_sublist& old_list = *m_page_sublist[old_list_no];
378 old_list.remove(ptr);
383 ndbrequire(new_list_no != ZNIL);
384 if (old_list_no != new_list_no)
386 Page_sublist& new_list = *m_page_sublist[new_list_no];
390 ptr.p->m_state = new_state;
392 bool old_hot = (old_state & Page_entry::HOT);
393 bool new_hot = (new_state & Page_entry::HOT);
394 if (! old_hot && new_hot)
397 m_stats.m_num_hot_pages++;
399 if (old_hot && ! new_hot)
402 ndbrequire(m_stats.m_num_hot_pages != 0);
403 m_stats.m_num_hot_pages--;
409 verify_page_entry(ptr);
411 D(
"<set_page_state");
420 bool ok = m_global_page_pool.
seize(gptr);
423 if (ok && gptr.i == 0)
424 ok = m_global_page_pool.
seize(gptr);
428 ndbrequire(m_stats.m_num_pages < m_param.m_max_pages);
429 m_stats.m_num_pages++;
435 Pgman::release_cache_page(Uint32
i)
439 ndbrequire(m_stats.m_num_pages != 0);
440 m_stats.m_num_pages--;
444 Pgman::find_page_entry(
Ptr<Page_entry>& ptr, Uint32 file_no, Uint32 page_no)
447 key.m_file_no = file_no;
448 key.m_page_no = page_no;
450 if (m_page_hashlist.
find(ptr, key))
452 D(
"find_page_entry");
460 Pgman::seize_page_entry(
Ptr<Page_entry>& ptr, Uint32 file_no, Uint32 page_no)
462 if (m_page_entry_pool.
seize(ptr))
464 new (ptr.p) Page_entry(file_no, page_no);
465 m_page_hashlist.
add(ptr);
467 ptr.p->m_this =
this;
469 D(
"seize_page_entry");
478 Pgman::get_page_entry(
Ptr<Page_entry>& ptr, Uint32 file_no, Uint32 page_no)
480 if (find_page_entry(ptr, file_no, page_no))
483 ndbrequire(ptr.p->m_state != 0);
484 m_stats.m_page_hits++;
486 D(
"get_page_entry: found");
491 if (m_page_entry_pool.getNoOfFree() == 0)
494 Page_sublist& pl_idle = *m_page_sublist[Page_entry::SL_IDLE];
496 if (pl_idle.first(idle_ptr))
500 D(
"get_page_entry: re-use idle entry");
503 Page_state state = idle_ptr.p->m_state;
504 ndbrequire(state == Page_entry::ONSTACK);
506 Page_stack& pl_stack = m_page_stack;
507 ndbrequire(pl_stack.hasPrev(idle_ptr));
508 pl_stack.remove(idle_ptr);
509 state &= ~ Page_entry::ONSTACK;
510 set_page_state(idle_ptr, state);
511 ndbrequire(idle_ptr.p->m_state == 0);
513 release_page_entry(idle_ptr);
517 if (seize_page_entry(ptr, file_no, page_no))
520 ndbrequire(ptr.p->m_state == 0);
521 m_stats.m_page_faults++;
523 D(
"get_page_entry: seize");
536 D(
"release_page_entry");
538 Page_state state = ptr.p->m_state;
540 ndbrequire(ptr.p->m_requests.isEmpty());
542 ndbrequire(! (state & Page_entry::ONSTACK));
543 ndbrequire(! (state & Page_entry::ONQUEUE));
544 ndbrequire(ptr.p->m_real_page_i == RNIL);
546 if (! (state & Page_entry::LOCKED))
548 ndbrequire(! (state & Page_entry::REQUEST));
551 if (ptr.p->m_copy_page_i != RNIL)
553 m_global_page_pool.
release(ptr.p->m_copy_page_i);
556 set_page_state(ptr, 0);
557 m_page_hashlist.
remove(ptr);
558 m_page_entry_pool.
release(ptr);
571 Pgman::lirs_stack_prune()
573 D(
">lirs_stack_prune");
574 Page_stack& pl_stack = m_page_stack;
577 while (pl_stack.first(ptr))
579 Page_state state = ptr.p->m_state;
580 if (state & Page_entry::HOT)
586 D(ptr <<
": prune from stack");
588 pl_stack.remove(ptr);
589 state &= ~ Page_entry::ONSTACK;
590 set_page_state(ptr, state);
592 if (state & Page_entry::BOUND)
595 ndbrequire(state & Page_entry::ONQUEUE);
597 else if (state & Page_entry::REQUEST)
601 ndbrequire(! (state & Page_entry::ONQUEUE));
606 release_page_entry(ptr);
609 D(
"<lirs_stack_prune");
619 Pgman::lirs_stack_pop()
622 Page_stack& pl_stack = m_page_stack;
623 Page_queue& pl_queue = m_page_queue;
626 bool ok = pl_stack.first(ptr);
628 Page_state state = ptr.p->m_state;
630 D(ptr <<
": pop from stack");
632 ndbrequire(state & Page_entry::HOT);
633 ndbrequire(state & Page_entry::ONSTACK);
634 pl_stack.remove(ptr);
635 state &= ~ Page_entry::HOT;
636 state &= ~ Page_entry::ONSTACK;
637 ndbrequire(! (state & Page_entry::ONQUEUE));
639 if (state & Page_entry::BOUND)
643 state |= Page_entry::ONQUEUE;
649 ndbrequire(state & Page_entry::REQUEST);
652 set_page_state(ptr, state);
662 D(
">lirs_reference");
664 Page_stack& pl_stack = m_page_stack;
665 Page_queue& pl_queue = m_page_queue;
667 Page_state state = ptr.p->m_state;
668 ndbrequire(! (state & Page_entry::LOCKED));
670 ndbrequire(m_stats.m_num_hot_pages <= m_param.m_max_hot_pages);
673 if (m_stats.m_num_hot_pages == m_param.m_max_hot_pages)
675 if (state & Page_entry::HOT)
679 ndbrequire(state & Page_entry::ONSTACK);
680 bool at_bottom = ! pl_stack.hasPrev(ptr);
681 pl_stack.remove(ptr);
689 else if (state & Page_entry::ONSTACK)
693 pl_stack.remove(ptr);
694 if (! pl_stack.isEmpty())
700 state |= Page_entry::HOT;
701 if (state & Page_entry::ONQUEUE)
704 move_cleanup_ptr(ptr);
705 pl_queue.remove(ptr);
706 state &= ~ Page_entry::ONQUEUE;
714 state |= Page_entry::ONSTACK;
720 ndbrequire(pl_stack.hasPrev(ptr));
721 if (state & Page_entry::ONQUEUE)
724 move_cleanup_ptr(ptr);
725 pl_queue.remove(ptr);
726 state &= ~ Page_entry::ONQUEUE;
728 if (state & Page_entry::BOUND)
732 state |= Page_entry::ONQUEUE;
743 D(
"filling up hot pages: " << m_stats.m_num_hot_pages <<
"/"
744 << m_param.m_max_hot_pages);
746 if (state & Page_entry::ONSTACK)
749 bool at_bottom = ! pl_stack.hasPrev(ptr);
750 pl_stack.remove(ptr);
754 ndbassert(state & Page_entry::HOT);
759 state |= Page_entry::ONSTACK;
760 state |= Page_entry::HOT;
762 if (state & Page_entry::ONQUEUE) {
764 pl_queue.remove(ptr);
765 state &= ~Page_entry::ONQUEUE;
769 set_page_state(ptr, state);
770 D(
"<lirs_reference");
776 Pgman::do_stats_loop(
Signal* signal)
782 Uint32 delay = m_param.m_stats_loop_delay;
783 signal->theData[0] = PgmanContinueB::STATS_LOOP;
784 sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, delay, 1);
788 Pgman::do_busy_loop(
Signal* signal,
bool direct)
790 D(
">do_busy_loop on=" << m_busy_loop_on <<
" direct=" << direct);
791 Uint32 restart =
false;
795 (void)process_bind(signal);
796 (void)process_map(signal);
798 if (! m_busy_loop_on)
801 m_busy_loop_on =
true;
806 ndbrequire(m_busy_loop_on);
807 restart += process_bind(signal);
808 restart += process_map(signal);
809 restart += process_callback(signal);
812 m_busy_loop_on =
false;
817 signal->theData[0] = PgmanContinueB::BUSY_LOOP;
818 sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
820 D(
"<do_busy_loop on=" << m_busy_loop_on <<
" restart=" << restart);
824 Pgman::do_cleanup_loop(
Signal* signal)
826 D(
"do_cleanup_loop");
827 process_cleanup(signal);
829 Uint32 delay = m_param.m_cleanup_loop_delay;
830 signal->theData[0] = PgmanContinueB::CLEANUP_LOOP;
831 sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, delay, 1);
835 Pgman::do_lcp_loop(
Signal* signal)
837 D(
">do_lcp_loop m_lcp_state=" << Uint32(m_lcp_state));
838 ndbrequire(m_lcp_state != LS_LCP_OFF);
839 LCP_STATE newstate = process_lcp(signal);
847 signal->theData[0] = PgmanContinueB::LCP_LOOP;
848 sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
850 case LS_LCP_MAX_LCP_OUTSTANDING:
857 m_lcp_state = newstate;
858 D(
"<do_lcp_loop m_lcp_state=" << Uint32(m_lcp_state));
864 Pgman::process_bind(
Signal* signal)
868 Page_sublist& pl_bind = *m_page_sublist[Page_entry::SL_BIND];
870 while (! pl_bind.isEmpty() && --max_count >= 0)
875 if (! process_bind(signal, ptr))
882 return ! pl_bind.isEmpty();
888 D(ptr <<
" : process_bind");
889 Page_queue& pl_queue = m_page_queue;
892 if (m_stats.m_num_pages < m_param.m_max_pages)
895 bool ok = seize_cache_page(gptr);
903 if (! pl_queue.first(clean_ptr))
906 D(
"bind failed: queue empty");
910 Page_state clean_state = clean_ptr.p->m_state;
912 if (! (clean_state & Page_entry::MAPPED) ||
913 clean_state & Page_entry::DIRTY ||
914 clean_state & Page_entry::REQUEST)
917 D(
"bind failed: queue front not evictable");
923 D(clean_ptr <<
" : evict");
925 ndbassert(clean_ptr.p->m_dirty_count == 0);
926 ndbrequire(clean_state & Page_entry::ONQUEUE);
927 ndbrequire(clean_state & Page_entry::BOUND);
928 ndbrequire(clean_state & Page_entry::MAPPED);
930 move_cleanup_ptr(clean_ptr);
931 pl_queue.remove(clean_ptr);
932 clean_state &= ~ Page_entry::ONQUEUE;
934 gptr.i = clean_ptr.p->m_real_page_i;
936 clean_ptr.p->m_real_page_i = RNIL;
937 clean_state &= ~ Page_entry::BOUND;
938 clean_state &= ~ Page_entry::MAPPED;
940 set_page_state(clean_ptr, clean_state);
942 if (! (clean_state & Page_entry::ONSTACK))
943 release_page_entry(clean_ptr);
945 m_global_page_pool.
getPtr(gptr);
948 Page_state state = ptr.p->m_state;
950 ptr.p->m_real_page_i = gptr.i;
951 state |= Page_entry::BOUND;
952 if (state & Page_entry::EMPTY)
955 state |= Page_entry::MAPPED;
958 if (! (state & Page_entry::LOCKED) &&
959 ! (state & Page_entry::ONQUEUE) &&
960 ! (state & Page_entry::HOT))
964 D(ptr <<
" : add to queue at bind");
966 state |= Page_entry::ONQUEUE;
969 set_page_state(ptr, state);
974 Pgman::process_map(
Signal* signal)
978 if (m_param.m_max_io_waits > m_stats.m_current_io_waits) {
979 max_count = m_param.m_max_io_waits - m_stats.m_current_io_waits;
980 max_count = max_count / 2 + 1;
982 Page_sublist& pl_map = *m_page_sublist[Page_entry::SL_MAP];
984 while (! pl_map.isEmpty() && --max_count >= 0)
989 if (! process_map(signal, ptr))
996 return ! pl_map.isEmpty();
1002 D(ptr <<
" : process_map");
1003 pagein(signal, ptr);
1008 Pgman::process_callback(
Signal* signal)
1010 D(
">process_callback");
1012 Page_sublist& pl_callback = *m_page_sublist[Page_entry::SL_CALLBACK];
1015 pl_callback.first(ptr);
1017 while (! ptr.isNull() && --max_count >= 0)
1021 pl_callback.next(ptr);
1023 if (! process_callback(signal, curr))
1029 D(
"<process_callback");
1030 return ! pl_callback.isEmpty();
1036 D(ptr <<
" : process_callback");
1039 while (! ptr.p->m_requests.isEmpty() && --max_count >= 0)
1042 Page_state state = ptr.p->m_state;
1050 Local_page_request_list req_list(m_page_request_pool, ptr.p->m_requests);
1053 req_list.first(req_ptr);
1054 D(req_ptr <<
" : process_callback");
1057 if (req_ptr.p->m_flags & Page_request::DELAY_REQ)
1059 Uint64 now = NdbTick_CurrentMillisecond();
1060 if (now < req_ptr.p->m_delay_until_time)
1067 Uint32 blockNo = blockToMain(req_ptr.p->m_block);
1068 Uint32 instanceNo = blockToInstance(req_ptr.p->m_block);
1069 b = globalData.getBlock(blockNo, instanceNo);
1070 callback = req_ptr.p->m_callback;
1072 if (req_ptr.p->m_flags & DIRTY_FLAGS)
1075 state |= Page_entry::DIRTY;
1076 ndbassert(ptr.p->m_dirty_count);
1077 ptr.p->m_dirty_count --;
1080 req_list.releaseFirst(req_ptr);
1082 ndbrequire(state & Page_entry::BOUND);
1083 ndbrequire(state & Page_entry::MAPPED);
1086 if (ptr.p->m_requests.isEmpty())
1089 state &= ~ Page_entry::REQUEST;
1093 set_page_state(ptr, state);
1094 b->execute(signal, callback, ptr.p->m_real_page_i);
1102 Pgman::process_cleanup(
Signal* signal)
1104 D(
">process_cleanup");
1105 Page_queue& pl_queue = m_page_queue;
1108 m_cleanup_ptr.i = RNIL;
1110 if (m_cleanup_ptr.i == RNIL && ! pl_queue.first(m_cleanup_ptr))
1113 D(
"<process_cleanup: empty queue");
1117 int max_loop_count = m_param.m_max_loop_count;
1119 if (m_param.m_max_io_waits > m_stats.m_current_io_waits) {
1120 max_count = m_param.m_max_io_waits - m_stats.m_current_io_waits;
1121 max_count = max_count / 2 + 1;
1125 while (max_loop_count != 0 && max_count != 0)
1127 Page_state state = ptr.p->m_state;
1128 ndbrequire(! (state & Page_entry::LOCKED));
1129 if (state & Page_entry::BUSY)
1131 D(
"process_cleanup: break on busy page");
1135 if (state & Page_entry::DIRTY &&
1136 ! (state & Page_entry::PAGEIN) &&
1137 ! (state & Page_entry::PAGEOUT))
1139 D(ptr <<
" : process_cleanup");
1142 ptr.p->m_real_page_i,
1143 ptr.p->m_dirty_count);
1144 pageout(signal, ptr);
1147 if (! pl_queue.hasNext(ptr))
1152 m_cleanup_ptr = ptr;
1153 D(
"<process_cleanup");
1164 Page_queue& pl_queue = m_page_queue;
1165 if (ptr.i == m_cleanup_ptr.i)
1168 pl_queue.prev(m_cleanup_ptr);
1176 Pgman::execLCP_FRAG_ORD(
Signal* signal)
1178 if (ERROR_INSERTED(11008))
1180 ndbout_c(
"Ignore LCP_FRAG_ORD");
1184 ndbrequire(ord->lcpId >= m_last_lcp_complete + 1 || m_last_lcp_complete == 0);
1185 m_last_lcp = ord->lcpId;
1186 DBG_LCP(
"Pgman::execLCP_FRAG_ORD lcp: " << m_last_lcp << endl);
1188 D(
"execLCP_FRAG_ORD"
1189 <<
" this=" << m_last_lcp
1190 <<
" last_complete=" << m_last_lcp_complete
1191 <<
" bucket=" << m_lcp_curr_bucket);
1195 Pgman::execEND_LCP_REQ(
Signal* signal)
1197 if (ERROR_INSERTED(11008))
1199 ndbout_c(
"Ignore END_LCP");
1204 m_end_lcp_req = *req;
1206 DBG_LCP(
"execEND_LCP_REQ" << endl);
1208 ndbrequire(!m_lcp_outstanding);
1209 m_lcp_curr_bucket = 0;
1212 <<
" this=" << m_last_lcp
1213 <<
" last_complete=" << m_last_lcp_complete
1214 <<
" bucket=" << m_lcp_curr_bucket
1215 <<
" outstanding=" << m_lcp_outstanding);
1217 m_last_lcp_complete = m_last_lcp;
1218 ndbrequire(m_lcp_state == LS_LCP_OFF);
1219 m_lcp_state = LS_LCP_ON;
1220 do_lcp_loop(signal);
1224 Pgman::process_lcp(
Signal* signal)
1226 Page_hashlist& pl_hash = m_page_hashlist;
1229 if (m_param.m_max_io_waits > m_stats.m_current_io_waits)
1232 max_count = m_param.m_max_io_waits - m_stats.m_current_io_waits;
1233 max_count = max_count / 2 + 1;
1237 <<
" this=" << m_last_lcp
1238 <<
" last_complete=" << m_last_lcp_complete
1239 <<
" bucket=" << m_lcp_curr_bucket
1240 <<
" outstanding=" << m_lcp_outstanding);
1243 if (m_lcp_curr_bucket != ~(Uint32)0)
1246 Page_hashlist::Iterator iter;
1247 pl_hash.next(m_lcp_curr_bucket, iter);
1249 while (iter.curr.i != RNIL &&
1250 m_lcp_outstanding < (Uint32) max_count &&
1251 (loop ++ < 32 || iter.bucket == m_lcp_curr_bucket))
1255 Page_state state = ptr.p->m_state;
1257 DBG_LCP(
"LCP " << ptr <<
" - ");
1259 if (ptr.p->m_last_lcp < m_last_lcp &&
1260 (state & Page_entry::DIRTY) &&
1261 (! (state & Page_entry::LOCKED)))
1264 if(! (state & Page_entry::BOUND))
1266 ndbout << ptr << endl;
1269 if (state & Page_entry::BUSY)
1272 DBG_LCP(
" BUSY" << endl);
1275 else if (state & Page_entry::PAGEOUT)
1278 DBG_LCP(
" PAGEOUT -> state |= LCP" << endl);
1279 set_page_state(ptr, state | Page_entry::LCP);
1284 DBG_LCP(
" pageout()" << endl);
1285 ptr.p->m_state |= Page_entry::LCP;
1288 ptr.p->m_real_page_i,
1289 ptr.p->m_dirty_count);
1290 pageout(signal, ptr);
1292 ptr.p->m_last_lcp = m_last_lcp;
1293 m_lcp_outstanding++;
1298 DBG_LCP(
" NOT DIRTY" << endl);
1303 m_lcp_curr_bucket = (iter.curr.i != RNIL ? iter.bucket : ~(Uint32)0);
1306 if (m_lcp_curr_bucket == ~(Uint32)0 && !m_lcp_outstanding)
1310 Page_sublist& pl = *m_page_sublist[Page_entry::SL_LOCKED];
1314 process_lcp_locked(signal, ptr);
1315 return LS_LCP_LOCKED;
1320 if (ERROR_INSERTED(11007))
1322 ndbout <<
"No more writes..." << endl;
1323 signal->theData[0] = 9999;
1324 sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 10000, 1);
1325 SET_ERROR_INSERT_VALUE(11008);
1328 conf->senderData = m_end_lcp_req.senderData;
1329 conf->senderRef = reference();
1330 sendSignal(m_end_lcp_req.senderRef, GSN_END_LCP_CONF,
1331 signal, EndLcpConf::SignalLength, JBB);
1336 if (m_lcp_outstanding >= (Uint32) max_count)
1339 return LS_LCP_MAX_LCP_OUTSTANDING;
1348 CRASH_INSERTION(11006);
1352 ptr.p->m_last_lcp = m_last_lcp;
1353 if (ptr.p->m_state & Page_entry::DIRTY)
1356 ndbrequire(m_global_page_pool.
seize(copy));
1357 m_global_page_pool.
getPtr(org, ptr.p->m_real_page_i);
1359 ptr.p->m_copy_page_i = copy.i;
1361 m_lcp_outstanding++;
1362 ptr.p->m_state |= Page_entry::LCP;
1363 pageout(signal, ptr);
1367 Page_sublist& pl = *m_page_sublist[Page_entry::SL_LOCKED];
1370 signal->theData[0] = PgmanContinueB::LCP_LOCKED;
1371 signal->theData[1] = ptr.i;
1372 sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
1379 m_global_page_pool.
getPtr(copy, ptr.p->m_copy_page_i);
1380 m_global_page_pool.
getPtr(org, ptr.p->m_real_page_i);
1382 m_global_page_pool.
release(copy);
1383 ptr.p->m_copy_page_i = RNIL;
1385 Page_sublist& pl = *m_page_sublist[Page_entry::SL_LOCKED];
1388 signal->theData[0] = PgmanContinueB::LCP_LOCKED;
1389 signal->theData[1] = ptr.i;
1390 sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
1401 ndbrequire(! (ptr.p->m_state & Page_entry::PAGEIN));
1402 set_page_state(ptr, ptr.p->m_state | Page_entry::PAGEIN);
1404 fsreadreq(signal, ptr);
1405 m_stats.m_current_io_waits++;
1414 ndbrequire(ptr.p->m_state & Page_entry::PAGEIN);
1415 Page_state state = ptr.p->m_state;
1417 state &= ~ Page_entry::PAGEIN;
1418 state &= ~ Page_entry::EMPTY;
1419 state |= Page_entry::MAPPED;
1420 set_page_state(ptr, state);
1430 m_global_page_pool.
getPtr(pagePtr, ptr.p->m_real_page_i);
1435 lsn += page->m_page_header.m_page_lsn_hi;
lsn <<= 32;
1436 lsn += page->m_page_header.m_page_lsn_lo;
1440 ndbrequire(m_stats.m_current_io_waits > 0);
1441 m_stats.m_current_io_waits--;
1442 m_stats.m_pages_read++;
1444 ptr.p->m_last_lcp = m_last_lcp_complete;
1445 do_busy_loop(signal,
true);
1454 Page_state state = ptr.p->m_state;
1455 ndbrequire(state & Page_entry::BOUND);
1456 ndbrequire(state & Page_entry::MAPPED);
1457 ndbrequire(! (state & Page_entry::BUSY));
1458 ndbrequire(! (state & Page_entry::PAGEOUT));
1460 state |= Page_entry::PAGEOUT;
1464 m_global_page_pool.
getPtr(pagePtr, ptr.p->m_real_page_i);
1467 page->m_page_header.m_page_lsn_hi = (Uint32)(ptr.p->m_lsn >> 32);
1468 page->m_page_header.m_page_lsn_lo = (Uint32)(ptr.p->m_lsn & 0xFFFFFFFF);
1472 req.m_callback.m_callbackData = ptr.i;
1473 req.m_callback.m_callbackIndex = LOGSYNC_CALLBACK;
1474 D(
"Logfile_client - pageout");
1476 int ret = lgman.sync_lsn(signal, ptr.p->m_lsn, &req, 0);
1479 fswritereq(signal, ptr);
1480 m_stats.m_current_io_waits++;
1484 ndbrequire(ret == 0);
1485 m_stats.m_log_waits++;
1486 state |= Page_entry::LOGSYNC;
1488 set_page_state(ptr, state);
1492 Pgman::logsync_callback(
Signal* signal, Uint32 ptrI, Uint32 res)
1495 m_page_entry_pool.
getPtr(ptr, ptrI);
1497 D(
"logsync_callback");
1501 Page_state state = ptr.p->m_state;
1502 ndbrequire(state & Page_entry::PAGEOUT);
1503 ndbrequire(state & Page_entry::LOGSYNC);
1504 state &= ~ Page_entry::LOGSYNC;
1505 set_page_state(ptr, state);
1507 fswritereq(signal, ptr);
1508 m_stats.m_current_io_waits++;
1517 Page_state state = ptr.p->m_state;
1518 ndbrequire(state & Page_entry::PAGEOUT);
1522 ptr.p->m_real_page_i,
1523 ptr.p->m_dirty_count);
1525 state &= ~ Page_entry::PAGEOUT;
1526 state &= ~ Page_entry::EMPTY;
1527 state &= ~ Page_entry::DIRTY;
1529 ndbrequire(m_stats.m_current_io_waits > 0);
1530 m_stats.m_current_io_waits--;
1532 if (state & Page_entry::LCP)
1535 state &= ~ Page_entry::LCP;
1536 ndbrequire(m_lcp_outstanding);
1537 m_lcp_outstanding--;
1538 m_stats.m_pages_written_lcp++;
1539 if (ptr.p->m_copy_page_i != RNIL)
1543 process_lcp_locked_fswriteconf(signal, ptr);
1544 set_page_state(ptr, state);
1545 do_busy_loop(signal,
true);
1551 m_stats.m_pages_written++;
1554 set_page_state(ptr, state);
1555 do_busy_loop(signal,
true);
1557 if (m_lcp_state == LS_LCP_MAX_LCP_OUTSTANDING)
1560 do_lcp_loop(signal);
1569 File_map::ConstDataBufferIterator it;
1570 bool ret = m_file_map.
first(it) && m_file_map.next(it, ptr.p->m_file_no);
1572 Uint32 fd = * it.data;
1574 ndbrequire(ptr.p->m_page_no > 0);
1577 req->filePointer = fd;
1578 req->userReference = reference();
1579 req->userPointer = ptr.i;
1580 req->varIndex = ptr.p->m_page_no;
1581 req->numberOfPages = 1;
1582 req->operationFlag = 0;
1583 FsReadWriteReq::setFormatFlag(req->operationFlag,
1584 FsReadWriteReq::fsFormatGlobalPage);
1585 req->data.pageData[0] = ptr.p->m_real_page_i;
1586 sendSignal(NDBFS_REF, GSN_FSREADREQ, signal,
1587 FsReadWriteReq::FixedLength + 1, JBA);
1591 Pgman::execFSREADCONF(
Signal* signal)
1596 m_page_entry_pool.
getPtr(ptr, conf->userPointer);
1598 fsreadconf(signal, ptr);
1602 Pgman::execFSREADREF(
Signal* signal)
1605 SimulatedBlock::execFSREADREF(signal);
1612 File_map::ConstDataBufferIterator it;
1613 m_file_map.
first(it);
1614 m_file_map.next(it, ptr.p->m_file_no);
1615 Uint32 fd = * it.data;
1617 ndbrequire(ptr.p->m_page_no > 0);
1620 req->filePointer = fd;
1621 req->userReference = reference();
1622 req->userPointer = ptr.i;
1623 req->varIndex = ptr.p->m_page_no;
1624 req->numberOfPages = 1;
1625 req->operationFlag = 0;
1626 FsReadWriteReq::setFormatFlag(req->operationFlag,
1627 FsReadWriteReq::fsFormatGlobalPage);
1628 req->data.pageData[0] = ptr.p->m_real_page_i;
1630 #if ERROR_INSERT_CODE
1631 if (ptr.p->m_state & Page_entry::LOCKED)
1633 sendSignalWithDelay(NDBFS_REF, GSN_FSWRITEREQ, signal,
1634 3000, FsReadWriteReq::FixedLength + 1);
1635 ndbout_c(
"pageout locked (3s)");
1640 if (!ERROR_INSERTED(11008))
1642 sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal,
1643 FsReadWriteReq::FixedLength + 1, JBA);
1648 Pgman::execFSWRITECONF(
Signal* signal)
1653 m_page_entry_pool.
getPtr(ptr, conf->userPointer);
1655 fswriteconf(signal, ptr);
1660 Pgman::execFSWRITEREF(
Signal* signal)
1663 SimulatedBlock::execFSWRITEREF(signal);
1682 Uint32 req_flags = page_req.m_flags;
1684 if (req_flags & Page_request::EMPTY_PAGE)
1690 Page_state state = ptr.p->m_state;
1691 bool is_new = (state == 0);
1692 bool busy_count =
false;
1694 if (req_flags & Page_request::LOCK_PAGE)
1697 state |= Page_entry::LOCKED;
1700 if (req_flags & Page_request::ALLOC_REQ)
1704 else if (req_flags & Page_request::COMMIT_REQ)
1707 state |= Page_entry::BUSY;
1709 else if ((req_flags & Page_request::OP_MASK) != ZREAD)
1714 const Page_state LOCKED = Page_entry::LOCKED | Page_entry::MAPPED;
1715 if ((state & LOCKED) == LOCKED &&
1716 ! (req_flags & Page_request::UNLOCK_PAGE))
1718 ptr.p->m_state |= (req_flags & DIRTY_FLAGS ? Page_entry::DIRTY : 0);
1719 m_stats.m_page_requests_direct_return++;
1720 if (ptr.p->m_copy_page_i != RNIL)
1722 D(
"<get_page: immediate copy_page");
1723 return ptr.p->m_copy_page_i;
1726 D(
"<get_page: immediate locked");
1727 return ptr.p->m_real_page_i;
1730 bool only_request = ptr.p->m_requests.isEmpty();
1732 if (req_flags & Page_request::DELAY_REQ)
1735 only_request =
false;
1739 state & Page_entry::MAPPED)
1741 if (! (state & Page_entry::PAGEOUT))
1743 if (req_flags & DIRTY_FLAGS)
1744 state |= Page_entry::DIRTY;
1746 ptr.p->m_busy_count += busy_count;
1747 set_page_state(ptr, state);
1749 D(
"<get_page: immediate");
1751 ndbrequire(ptr.p->m_real_page_i != RNIL);
1752 m_stats.m_page_requests_direct_return++;
1753 return ptr.p->m_real_page_i;
1757 if (! (req_flags & (Page_request::LOCK_PAGE | Page_request::UNLOCK_PAGE)))
1759 ndbrequire(! (state & Page_entry::LOCKED));
1764 if ((state & Page_entry::MAPPED) && ! (state & Page_entry::PAGEOUT))
1765 m_stats.m_page_requests_wait_q++;
1767 m_stats.m_page_requests_wait_io++;
1771 Local_page_request_list req_list(m_page_request_pool, ptr.p->m_requests);
1772 if (! (req_flags & Page_request::ALLOC_REQ))
1773 req_list.seizeLast(req_ptr);
1775 req_list.seizeFirst(req_ptr);
1778 if (req_ptr.i == RNIL)
1782 release_page_entry(ptr);
1784 D(
"<get_page: error out of requests");
1788 req_ptr.p->m_block = page_req.m_block;
1789 req_ptr.p->m_flags = page_req.m_flags;
1790 req_ptr.p->m_callback = page_req.m_callback;
1792 req_ptr.p->m_delay_until_time = page_req.m_delay_until_time;
1795 state |= Page_entry::REQUEST;
1796 if (only_request && (req_flags & Page_request::EMPTY_PAGE))
1798 state |= Page_entry::EMPTY;
1801 if (req_flags & Page_request::UNLOCK_PAGE)
1806 ptr.p->m_busy_count += busy_count;
1807 ptr.p->m_dirty_count += !!(req_flags & DIRTY_FLAGS);
1808 set_page_state(ptr, state);
1811 D(
"<get_page: queued");
1818 int i = get_page_no_lirs(signal, ptr, page_req);
1819 if (unlikely(i == -1))
1825 Uint32 req_flags = page_req.m_flags;
1826 Page_state state = ptr.p->m_state;
1829 if (! (state & Page_entry::LOCKED) &&
1830 ! (req_flags & Page_request::CORR_REQ))
1833 lirs_reference(ptr);
1840 do_busy_loop(signal,
true);
1850 D(
">update_lsn: block=" << hex << block << dec <<
" lsn=" << lsn);
1853 Page_state state = ptr.p->m_state;
1856 if (state & Page_entry::BUSY)
1858 ndbrequire(ptr.p->m_busy_count != 0);
1859 if (--ptr.p->m_busy_count == 0)
1861 state &= ~ Page_entry::BUSY;
1865 state |= Page_entry::DIRTY;
1866 set_page_state(ptr, state);
1873 Pgman::create_data_file()
1875 File_map::DataBufferIterator it;
1876 if(m_file_map.
first(it))
1880 if(*it.data == RNIL)
1882 *it.data = (1u << 31) | it.pos;
1883 D(
"create_data_file:" << V(it.pos));
1886 }
while(m_file_map.next(it));
1889 Uint32 file_no = m_file_map.
getSize();
1890 Uint32 fd = (1u << 31) | file_no;
1892 if (m_file_map.
append(&fd, 1))
1894 D(
"create_data_file:" << V(file_no));
1897 D(
"create_data_file: RNIL");
1902 Pgman::alloc_data_file(Uint32 file_no)
1904 Uint32 sz = m_file_map.
getSize();
1907 Uint32 len = file_no - sz + 1;
1911 if (! m_file_map.
append(&fd, 1))
1913 D(
"alloc_data_file: RNIL");
1919 File_map::DataBufferIterator it;
1920 m_file_map.
first(it);
1921 m_file_map.next(it, file_no);
1922 if (* it.data != RNIL)
1924 D(
"alloc_data_file: RNIL");
1928 *it.data = (1u << 31) | file_no;
1929 D(
"alloc_data_file:" << V(file_no));
1934 Pgman::map_file_no(Uint32 file_no, Uint32 fd)
1936 File_map::DataBufferIterator it;
1937 m_file_map.
first(it);
1938 m_file_map.next(it, file_no);
1940 assert(*it.data == ((1u << 31) | file_no));
1942 D(
"map_file_no:" << V(file_no) << V(fd));
1946 Pgman::free_data_file(Uint32 file_no, Uint32 fd)
1948 File_map::DataBufferIterator it;
1949 m_file_map.
first(it);
1950 m_file_map.next(it, file_no);
1954 ndbrequire(*it.data == ((1u << 31) | file_no));
1958 ndbrequire(*it.data == fd);
1961 D(
"free_data_file:" << V(file_no) << V(fd));
1965 Pgman::execDATA_FILE_ORD(
Signal* signal)
1970 case DataFileOrd::CreateDataFile:
1971 ret = create_data_file();
1972 ndbrequire(ret == ord->ret);
1974 case DataFileOrd::AllocDataFile:
1975 ret = alloc_data_file(ord->file_no);
1976 ndbrequire(ret == ord->ret);
1978 case DataFileOrd::MapFileNo:
1979 map_file_no(ord->file_no, ord->fd);
1981 case DataFileOrd::FreeDataFile:
1982 free_data_file(ord->file_no, ord->fd);
1996 Page_stack& pl_stack = m_page_stack;
1997 Page_queue& pl_queue = m_page_queue;
1999 Page_state state = ptr.p->m_state;
2000 if (! (state & (Page_entry::PAGEIN | Page_entry::PAGEOUT)))
2002 if (state & Page_entry::ONSTACK)
2005 bool at_bottom = ! pl_stack.hasPrev(ptr);
2006 pl_stack.remove(ptr);
2007 state &= ~ Page_entry::ONSTACK;
2013 if (state & Page_entry::HOT)
2016 state &= ~ Page_entry::HOT;
2020 if (state & Page_entry::ONQUEUE)
2023 pl_queue.remove(ptr);
2024 state &= ~ Page_entry::ONQUEUE;
2027 if (state & Page_entry::BUSY)
2030 state &= ~ Page_entry::BUSY;
2033 if (state & Page_entry::DIRTY)
2036 state &= ~ Page_entry::DIRTY;
2039 if (state & Page_entry::EMPTY)
2042 state &= ~ Page_entry::EMPTY;
2045 if (state & Page_entry::MAPPED)
2048 state &= ~ Page_entry::MAPPED;
2051 if (state & Page_entry::BOUND)
2054 ndbrequire(ptr.p->m_real_page_i != RNIL);
2055 release_cache_page(ptr.p->m_real_page_i);
2056 ptr.p->m_real_page_i = RNIL;
2057 state &= ~ Page_entry::BOUND;
2060 set_page_state(ptr, state);
2061 release_page_entry(ptr);
2070 Pgman::execRELEASE_PAGES_REQ(
Signal* signal)
2073 const Uint32 senderData = req->senderData;
2074 const Uint32 senderRef = req->senderRef;
2075 const Uint32 requestType = req->requestType;
2076 const Uint32
bucket = req->requestData;
2077 ndbrequire(req->requestType == ReleasePagesReq::RT_RELEASE_UNLOCKED);
2079 Page_hashlist& pl_hash = m_page_hashlist;
2080 Page_hashlist::Iterator iter;
2081 pl_hash.
next(bucket, iter);
2084 while (iter.curr.i != RNIL && (loop++ < 8 || iter.bucket == bucket))
2088 if (!(ptr.p->m_state & Page_entry::LOCKED) &&
2089 (ptr.p->m_state & Page_entry::BOUND) &&
2090 (ptr.p->m_state & Page_entry::MAPPED))
2093 D(ptr <<
": release");
2094 ndbrequire(!(ptr.p->m_state & Page_entry::REQUEST));
2095 ndbrequire(!(ptr.p->m_state & Page_entry::EMPTY));
2096 ndbrequire(!(ptr.p->m_state & Page_entry::DIRTY));
2097 ndbrequire(!(ptr.p->m_state & Page_entry::BUSY));
2098 ndbrequire(!(ptr.p->m_state & Page_entry::PAGEIN));
2099 ndbrequire(!(ptr.p->m_state & Page_entry::PAGEOUT));
2100 ndbrequire(!(ptr.p->m_state & Page_entry::LOGSYNC));
2106 if (iter.curr.i != RNIL) {
2108 ndbassert(iter.bucket > bucket);
2110 req->senderData = senderData;
2111 req->senderRef = senderRef;
2112 req->requestType = requestType;
2113 req->requestData = iter.bucket;
2114 sendSignal(reference(), GSN_RELEASE_PAGES_REQ,
2115 signal, ReleasePagesReq::SignalLength, JBB);
2120 conf->senderData = senderData;
2121 conf->senderRef = reference();
2122 sendSignal(senderRef, GSN_RELEASE_PAGES_CONF,
2123 signal, ReleasePagesConf::SignalLength, JBB);
2128 #include <PgmanProxy.hpp>
2133 m_block = numberToBlock(block->number(), block->instance());
2135 if (pgman->isNdbMtLqh() && pgman->instance() == 0) {
2140 m_pgman = (
Pgman*)pgman;
2147 if (m_pgman_proxy != 0) {
2148 return m_pgman_proxy->get_page(*
this, signal, req, flags);
2152 Uint32 file_no = req.m_page.m_file_no;
2153 Uint32 page_no = req.m_page.m_page_no;
2155 D(
"get_page" << V(file_no) << V(page_no) << hex << V(flags));
2162 bool ok = m_pgman->get_page_entry(entry_ptr, file_no, page_no);
2168 Pgman::Page_request page_req;
2169 page_req.m_block = m_block;
2170 page_req.m_flags =
flags;
2171 page_req.m_callback = req.m_callback;
2173 page_req.m_delay_until_time = req.m_delay_until_time;
2176 int i = m_pgman->get_page(signal, entry_ptr, page_req);
2180 m_pgman->m_global_page_pool.
getPtr(m_ptr, (Uint32)i);
2186 Page_cache_client::update_lsn(
Local_key key, Uint64 lsn)
2188 if (m_pgman_proxy != 0) {
2189 m_pgman_proxy->update_lsn(*
this, key, lsn);
2194 Uint32 file_no = key.m_file_no;
2195 Uint32 page_no = key.m_page_no;
2197 D(
"update_lsn" << V(file_no) << V(page_no) << V(lsn));
2199 bool found = m_pgman->find_page_entry(entry_ptr, file_no, page_no);
2202 m_pgman->update_lsn(entry_ptr, m_block, lsn);
2208 if (m_pgman_proxy != 0) {
2209 return m_pgman_proxy->drop_page(*
this, key, page_id);
2213 Uint32 file_no = key.m_file_no;
2214 Uint32 page_no = key.m_page_no;
2216 D(
"drop_page" << V(file_no) << V(page_no));
2218 bool found = m_pgman->find_page_entry(entry_ptr, file_no, page_no);
2220 assert(entry_ptr.p->m_real_page_i == page_id);
2222 return m_pgman->drop_page(entry_ptr);
2228 if (m_pgman_proxy != 0) {
2229 return m_pgman_proxy->create_data_file(signal);
2231 return m_pgman->create_data_file();
2237 if (m_pgman_proxy != 0) {
2238 return m_pgman_proxy->alloc_data_file(signal, file_no);
2240 return m_pgman->alloc_data_file(file_no);
2246 if (m_pgman_proxy != 0) {
2247 m_pgman_proxy->map_file_no(signal, file_no, fd);
2250 m_pgman->map_file_no(file_no, fd);
2256 if (m_pgman_proxy != 0) {
2257 m_pgman_proxy->free_data_file(signal, file_no, fd);
2260 m_pgman->free_data_file(file_no, fd);
2270 Page_stack& pl_stack = m_page_stack;
2272 Uint32 ptrI = ptr.i;
2273 Page_state state = ptr.p->m_state;
2275 bool has_req = state & Page_entry::REQUEST;
2276 bool has_req2 = ! ptr.p->m_requests.isEmpty();
2277 ndbrequire(has_req == has_req2 || dump_page_lists(ptrI));
2279 bool is_bound = state & Page_entry::BOUND;
2280 bool is_bound2 = ptr.p->m_real_page_i != RNIL;
2281 ndbrequire(is_bound == is_bound2 || dump_page_lists(ptrI));
2283 bool is_mapped = state & Page_entry::MAPPED;
2285 ndbrequire(! is_mapped || is_bound || dump_page_lists(ptrI));
2287 ndbrequire(! is_bound || is_mapped || has_req || dump_page_lists(ptrI));
2289 bool on_stack = state & Page_entry::ONSTACK;
2290 bool is_hot = state & Page_entry::HOT;
2292 ndbrequire(! is_hot || on_stack || dump_page_lists(ptrI));
2295 bool at_bottom = on_stack && ! pl_stack.hasPrev(ptr);
2296 ndbrequire(! at_bottom || is_hot || dump_page_lists(ptrI));
2298 bool on_queue = state & Page_entry::ONQUEUE;
2300 ndbrequire(! is_hot || ! on_queue || dump_page_lists(ptrI));
2302 bool is_locked = state & Page_entry::LOCKED;
2303 bool on_queue2 = ! is_locked && ! is_hot && is_bound;
2304 ndbrequire(on_queue == on_queue2 || dump_page_lists(ptrI));
2307 bool to_queue = ! is_locked && ! is_hot && ! is_bound && has_req;
2310 bool to_release = (state == 0);
2313 bool is_lirs = on_stack || to_queue || on_queue;
2314 ndbrequire(to_release || is_locked == ! is_lirs || dump_page_lists(ptrI));
2316 bool pagein = state & Page_entry::PAGEIN;
2317 bool pageout = state & Page_entry::PAGEOUT;
2319 ndbrequire(! pagein || ! pageout || dump_page_lists(ptrI));
2321 Uint32 no = get_sublist_no(state);
2323 case Page_entry::SL_BIND:
2324 ndbrequire((! pagein && ! pageout) || dump_page_lists(ptrI));
2326 case Page_entry::SL_MAP:
2327 ndbrequire((! pagein && ! pageout) || dump_page_lists(ptrI));
2329 case Page_entry::SL_MAP_IO:
2330 ndbrequire((pagein && ! pageout) || dump_page_lists(ptrI));
2332 case Page_entry::SL_CALLBACK:
2333 ndbrequire((! pagein && ! pageout) || dump_page_lists(ptrI));
2335 case Page_entry::SL_CALLBACK_IO:
2336 ndbrequire((! pagein && pageout) || dump_page_lists(ptrI));
2338 case Page_entry::SL_BUSY:
2340 case Page_entry::SL_LOCKED:
2342 case Page_entry::SL_IDLE:
2344 case Page_entry::SL_OTHER:
2347 ndbrequire(to_release || dump_page_lists(ptrI));
2350 ndbrequire(
false || dump_page_lists(ptrI));
2356 Pgman::verify_page_lists()
2359 const Param& param = m_param;
2360 Page_hashlist& pl_hash = m_page_hashlist;
2361 Page_stack& pl_stack = m_page_stack;
2362 Page_queue& pl_queue = m_page_queue;
2365 Uint32 is_locked = 0;
2366 Uint32 is_bound = 0;
2367 Uint32 is_mapped = 0;
2369 Uint32 on_stack = 0;
2370 Uint32 on_queue = 0;
2371 Uint32 to_queue = 0;
2373 Page_hashlist::Iterator iter;
2374 pl_hash.next(0, iter);
2375 while (iter.curr.i != RNIL)
2378 Page_state state = ptr.p->m_state;
2380 ndbrequire(state != 0);
2381 verify_page_entry(ptr);
2383 if (state & Page_entry::LOCKED)
2385 if (state & Page_entry::BOUND)
2387 if (state & Page_entry::MAPPED)
2389 if (state & Page_entry::HOT)
2391 if (state & Page_entry::ONSTACK)
2393 if (state & Page_entry::ONQUEUE)
2395 if (! (state & Page_entry::LOCKED) &&
2396 ! (state & Page_entry::HOT) &&
2397 (state & Page_entry::REQUEST) &&
2398 ! (state & Page_entry::BOUND))
2403 for (pl_stack.first(ptr); ptr.i != RNIL; pl_stack.next(ptr))
2405 Page_state state = ptr.p->m_state;
2406 ndbrequire(state & Page_entry::ONSTACK || dump_page_lists(ptr.i));
2407 if (! pl_stack.hasPrev(ptr))
2409 ndbrequire(state & Page_entry::HOT || dump_page_lists(ptr.i));
2413 for (pl_queue.first(ptr); ptr.i != RNIL; pl_queue.next(ptr))
2415 Page_state state = ptr.p->m_state;
2416 ndbrequire(state & Page_entry::ONQUEUE || dump_page_lists(ptr.i));
2417 ndbrequire(state & Page_entry::BOUND || dump_page_lists(ptr.i));
2418 ndbrequire(! (state & Page_entry::HOT) || dump_page_lists(ptr.i));
2421 ndbrequire(is_bound == stats.m_num_pages || dump_page_lists());
2422 ndbrequire(is_hot == stats.m_num_hot_pages || dump_page_lists());
2423 ndbrequire(on_stack == pl_stack.count() || dump_page_lists());
2424 ndbrequire(on_queue == pl_queue.count() || dump_page_lists());
2427 Uint32 entry_count = 0;
2428 char sublist_info[200] =
"";
2429 for (k = 0; k < Page_entry::SUBLIST_COUNT; k++)
2431 const Page_sublist& pl = *m_page_sublist[k];
2432 for (pl.first(ptr); ptr.i != RNIL; pl.next(ptr))
2433 ndbrequire(get_sublist_no(ptr.p->m_state) == k || dump_page_lists(ptr.i));
2434 entry_count += pl.count();
2435 sprintf(sublist_info + strlen(sublist_info),
2436 " %s:%u", get_sublist_name(k), pl.count());
2438 ndbrequire(entry_count == pl_hash.count() || dump_page_lists());
2441 char hit_pct_str[20];
2442 if (stats.m_page_hits + stats.m_page_faults != 0)
2443 hit_pct = 10000 * stats.m_page_hits /
2444 (stats.m_page_hits + stats.m_page_faults);
2445 sprintf(hit_pct_str,
"%u.%02u", hit_pct / 100, hit_pct % 100);
2448 <<
" stats:" << m_stats_loop_on
2449 <<
" busy:" << m_busy_loop_on
2450 <<
" cleanup:" << m_cleanup_loop_on
2451 <<
" lcp:" << Uint32(m_lcp_state));
2454 <<
" entries:" << pl_hash.count()
2455 <<
" pages:" << stats.m_num_pages <<
"/" << param.m_max_pages
2456 <<
" mapped:" << is_mapped
2457 <<
" hot:" << is_hot
2458 <<
" io:" << stats.m_current_io_waits <<
"/" << param.m_max_io_waits
2459 <<
" hit pct:" << hit_pct_str);
2462 <<
" locked:" << is_locked
2463 <<
" stack:" << pl_stack.count()
2464 <<
" queue:" << pl_queue.count()
2465 <<
" to queue:" << to_queue);
2473 Page_sublist& pl_bind = *m_page_sublist[Page_entry::SL_BIND];
2474 Page_sublist& pl_map = *m_page_sublist[Page_entry::SL_MAP];
2475 Page_sublist& pl_callback = *m_page_sublist[Page_entry::SL_CALLBACK];
2477 if (! pl_bind.isEmpty() || ! pl_map.isEmpty() || ! pl_callback.isEmpty())
2479 ndbrequire(m_busy_loop_on || dump_page_lists());
2481 verify_page_lists();
2485 Pgman::dump_page_lists(Uint32 ptrI)
2488 debugOut <<
"PGMAN: page list dump" << endl;
2490 debugOut <<
"PGMAN: error on PE [" << ptrI <<
"]" <<
"\n";
2492 Page_stack& pl_stack = m_page_stack;
2493 Page_queue& pl_queue = m_page_queue;
2497 debugOut <<
"stack:" <<
"\n";
2499 for (pl_stack.first(ptr); ptr.i != RNIL; pl_stack.next(ptr))
2500 debugOut << n++ <<
" " << ptr <<
"\n";
2502 debugOut <<
"queue:" <<
"\n";
2504 for (pl_queue.first(ptr); ptr.i != RNIL; pl_queue.next(ptr))
2505 debugOut << n++ <<
" " << ptr <<
"\n";
2508 for (k = 0; k < Page_entry::SUBLIST_COUNT; k++)
2510 debugOut << get_sublist_name(k) <<
":" <<
"\n";
2511 const Page_sublist& pl = *m_page_sublist[k];
2513 for (pl.first(ptr); ptr.i != RNIL; pl.next(ptr))
2514 debugOut << n++ <<
" " << ptr <<
"\n";
2517 debugOut.flushline();
2524 Pgman::get_sublist_name(Uint32 list_no)
2527 case Page_entry::SL_BIND:
2529 case Page_entry::SL_MAP:
2531 case Page_entry::SL_MAP_IO:
2533 case Page_entry::SL_CALLBACK:
2535 case Page_entry::SL_CALLBACK_IO:
2537 case Page_entry::SL_BUSY:
2539 case Page_entry::SL_LOCKED:
2541 case Page_entry::SL_IDLE:
2543 case Page_entry::SL_OTHER:
2550 operator<<(NdbOut& out, Ptr<Pgman::Page_request> ptr)
2552 const Pgman::Page_request& pr = *ptr.p;
2555 out <<
" [" << dec << ptr.i <<
"]";
2556 out <<
" block=" << hex << pr.m_block;
2557 out <<
" flags=" << hex << pr.m_flags;
2558 out <<
"," << dec << (pr.m_flags & Pgman::Page_request::OP_MASK);
2560 if (pr.m_flags & Pgman::Page_request::LOCK_PAGE)
2561 out <<
",lock_page";
2562 if (pr.m_flags & Pgman::Page_request::EMPTY_PAGE)
2563 out <<
",empty_page";
2564 if (pr.m_flags & Pgman::Page_request::ALLOC_REQ)
2565 out <<
",alloc_req";
2566 if (pr.m_flags & Pgman::Page_request::COMMIT_REQ)
2567 out <<
",commit_req";
2568 if (pr.m_flags & Pgman::Page_request::DIRTY_REQ)
2569 out <<
",dirty_req";
2570 if (pr.m_flags & Pgman::Page_request::CORR_REQ)
2577 operator<<(NdbOut& out, Ptr<Pgman::Page_entry> ptr)
2579 const Pgman::Page_entry pe = *ptr.p;
2580 Uint32 list_no = Pgman::get_sublist_no(pe.m_state);
2581 out <<
"PE [" << dec << ptr.i <<
"]";
2582 out <<
" state=" << hex << pe.m_state;
2584 if (pe.m_state & Pgman::Page_entry::REQUEST)
2586 if (pe.m_state & Pgman::Page_entry::EMPTY)
2588 if (pe.m_state & Pgman::Page_entry::BOUND)
2590 if (pe.m_state & Pgman::Page_entry::MAPPED)
2592 if (pe.m_state & Pgman::Page_entry::DIRTY)
2594 if (pe.m_state & Pgman::Page_entry::USED)
2596 if (pe.m_state & Pgman::Page_entry::BUSY)
2598 if (pe.m_state & Pgman::Page_entry::LOCKED)
2600 if (pe.m_state & Pgman::Page_entry::PAGEIN)
2602 if (pe.m_state & Pgman::Page_entry::PAGEOUT)
2604 if (pe.m_state & Pgman::Page_entry::LOGSYNC)
2606 if (pe.m_state & Pgman::Page_entry::LCP)
2608 if (pe.m_state & Pgman::Page_entry::HOT)
2610 if (pe.m_state & Pgman::Page_entry::ONSTACK)
2612 if (pe.m_state & Pgman::Page_entry::ONQUEUE)
2616 if (list_no == ZNIL)
2620 out << dec << list_no;
2621 out <<
"," << Pgman::get_sublist_name(list_no);
2623 out <<
" diskpage=" << dec << pe.m_file_no <<
"," << pe.m_page_no;
2624 if (pe.m_real_page_i == RNIL)
2625 out <<
" realpage=RNIL";
2627 out <<
" realpage=" << dec << pe.m_real_page_i;
2629 if (pe.m_state & Pgman::Page_entry::MAPPED) {
2631 pe.m_this->m_global_page_pool.getPtr(gptr, pe.m_real_page_i);
2632 Uint32 hash_result[4];
2634 md5_hash(hash_result,
2635 (Uint64*)gptr.p->data,
sizeof(gptr.p->data)/
sizeof(Uint32));
2636 out.print(
" md5=%08x%08x%08x%08x",
2637 hash_result[0], hash_result[1],
2638 hash_result[2], hash_result[3]);
2642 out <<
" lsn=" << dec << pe.m_lsn;
2643 out <<
" busy_count=" << dec << pe.m_busy_count;
2654 req_list(ptr.p->m_this->m_page_request_pool, ptr.p->m_requests);
2655 if (! req_list.isEmpty())
2659 for (req_list.first(req_ptr); req_ptr.i != RNIL; req_list.next(req_ptr))
2661 out <<
" " << req_ptr;
2670 Pgman::execDUMP_STATE_ORD(
Signal* signal)
2673 Page_hashlist& pl_hash = m_page_hashlist;
2675 if (signal->theData[0] == 11000 && signal->getLength() == 2)
2678 Uint32 flag = signal->theData[1];
2679 debugFlag = flag & 1;
2680 debugSummaryFlag = flag & 2;
2684 if (signal->theData[0] == 11001)
2688 if (signal->getLength() > 1)
2689 list = signal->theData[1];
2691 Page_sublist& pl = *m_page_sublist[list];
2694 for (pl.first(ptr); ptr.i != RNIL; pl.next(ptr))
2696 ndbout << ptr << endl;
2697 infoEvent(
" PE [ file: %d page: %d ] state: %x lsn: %lld lcp: %d busy: %d req-list: %d",
2698 ptr.p->m_file_no, ptr.p->m_page_no,
2699 ptr.p->m_state, ptr.p->m_lsn, ptr.p->m_last_lcp,
2700 ptr.p->m_busy_count,
2701 !ptr.p->m_requests.isEmpty());
2705 if (signal->theData[0] == 11002 && signal->getLength() == 3)
2708 key.m_file_no = signal->theData[1];
2709 key.m_page_no = signal->theData[2];
2712 if (pl_hash.find(ptr, key))
2714 ndbout <<
"pageout " << ptr << endl;
2717 ptr.p->m_real_page_i,
2718 ptr.p->m_dirty_count);
2719 pageout(signal, ptr);
2724 if (signal->theData[0] == 11003)
2727 verify_page_lists();
2730 ndbout <<
"Only in VM_TRACE builds" << endl;
2734 if (signal->theData[0] == 11004)
2736 ndbout <<
"Dump LCP bucket m_lcp_outstanding: " << m_lcp_outstanding;
2737 if (m_lcp_curr_bucket != ~(Uint32)0)
2739 Page_hashlist::Iterator iter;
2740 pl_hash.next(m_lcp_curr_bucket, iter);
2742 ndbout_c(
" %d", m_lcp_curr_bucket);
2744 while (iter.curr.i != RNIL && iter.bucket == m_lcp_curr_bucket)
2747 ndbout << ptr << endl;
2751 ndbout_c(
"-- done");
2759 if (signal->theData[0] == 11005)
2761 g_dbg_lcp = !g_dbg_lcp;
2764 if (signal->theData[0] == 11006)
2766 SET_ERROR_INSERT_VALUE(11006);
2769 if (signal->theData[0] == 11007)
2771 SET_ERROR_INSERT_VALUE(11007);
2774 if (signal->theData[0] == 11008)
2776 SET_ERROR_INSERT_VALUE(11008);
2779 if (signal->theData[0] == 11009)
2781 SET_ERROR_INSERT_VALUE(11009);
2786 Pgman::execDBINFO_SCANREQ(
Signal *signal)
2792 switch(req.tableId) {
2793 case Ndbinfo::DISKPAGEBUFFER_TABLEID:
2797 row.write_uint32(getOwnNodeId());
2798 row.write_uint32(instance());
2799 row.write_uint64(m_stats.m_pages_written);
2800 row.write_uint64(m_stats.m_pages_written_lcp);
2801 row.write_uint64(m_stats.m_pages_read);
2802 row.write_uint64(m_stats.m_log_waits);
2803 row.write_uint64(m_stats.m_page_requests_direct_return);
2804 row.write_uint64(m_stats.m_page_requests_wait_q);
2805 row.write_uint64(m_stats.m_page_requests_wait_io);
2807 ndbinfo_send_row(signal, req, row, rl);
2812 ndbinfo_send_scan_conf(signal, req, rl);