/* Copyright (c) 2003-2005 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include void print_help(){ ndbout << "The test menu" << endl; ndbout << "1 - Sending of long signals w/ segmented sections" << endl; ndbout << "2 - As 1 but using receiver group" << endl; ndbout << "3 - Sending of long signals w/ linear sections" << endl; ndbout << "4 - As 3 but using receiver group" << endl; ndbout << "5 - Sending of manually fragmented signals w/ segmented sections" << endl; ndbout << "6 - As 5 but using receiver group" << endl; ndbout << "7 - Sending of manually fragmented signals w/ linear sections" << endl; ndbout << "8 - As but using receiver group" << endl; ndbout << "9 - Sending of CONTINUEB fragmented signals w/ segmented sections" << endl; ndbout << "10 - As 9 but using receiver group" << endl; ndbout << "11 - Sending of CONTINUEB fragmented signals w/ linear sections" << endl; ndbout << "12 - As but using receiver group" << endl; ndbout << "13 - Send 100 * 1000 25 len signals wo/ sections" << endl; ndbout << "r - Recive signal from anyone" << endl; ndbout << "a - Run tests 1 - 12 with variable sizes - 10 loops" << endl; ndbout << "b - Run tests 1 - 12 with variable sizes - 100 loops" << endl; ndbout << "c - Run tests 1 - 12 with variable sizes - 1000k loops" << endl; } void runTest(SignalSender &, Uint32 i, bool verbose); static int randRange(Uint32 min, Uint32 max){ float r = rand(); float f = (max - min + 1); float d = (float)RAND_MAX + 1.0; return min + (int)(f * r / d); } static int randRange(const Uint32 odds[], Uint32 count){ Uint32 val = randRange((Uint32)0, 100); Uint32 i = 0; Uint32 sum = 0; while(sum <= val && i < count){ sum += odds[i]; i++; } return i - 1; } int main(void){ srand(NdbTick_CurrentMillisecond()); #if 0 for(int i = 0; i<100; i++) ndbout_c("randRange(0, 3) = %d", randRange(0, 3)); return 0; #endif SignalSender ss; ndbout << "Connecting..."; if(!ss.connect(30)){ ndbout << "failed" << endl << "Exiting" << endl; return 0; } ndbout << "done" << endl; ndbout_c("Connected as block=%d node=%d", refToBlock(ss.getOwnRef()), refToNode(ss.getOwnRef())); Uint32 data[25]; Uint32 sec0[70]; Uint32 sec1[123]; Uint32 sec2[10]; data[0] = ss.getOwnRef(); data[1] = 1; data[2] = 76; data[3] = 1; data[4] = 1; data[5] = 70; data[6] = 123; data[7] = 10; const Uint32 theDataLen = 18; for(Uint32 i = 0; i<70; i++) sec0[i] = i; for(Uint32 i = 0; i<123; i++) sec1[i] = 70+i; for(Uint32 i = 0; i<10; i++) sec2[i] = (i + 1)*(i + 1); SimpleSignal signal1; signal1.set(ss, 0, CMVMI, GSN_TESTSIG, theDataLen + 2); signal1.header.m_noOfSections = 1; signal1.header.m_fragmentInfo = 1; memcpy(&signal1.theData[0], data, 4 * theDataLen ); signal1.theData[theDataLen + 0] = 0; signal1.theData[theDataLen + 1] = 7; // FragmentId signal1.ptr[0].sz = 60; signal1.ptr[0].p = &sec0[0]; SimpleSignal signal2; Uint32 idx = 0; memcpy(&signal2.theData[0], data, 4 * theDataLen ); signal2.theData[theDataLen + idx] = 0; idx++; signal2.theData[theDataLen + idx] = 1; idx++; //signal2.theData[theDataLen + idx] = 2; idx++; signal2.theData[theDataLen + idx] = 7; idx++; // FragmentId signal2.set(ss, 0, CMVMI, GSN_TESTSIG, theDataLen + idx); signal2.header.m_fragmentInfo = 3; signal2.header.m_noOfSections = idx - 1; signal2.ptr[0].sz = 10; signal2.ptr[0].p = &sec0[60]; signal2.ptr[1].sz = 123; signal2.ptr[1].p = &sec1[0]; signal2.ptr[2].sz = 10; signal2.ptr[2].p = &sec2[0]; char * buf; while((buf = readline("Enter command: "))){ add_history(buf); data[1] = atoi(buf); if(strcmp(buf, "r") == 0){ SimpleSignal * ret1 = ss.waitFor(); (* ret1).print(); delete ret1; continue; } if(strcmp(buf, "a") == 0){ runTest(ss, 10, true); print_help(); continue; } if(strcmp(buf, "b") == 0){ runTest(ss, 100, false); print_help(); continue; } if(strcmp(buf, "c") == 0){ runTest(ss, 1000000, false); print_help(); continue; } if(data[1] >= 1 && data[1] <= 12){ Uint32 nodeId = ss.getAliveNode(); ndbout_c("Sending 2 fragmented to node %d", nodeId); ss.sendSignal(nodeId, &signal1); ss.sendSignal(nodeId, &signal2); if(data[1] >= 5){ continue; } ndbout_c("Waiting for signal from %d", nodeId); SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId); (* ret1).print(); Uint32 count = ret1->theData[4] - 1; delete ret1; while(count > 0){ ndbout << "Waiting for " << count << " signals... "; SimpleSignal * ret1 = ss.waitFor(); ndbout_c("received from node %d", refToNode(ret1->header.theSendersBlockRef)); (* ret1).print(); delete ret1; count--; } } else if (data[1] == 13) { const Uint32 count = 3500; const Uint32 loop = 1000; signal1.set(ss, 0, CMVMI, GSN_TESTSIG, 25); signal1.header.m_fragmentInfo = 0; signal1.header.m_noOfSections = 0; signal1.theData[1] = 14; signal1.theData[3] = 0; // Print signal1.theData[8] = count; signal1.theData[9] = loop; Uint32 nodeId = ss.getAliveNode(); ndbout_c("Sending 25 len signal to node %d", nodeId); ss.sendSignal(nodeId, &signal1); Uint32 total; { SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId); ndbout_c("received from node %d", refToNode(ret1->header.theSendersBlockRef)); total = ret1->theData[10] - 1; delete ret1; } do { ndbout << "Waiting for " << total << " signals... " << flush; SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId); ndbout_c("received from node %d", refToNode(ret1->header.theSendersBlockRef)); delete ret1; total --; } while(total > 0); } else { print_help(); } } ndbout << "Exiting" << endl; }; void runTest(SignalSender & ss, Uint32 count, bool verbose){ SimpleSignal sig; Uint32 sec0[256]; Uint32 sec1[256]; Uint32 sec2[256]; for(Uint32 i = 0; i<256; i++){ sec0[i] = i; sec1[i] = i + i; sec2[i] = i * i; } sig.theData[0] = ss.getOwnRef(); sig.theData[1] = 1; // TestType sig.theData[2] = 128; // FragSize sig.theData[3] = 0; // Print sig.theData[4] = 1; // RetCount sig.ptr[0].p = &sec0[0]; sig.ptr[1].p = &sec1[0]; sig.ptr[2].p = &sec2[0]; for(unsigned loop = 0; loop < count; loop++){ const Uint32 odds[] = { 5, 40, 30, 25 }; const Uint32 secs = randRange(odds, 4); sig.ptr[0].sz = randRange(1, 256); sig.ptr[1].sz = randRange(1, 256); sig.ptr[2].sz = randRange(1, 256); sig.header.m_noOfSections = secs; const Uint32 len = 5 + (secs > 0 ? 1 : 0) * (25 - 5 - 7); sig.set(ss, 0, CMVMI, GSN_TESTSIG, len); ndbout << "Loop " << loop << " #secs = " << secs << " sizes = [ "; unsigned min = 256; unsigned max = 0; unsigned sum = 0; for(unsigned i = 0; i sz ? max : sz); sum += sz; sig.theData[5+i] = sz; } ndbout_c("] len = %d", len); for(int test = 1; test <= 12; test++){ sig.theData[1] = test; Uint32 nodeId = ss.getAliveNode(); if(verbose){ ndbout << " Test " << test << " node " << nodeId << "..."; fflush(stdout); } SendStatus r = ss.sendSignal(nodeId, &sig); assert(r == SEND_OK); if(test < 5){ SimpleSignal * ret1 = ss.waitFor((Uint16)nodeId); Uint32 count = ret1->theData[4] - 1; delete ret1; while(count > 0){ SimpleSignal * ret1 = ss.waitFor(); delete ret1; count--; } if(verbose) ndbout << "done" << endl; } else { Uint32 nodes = ss.getNoOfConnectedNodes(); Uint32 sum2 = 0; if((test & 1) == 1) nodes = 1; while(nodes > 0){ SimpleSignal * ret = ss.waitFor(); if(ret->header.m_fragmentInfo == 0){ for(Uint32 i = 0; iheader.m_noOfSections; i++) sum2 += ret->ptr[i].sz; } else { for(Uint32 i = 0; iheader.m_noOfSections; i++) if(ret->theData[i] != 3) sum2 += ret->ptr[i].sz; } if(ret->header.m_fragmentInfo == 0 || ret->header.m_fragmentInfo == 3){ nodes--; } delete ret; } if(verbose) ndbout_c("done sum=%d sum2=%d", sum, sum2); } } } }