11/*
2- Copyright (c) 2003, 2014 , Oracle and/or its affiliates. All rights reserved.
2+ Copyright (c) 2003, 2015 , Oracle and/or its affiliates. All rights reserved.
33
44 This program is free software; you can redistribute it and/or modify
55 it under the terms of the GNU General Public License as published by
@@ -452,6 +452,10 @@ void Dbdict::execCONTINUEB(Signal* signal)
452452 sendSignal(calcDictBlockRef(c_masterNodeId), GSN_GET_TABINFOREQ, signal,
453453 GetTabInfoReq::SignalLength, JBB);
454454 break;
455+ case ZNEXT_GET_TAB_REQ:
456+ jam();
457+ startNextGetTabInfoReq(signal);
458+ break;
455459 default :
456460 ndbrequire(false);
457461 break;
@@ -493,7 +497,7 @@ void Dbdict::packTableIntoPages(Signal* signal)
493497 jam();
494498 sendGET_TABINFOREF(signal, &req_copy,
495499 GetTabInfoRef::TableNotDefined, __LINE__);
496- initRetrieveRecord(0 , 0, 0);
500+ initRetrieveRecord(signal , 0, 0);
497501 return;
498502 }
499503
@@ -513,7 +517,7 @@ void Dbdict::packTableIntoPages(Signal* signal)
513517 // cannot see another uncommitted trans
514518 sendGET_TABINFOREF(signal, &req_copy,
515519 (GetTabInfoRef::ErrorCode)err, __LINE__);
516- initRetrieveRecord(0 , 0, 0);
520+ initRetrieveRecord(signal , 0, 0);
517521 return;
518522 }
519523 }
@@ -541,7 +545,7 @@ void Dbdict::packTableIntoPages(Signal* signal)
541545 jam();
542546 sendGET_TABINFOREF(signal, &req_copy,
543547 GetTabInfoRef::TableNotDefined, __LINE__);
544- initRetrieveRecord(0 , 0, 0);
548+ initRetrieveRecord(signal , 0, 0);
545549 return;
546550 }
547551
@@ -558,7 +562,7 @@ void Dbdict::packTableIntoPages(Signal* signal)
558562 Uint32 dstRef = c_retrieveRecord.blockRef;
559563 sendSignal(dstRef, GSN_GET_TABINFOREF, signal,
560564 GetTabInfoRef::SignalLength, JBB);
561- initRetrieveRecord(0 ,0,0);
565+ initRetrieveRecord(signal ,0,0);
562566 return;
563567 }
564568 break;
@@ -1984,6 +1988,7 @@ Dbdict::Dbdict(Block_context& ctx):
19841988 c_attributeRecordHash(c_attributeRecordPool),
19851989 c_obj_name_hash(c_obj_pool),
19861990 c_obj_id_hash(c_obj_pool),
1991+ c_gettabinforeq_q(*this),
19871992 c_schemaOpHash(c_schemaOpPool),
19881993 c_schemaTransHash(c_schemaTransPool),
19891994 c_schemaTransList(c_schemaTransPool),
@@ -2316,14 +2321,34 @@ void Dbdict::initWriteSchemaRecord()
23162321
23172322void Dbdict::initRetrieveRecord(Signal* signal, Uint32 i, Uint32 returnCode)
23182323{
2319- c_retrieveRecord.busyState = false ;
2324+ jam() ;
23202325 c_retrieveRecord.blockRef = 0;
23212326 c_retrieveRecord.m_senderData = RNIL;
23222327 c_retrieveRecord.tableId = RNIL;
23232328 c_retrieveRecord.currentSent = 0;
23242329 c_retrieveRecord.retrievedNoOfPages = 0;
23252330 c_retrieveRecord.retrievedNoOfWords = 0;
23262331 c_retrieveRecord.m_useLongSig = false;
2332+
2333+ if (!c_gettabinforeq_q.isEmpty())
2334+ {
2335+ jam();
2336+ ndbrequire(signal != NULL);
2337+
2338+ /* Take a real-time break now, CONTINUEB will
2339+ * start processing the next request.
2340+ * busyState = true will maintain fairness
2341+ */
2342+ signal->theData[0] = ZNEXT_GET_TAB_REQ;
2343+ sendSignal(reference(), GSN_CONTINUEB, signal,
2344+ 1, JBB);
2345+ }
2346+ else
2347+ {
2348+ /* Done */
2349+ c_retrieveRecord.busyState = false;
2350+ }
2351+
23272352}//initRetrieveRecord()
23282353
23292354void Dbdict::initSchemaRecord()
@@ -2831,6 +2856,9 @@ void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
28312856 bat[1].bits.q = ZLOG_SIZE_OF_PAGES_IN_WORDS; // 2**13 = 8192 elements
28322857 bat[1].bits.v = 5; // 32 bits per element
28332858
2859+ /* Initialize Segment Sub pool in GetTabInfoReq queue */
2860+ ndbrequire(c_gettabinforeq_q.init(jamBuffer()));
2861+
28342862 initCommonData();
28352863 initRecords();
28362864
@@ -4195,8 +4223,10 @@ Dbdict::restart_fromWriteSchemaFile(Signal* signal,
41954223}
41964224
41974225void
4198- Dbdict::execGET_TABINFOREF(Signal* signal){
4226+ Dbdict::execGET_TABINFOREF(Signal* signal)
4227+ {
41994228 jamEntry();
4229+
42004230 /**
42014231 * Make copy of 'ref' such that we can build 'req' without overwriting
42024232 * source.
@@ -4208,6 +4238,13 @@ Dbdict::execGET_TABINFOREF(Signal* signal){
42084238 {
42094239 jam();
42104240
4241+ const Uint32 senderRef = ref_copy.senderRef;
4242+ ndbout_c("DICT : GET_TABINFOREF(Busy) Retained for upgrade "
4243+ "compatibility. Sender node : %u block : %u version : %x",
4244+ refToNode(senderRef),
4245+ refToMain(senderRef),
4246+ getNodeInfo(refToNode(senderRef)).m_version);
4247+
42114248 /**
42124249 * Master is busy. Send delayed CONTINUEB to self to add some delay, then
42134250 * send new GET_TABINFOREQ to master.
@@ -10087,85 +10124,66 @@ void Dbdict::execGET_TABINFOREQ(Signal* signal)
1008710124 }
1008810125
1008910126 GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
10090- SectionHandle handle(this, signal);
1009110127
10092- /**
10093- * If I get a GET_TABINFO_REQ from myself
10094- * it's is a one from the time queue
10095- */
10096- bool fromTimeQueue = (signal->senderBlockRef() == reference());
10097-
10098- if (ERROR_INSERTED(6215) && fromTimeQueue == false)
10128+ if (ERROR_INSERTED(6215) &&
10129+ (signal->senderBlockRef() != reference()))
1009910130 {
1010010131 jam();
1010110132 // API tries 100 times and (80/100)^100 is quite small..
1010210133 if (rand() % 100 >= 20)
1010310134 {
1010410135 jam();
10136+ SectionHandle handle(this, signal);
1010510137 releaseSections(handle);
1010610138 sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy, __LINE__);
1010710139 return;
1010810140 }
1010910141 // no CLEAR_ERROR_INSERT_VALUE
1011010142 }
1011110143
10112- if (c_retrieveRecord.busyState && fromTimeQueue == true) {
10113- jam();
10114-
10115- sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 30,
10116- signal->length(),
10117- &handle);
10144+ const bool testRef = (ERROR_INSERTED(6026) &&
10145+ refToMain(signal->senderBlockRef()) == DBDICT &&
10146+ (signal->senderBlockRef() != reference()));
10147+ if (testRef)
10148+ {
10149+ ndbout_c("DICT : ERROR_INSERT(6026) simulating old internal "
10150+ "GET_TABINFOREF");
10151+ CLEAR_ERROR_INSERT_VALUE;
10152+ SectionHandle handle(this, signal);
10153+ releaseSections(handle);
10154+ sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy, __LINE__);
1011810155 return;
10119- }//if
10120-
10121- const Uint32 MAX_WAITERS = (MAX_NDB_NODES*3)/2;
10156+ }
1012210157
10123- // Test sending GET_TABINFOREF to DICT (Bug#14647210).
10124- const bool testRef = refToMain(signal->senderBlockRef()) == DBDICT &&
10125- ERROR_INSERTED_CLEAR(6026);
10126-
10127- if ((c_retrieveRecord.busyState || testRef) && fromTimeQueue == false)
10158+ if (c_retrieveRecord.busyState)
1012810159 {
1012910160 jam();
10161+ NodeInfo sendersNI = getNodeInfo(refToNode(req->senderRef));
10162+ bool internalReq = (sendersNI.m_type == NodeInfo::DB);
1013010163
10131- const Uint32 senderVersion =
10132- getNodeInfo(refToNode(signal->senderBlockRef())).m_version;
10133-
10134- /**
10135- * DBDICT may possibly generate large numbers of signals if many nodes
10136- * are started at the same time, so we do not want to queue those using
10137- * sendSignalWithDelay(). See also Bug#14647210. Signals from other
10138- * blocks we do queue localy, since these blocks may not retry on
10139- * GET_TABINFOREF with error==busy, and since they also should not
10140- * generate large bursts of GET_TABINFOREQ.
10164+ /* Queue request
10165+ * Will be processed later when current requests + queue are completed
1014110166 */
10142- if (c_retrieveRecord.noOfWaiters < MAX_WAITERS &&
10143- (refToMain(signal->senderBlockRef()) != DBDICT ||
10144- !ndbd_dict_get_tabinforef_implemented(senderVersion)))
10167+ if (!c_gettabinforeq_q.tryEnqReq(internalReq,
10168+ signal))
1014510169 {
1014610170 jam();
10147- c_retrieveRecord.noOfWaiters++;
10171+ /**
10172+ * Enqueue failure resulting in Busy signal only allowed for
10173+ * external requests
10174+ */
10175+ ndbrequire(!internalReq);
1014810176
10149- sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 30,
10150- signal->length(),
10151- &handle);
10152- return;
10153- }
10177+ SectionHandle handle(this, signal);
10178+ releaseSections(handle);
1015410179
10155- if (!c_retrieveRecord.busyState)
10156- {
10157- ndbout << "Sending extra TABINFOREF to node"
10158- << refToNode(signal->senderBlockRef()) << endl;
10180+ sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy, __LINE__);
1015910181 }
10160- releaseSections(handle);
10161- sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy, __LINE__);
10182+
1016210183 return;
1016310184 }
1016410185
10165- if(fromTimeQueue){
10166- jam();
10167- c_retrieveRecord.noOfWaiters--;
10168- }
10186+ SectionHandle handle(this, signal);
1016910187
1017010188 const bool useLongSig = (req->requestType & GetTabInfoReq::LongSignalConf);
1017110189 const bool byName = (req->requestType & GetTabInfoReq::RequestByName);
@@ -29878,3 +29896,30 @@ Dbdict::send_event(Signal* signal,
2987829896 signal->theData[4] = refToNode(trans_ptr.p->m_clientRef);
2987929897 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 5, JBB);
2988029898}
29899+
29900+ void
29901+ Dbdict::startNextGetTabInfoReq(Signal* signal)
29902+ {
29903+ jam();
29904+
29905+ /* Retrieve record should be in busy state to block
29906+ * queue-jumpers. We can clear it now as we will
29907+ * execute direct from the head of the queue(s)
29908+ */
29909+ ndbrequire(c_retrieveRecord.busyState);
29910+ ndbrequire(!c_gettabinforeq_q.isEmpty());
29911+
29912+ /* Directly start next queued request
29913+ * Prefer internalQueue, but give externalQueue entries
29914+ * a proportional share to avoid starvation.
29915+ */
29916+ ndbrequire(c_gettabinforeq_q.deqReq(signal));
29917+
29918+ c_retrieveRecord.busyState = false;
29919+
29920+ /* Execute...using EXECUTE_DIRECT to get signal trace */
29921+ EXECUTE_DIRECT(number(),
29922+ GSN_GET_TABINFOREQ,
29923+ signal,
29924+ GetTabInfoReq::SignalLength);
29925+ }
0 commit comments