theLink 10.0
|
The client part of the performance test tool.
usage: perfclient [OPTION]... [ARGUMENT]... This tool is the client part of the performance test toolkit and expect the 'perfserver' as argument. The following tests are defined: --all Do all the following tests. --all-performance Do all tests relevant for performance testing. --all-no-parent Do all the following tests but without parent. --send-nothing Send empty package just to test the service callback. --send The data is send from the client to the server using ... 1. a 1 byte char 2. a 2 byte short 3. a 4 byte integer 4. a 8 byte double 5. a binary of size between 1 and 1000 bytes --send-string Same as '--send' but use 'string-data' only --send-and-wait Same as '--send' but use 'MqSendEND_AND_WAIT' -> DEFAULT --send-and-callback Same as '--send' but use 'MqSendEND_AND_CALLBACK' --send-persistent Use a persistent-transaction together with 'MqSendEND_AND_WAIT' --storage STRING database file, #memdb# or #tmpdb# (default: file) --parent Create and Delete a PARENT-context in a loop --spawn|--thread|--fork choose starter (default: lng-specific) --wrk NUMBER number of parallel workers (default: 1) --child Create and Delete a CHILD-context in a loop --bus or --bfl Create and Delete a MkBufferStreamS or MkBufferListS in a loop --bin/str send ad wait for binary/string data perfclient [ARGUMENT]... syntax: perfclient [OPTION]... @ server [OPTION]... [ARGUMENT] msgque [OPTION]: --help-msgque print msgque specific help perfclient [OPTION]: --num NUMBER number of test-cycles (default: -1) --sec SECONDS seconds per test (default: 2) --timeout-event SECONDS timeout for background wait (default: 3) -h, --help print this help
/** * @file NHI1/example/c/perfclient.c * @brief tag: nhi1-release-250425 * @copyright (C) NHI - #1 - Project - Group * This software has NO permission to copy, * please contact AUTHOR for additional information */ /* LABEL-START */ #define META_FILE_NAME "client.c" /* LABEL-END */ /** \ingroup validation * \defgroup client client * \{ * \brief client \client_desc * * \verbinclude client.help */ #include <limits.h> #include <float.h> #include <unistd.h> #include "common.h" #include "stat.h" #define META_CONTEXT_S mqctx /*****************************************************************************/ /* */ /* main */ /* */ /*****************************************************************************/ static int NUM_DEFAULT=-1, SEC_DEFAULT=2, WRK_DEFAULT=1; static void ClientHelp ( const char * ) __attribute__ ((noreturn)); static char STORAGE_DEFAULT[128]; static int TIMEOUT_EVENT_DEFAULT=3; static MK_I32 callnum = 0; static MK_STRN int2str (MK_I32 i) { static MkThreadLocal char buffer[30]; snprintf(buffer,20,"%i", i); return buffer; } static int parent_count = 0; static enum MkErrorE count_callback ( MQ_SERVICE_CALL_ARGS ) { parent_count += MqReadI32_e(mqctx); return MK_OK; error: return MkErrorStack_1X(mqctx); } static enum MkErrorE RET_ECUL ( MQ_SERVICE_CALL_ARGS ) { MK_I8 valY; MK_I16 valS; MK_I32 valI; MK_DBL valD; MK_BUF buf; callnum++; MqReadI8_E (mqctx, &valY); MqReadI16_E (mqctx, &valS); MqReadI32_E (mqctx, &valI); MqReadDBL_E (mqctx, &valD); MqReadBUF_E (mqctx, &buf); return MK_OK; error: return MkErrorStack_1X(mqctx); } static enum MkErrorE RET_SDTR ( MQ_SERVICE_CALL_ARGS ) { MK_I32 id; MK_I8 valY; MK_I16 valS; MK_I32 valI; MK_DBL valD; MK_BUF buf; callnum++; MqReadT_START_E (mqctx); MqReadI32_E (mqctx, &id); MqReadT_END_E (mqctx); MqReadI8_E (mqctx, &valY); MqReadI16_E (mqctx, &valS); MqReadI32_E (mqctx, &valI); MqReadDBL_E (mqctx, &valD); MqReadBUF_E (mqctx, &buf); return MK_OK; error: return MkErrorStack_1X(mqctx); } /// \brief display help using \b -h or \b --help command-line option /// \param base the executable usually: <tt>basename(argv[0])</tt> static void ClientHelp ( const char * base ) { MkRtSetup_NULL; MkBufferCreateLOCAL_T(MkBuffer1024C,buf,0); MkBufferAppendV(buf, "usage: %s [OPTION]... [ARGUMENT]...\n" "\n" " This tool is the client part of the performance test toolkit and expect\n" " the 'perfserver' as argument.\n" "\n" " The following tests are defined:\n" " --all Do all the following tests.\n" " --all-performance Do all tests relevant for performance testing.\n" " --all-no-parent Do all the following tests but without parent.\n" " --send-nothing Send empty package just to test the service callback.\n" " --send The data is send from the client to the server using ...\n" " 1. a 1 byte char \n" " 2. a 2 byte short \n" " 3. a 4 byte integer \n" " 4. a 8 byte double \n" " 5. a binary of size between 1 and 1000 bytes\n" " --send-string Same as '--send' but use 'string-data' only\n" " --send-and-wait Same as '--send' but use 'MqSendEND_AND_WAIT' -> DEFAULT\n" " --send-and-callback Same as '--send' but use 'MqSendEND_AND_CALLBACK'\n" " --send-persistent Use a persistent-transaction together with 'MqSendEND_AND_WAIT'\n" " --storage STRING database file, #memdb# or #tmpdb# (default: file)\n" " --parent Create and Delete a PARENT-context in a loop\n" " --spawn|--thread|--fork choose starter (default: lng-specific)\n" " --wrk NUMBER number of parallel workers (default: %i)\n" " --child Create and Delete a CHILD-context in a loop\n" " --bus or --bfl Create and Delete a MkBufferStreamS or MkBufferListS in a loop\n" " --bin/str send ad wait for binary/string data\n" "\n" " %s [ARGUMENT]... syntax:\n" " %s [OPTION]... %c server [OPTION]... [ARGUMENT]\n" "\n" "%s" "\n" " %s [OPTION]:\n" " --num NUMBER number of test-cycles (default: %i)\n" " --sec SECONDS seconds per test (default: %i)\n" " --timeout-event SECONDS timeout for background wait (default: %i)\n" " -h, --help print this help\n" "\n", base, WRK_DEFAULT, base, base, MK_ALFA, MqHelp (NULL), base, NUM_DEFAULT, SEC_DEFAULT, TIMEOUT_EVENT_DEFAULT ); fputs(bufR.super.buf.storage.first.C,stderr); exit(EXIT_SUCCESS); } // =================================================================================== // === MARK_W // === // "global" because PerfWorker_STR0 and PerfWorker_END0 require access static MkThreadLocal bool doNext = true; // --sec require this static MkThreadLocal int worker_count = 0; // [perfworker-example] // asynchronous call static enum MkErrorE PerfWorker_STR0( MQ_SERVICE_CALL_ARGS ) { MK_BFL largv = NULL; MK_BFL pargv = NULL; MK_I32 num = MqReadI32_e(mqctx); pargv = MkBufferListDup(MqReadBFL_e(mqctx)); enum MkErrorE ret = MK_OK; if (num == -1) num = 999999; // endless // start test until "doNext" is "false" or "num" exceeds for (int i=0; doNext && i<num; i++) { // CREATE the context MQ_CTX ctx = MqContextCreate(NULL, mqctx); largv = MkBufferListDup(pargv); MqLinkCreate_C (ctx, largv) { MqContextErrorMove(mqctx,ctx); MqContextDelete(ctx); goto error; } //MqSend(ctx,"E","MARK:C","start"); MkBufferListDelete(largv); // DELETE the context MqContextDelete(ctx); // count the loops worker_count++; // give PerfWorker_END0 time to update "doNext" MqProcessEvent(mqctx, MQ_WAIT_NO, MK_TIMEOUT_DEFAULT); } end: //printV("ret=%i, Delete=%p\n", ret, largv) MkBufferListDelete(largv); MkBufferListDelete(pargv); if (doNext == true) { // finish the test WITHOUT "END0" -> test on --num, answer required. MqSend_E(mqctx, "R", "I", worker_count); } return ret; error: if (doNext == true) { ret = MkErrorStack_1X(mqctx); } else { ret = MkErrorReset_1X(mqctx); } goto end; } // [perfworker-example] static enum MkErrorE PerfWorker_END0( MQ_SERVICE_CALL_ARGS ) { doNext = false; return MqSend(mqctx, "R", "I", worker_count); } static enum MkErrorE PerfWorker_GET0( MQ_SERVICE_CALL_ARGS ) { printXI(mqctx, worker_count); return MqSend(mqctx, "R", "I", worker_count); } enum MkErrorE PerfWorkerSetup ( MQ_SERVICE_CALL_ARGS ) { MqServiceCreate_E (mqctx, "STR0", PerfWorker_STR0, NULL, NULL, NULL); MqServiceCreate_E (mqctx, "END0", PerfWorker_END0, NULL, NULL, NULL); MqServiceCreate_E (mqctx, "GET0", PerfWorker_GET0, NULL, NULL, NULL); return MK_OK; error: return MkErrorStack_1X(mqctx); } enum MkErrorE PerfWorker ( MQ_CALLBACK_FACTORY_CTOR_ARGS ) { MQ_CTX mqctx = MqContextCreate(NULL,tmpl); MqConfigSetServerSetup(mqctx, PerfWorkerSetup, NULL, NULL, NULL); *contextP = mqctx; return MK_OK; } // =================================================================================== // === // === // help doxygen to build external references to the "main" proc of a tool //#define ClientMain main // BEGIN-C-CLIENT-1 /// \brief main entry-point for the tool /// \param argc the number of command-line arguments /// \param argv the command-line arguments as an array of strings /// \return the exit number enum MkErrorE PerfClient ( MQ_CALLBACK_FACTORY_CTOR_ARGS ) { MQ_CTX mqctx = MqContextCreate(NULL,tmpl); MqContextC_T->fHelp = ClientHelp; *contextP = mqctx; return MK_OK; } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #define SIZE 1000 MkBinaryR bin; enum MkErrorE PerfSendPackageStart_RT (MK_RT_ARGS MQ_CTX mqctx, int count) { MqSendSTART_E (mqctx); MqSendI8_E (mqctx, (MK_I8) (count % SCHAR_MAX)); MqSendI16_E (mqctx, (MK_I16) (count % SHRT_MAX)); MqSendI32_E (mqctx, (MK_I32) (count % INT_MAX)); MqSendDBL_E (mqctx, (MK_DBL) (count % INT_MAX)); MqSendBIN_E (mqctx, MkBinaryCreateSlice(bin,0,(count%SIZE)+1)); error: return MkErrorGetCode_0E(); } #define PerfSendPackageStart(...) PerfSendPackageStart_RT(MK_RT_CALL __VA_ARGS__) enum MkErrorE PerfClientExec (MK_RT_ARGS MQ_CTX mqctx, MK_BFL largv) { MK_BUF buf; // storage for return values MK_BFL parentArgv = NULL; // the commandline-arguments (before and after the first MK_ALFA) // what should be tested ? bool sendT = false ; // test MqSendEND time? bool sendStringT = false ; // test MqSendEND time? using string only arguments bool sendNothingT = false ; // test MqSendEND time? but send NO data, just call the service bool sendAndWaitT = false ; // test MqSendEND_AND_WAIT round-trip time? bool sendAndCallT = false ; // test MqSendEND_AND_CALLBACK round-trip time? bool sendPersistentT = false ; // test MqSendEND_AND_WAIT together with persistent transactions round-trip time? bool parentT = false ; // test parent-context creation time? bool childT = false ; // test childT-context creation time? bool allT = false ; // test all bool allWithoutParentT = false ; // test all ... without parent bool allPerformanceT = false ; // test all ... but only tests relevant for performance testing bool busT = false ; // test MkBufferStreamS bool bflT = false ; // test MkBufferListS bool binT = false ; // test binary data bool strT = false ; // test string data MK_I32 num = NUM_DEFAULT; MK_I32 sec = SEC_DEFAULT; MK_I32 wrk = WRK_DEFAULT; MK_I32 timeoutEvent = TIMEOUT_EVENT_DEFAULT; MK_STRN storage = "unknown"; MK_BIN binD = MkSysMalloc (MK_ERROR_PANIC, (SIZE)); memset (binD, 'A', SIZE); bin = MkBinaryCreate(SIZE,binD); MK_STR strD = MkSysMalloc (MK_ERROR_PANIC, (SIZE+1)); memset ((void*)strD, 'S', SIZE); strD[SIZE] = '\0'; //MkStringR str = MkStringCreate(SIZE,strD); MkBufferListCreateSTATIC_T(wrkargs, 0); // read application specific arguments MkBufferListCheckOptionBOL_E (largv, "--send", false, true, &sendT) ; MkBufferListCheckOptionBOL_E (largv, "--send-nothing", false, true, &sendNothingT) ; MkBufferListCheckOptionBOL_E (largv, "--send-string", false, true, &sendStringT) ; MkBufferListCheckOptionBOL_E (largv, "--send-and-wait", false, true, &sendAndWaitT) ; MkBufferListCheckOptionBOL_E (largv, "--send-and-callback", false, true, &sendAndCallT) ; MkBufferListCheckOptionBOL_E (largv, "--send-persistent", false, true, &sendPersistentT) ; MkBufferListCheckOptionBOL_E (largv, "--parent", false, true, &parentT) ; MkBufferListCheckOptionBOL_E (largv, "--child", false, true, &childT) ; MkBufferListCheckOptionBOL_E (largv, "--all", false, true, &allT) ; MkBufferListCheckOptionBOL_E (largv, "--all-no-parent", false, true, &allWithoutParentT) ; MkBufferListCheckOptionBOL_E (largv, "--all-performance", false, true, &allPerformanceT) ; MkBufferListCheckOptionBOL_E (largv, "--bus", false, true, &busT) ; MkBufferListCheckOptionBOL_E (largv, "--bfl", false, true, &bflT) ; MkBufferListCheckOptionBOL_E (largv, "--bin", false, true, &binT) ; MkBufferListCheckOptionBOL_E (largv, "--str", false, true, &strT) ; if (allT) { sendT = sendAndWaitT = sendAndCallT = sendPersistentT = parentT = childT = sendStringT = sendNothingT = busT = bflT = binT = strT = true; } else if (allWithoutParentT) { sendT = sendAndWaitT = sendAndCallT = sendPersistentT = sendStringT = sendNothingT = busT = bflT = binT = strT = true; parentT = childT = false; } else if (allPerformanceT) { sendT = sendAndWaitT = sendAndCallT = parentT = childT = sendNothingT = busT = bflT = true; sendPersistentT = sendStringT = binT = strT = false; } else if ( sendT == false && sendAndWaitT == false && sendAndCallT == false && sendPersistentT == false && parentT == false && childT == false && sendStringT == false && sendNothingT == false && busT == false && bflT == false && binT == false && strT == false ) { sendNothingT = true; } if (sendPersistentT) { snprintf(STORAGE_DEFAULT,128,"test.%u.dat", (unsigned int) getpid()); } // the user can supply --num to change the number of iterations MkBufferListCheckOptionI32_E (largv,"--sec", SEC_DEFAULT, true, &sec); MkBufferListCheckOptionI32_E (largv,"--num", NUM_DEFAULT, true, &num); MkBufferListCheckOptionI32_E (largv,"--wrk", WRK_DEFAULT, true, &wrk); MkBufferListCheckOptionSTR_E (largv,"--storage", STORAGE_DEFAULT, true, &storage); MkBufferListCheckOptionI32_E (largv,"--timeout-event", TIMEOUT_EVENT_DEFAULT, true, &timeoutEvent); // save parent args for later use parentArgv = MkBufferListDup(largv); if (sendT||sendStringT||sendNothingT||sendAndWaitT||sendAndCallT||sendPersistentT|| childT||busT||bflT||binT||strT) { // NEW --parent use worker // OLD this seems outdated - keep for docu // -> Even "--parent" require this initial server because the worker require context->link.alfa // start the server MqLinkCreate_E (mqctx, largv); // check for wrong arguments MqCheckForLeftOverArguments_E (mqctx, largv); // initialize memory, just run one test-case to initialize dynamic data MqSendSTART_E (mqctx); MqSendBIN_E (mqctx, bin); MqSendEND_AND_WAIT_E (mqctx, "ECOU", MK_TIMEOUT_NORMAL); MqReadBUF_E (mqctx, &buf); } // start the MqSendEND_AND_WAIT transaction-performance test MkDLogV (mqctx, 0, "%-30s : %10s [ %8s / %-10s ]\n", "start ------------------------", "result", "count", "sec" ); // --------------------------------------------------------------------------------------- if (sendNothingT) { StatTimerSP itemT = StatCreate (mqctx,sec,num); { StatCtxSP stat = StatCtxCreate (mqctx, "--send-nothing"); // init MqSendSTART_E (mqctx); MqSendEND_E (mqctx, "NTHT", 0); MqSendSYNC_E (mqctx); // test StatInit (itemT); while (StatCheck(itemT)) { MqSendSTART_E (mqctx); MqSendEND_E (mqctx, "NTHT", 0); }; // just sync with the server and wait until all "NTHT" are processed MqSendSYNC_E (mqctx); StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); } // cleanup StatDelete (&itemT); } // finish the MqSendEND test // --------------------------------------------------------------------------------------- if (sendT) { // [Example-MqSendSYNC] StatTimerSP itemT = StatCreate (mqctx,sec,num); { StatCtxSP stat = StatCtxCreate (mqctx, "--send"); // init PerfSendPackageStart(mqctx,9999); MqSendEND_E (mqctx, "RDUL", 0); MqSendSYNC_E (mqctx); // test StatInit (itemT); // TEST: start as many as possible asyncron-service-calles in "itemT" intervall. while (StatCheck(itemT)) { PerfSendPackageStart(mqctx, StatCount(itemT)); MqSendEND_E (mqctx, "RDUL", 0); } // just sync with the server MqSendSYNC_E (mqctx); StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); } // [Example-MqSendSYNC] // cleanup StatDelete (&itemT); } /* finish the MqSendEND test */ // --------------------------------------------------------------------------------------- if (sendStringT) { // test StatTimerSP itemT = StatCreate (mqctx,sec,num); { StatCtxSP stat = StatCtxCreate (mqctx, "--send-string"); // init MqSendSTART_E (mqctx); MqSendSTR_E (mqctx, "Hallo"); MqSendSTR_E (mqctx, "shahdahdhe73uz38djdjfkfod93"); MqSendSTR_E (mqctx, "huch"); MqSendSTR_E (mqctx, "keybord?"); MqSendSTR_E (mqctx, "human!!"); MqSendEND_E (mqctx, "RDUC", 0); MqSendSYNC_E (mqctx); // test StatInit (itemT); while (StatCheck(itemT)) { MqSendSTART_E (mqctx); MqSendSTR_E (mqctx, "Hallo"); MqSendSTR_E (mqctx, "shahdahdhe73uz38djdjfkfod93"); MqSendSTR_E (mqctx, "huch"); MqSendSTR_E (mqctx, "keybord?"); MqSendSTR_E (mqctx, "human!!"); MqSendEND_E (mqctx, "RDUC", 0); }; // just sync with the server and wait until all "RDUC" are processed MqSendSYNC_E (mqctx); StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); } // cleanup StatDelete (&itemT); } // finish the MqSendEND test // --------------------------------------------------------------------------------------- if (sendAndCallT) { StatTimerSP itemT = StatCreate (mqctx,sec,num); { StatCtxSP stat = StatCtxCreate (mqctx, "--send-and-callback"); // init PerfSendPackageStart(mqctx,9999); MqSendEND_AND_CALLBACK_E (mqctx, "ECUL", RET_ECUL, NULL, NULL, 0); MqProcessEvent_E (mqctx, MQ_WAIT_ONCE, timeoutEvent); MqSendSYNC_E (mqctx); // test callnum = 0; StatInit (itemT); while (StatCheck(itemT)) { int count = StatCount(itemT); PerfSendPackageStart(mqctx, count); MqSendEND_AND_CALLBACK_E (mqctx, "ECUL", RET_ECUL, NULL, NULL, 0); // don't flood the socket buffer with unread messages if ((count % 7) == 0) { while (MqProcessEvent (mqctx, MQ_WAIT_NO, timeoutEvent) == MK_OK); } MkErrorCheck_0E(); }; // wait until all callbacks are processed while (callnum != StatCount(itemT)) { MqProcessEvent_E (mqctx, MQ_WAIT_ONCE, timeoutEvent); } StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); } // cleanup StatDelete (&itemT); //MkSysSleep_E (MK_ERROR_IGNORE, 2); } // finish the MqSendEND_AND_CALLBACK test // --------------------------------------------------------------------------------------- if (sendAndWaitT) { enum MkErrorE doSendAndWaitT_RT(MK_RT_ARGS MQ_CTX mqctx, int count) { MK_I8 valY; MK_I16 valS; MK_I32 valI; MK_DBL valD; MK_BUF buf; PerfSendPackageStart(mqctx,count); MqSendEND_AND_WAIT_E (mqctx, "ECUL", MK_TIMEOUT_NORMAL); MqReadI8_E (mqctx, &valY); MqReadI16_E (mqctx, &valS); MqReadI32_E (mqctx, &valI); MqReadDBL_E (mqctx, &valD); MqReadBUF_E (mqctx, &buf); return MK_OK; error: return MkErrorStack_1X(mqctx); } #define doSendAndWaitT(x,c) MkErrorCheck(doSendAndWaitT_RT(MK_RT_CALL x,c)) // test StatTimerSP itemT = StatCreate (mqctx,sec,num); { StatCtxSP stat = StatCtxCreate (mqctx, "--send-and-wait"); // init doSendAndWaitT(mqctx,9999); // test StatInit (itemT); while (StatCheck(itemT)) { doSendAndWaitT(mqctx,StatCount(itemT)); }; StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); } // cleanup StatDelete (&itemT); } // finish the MqSendEND_AND_WAIT performance test // --------------------------------------------------------------------------------------- if (sendPersistentT) { char systemC[200] = ""; StatTimerSP itemT = StatCreate (mqctx,sec,num); { StatCtxSP stat = StatCtxCreate (mqctx, "--send-persistent"); // setup the callback MqServiceCreate_E (mqctx, "SDTR", RET_SDTR, NULL ,NULL, NULL); if (storage[0] != '#') { snprintf(systemC,200,"rm %s-* 2>/dev/null", storage); system(systemC); } // set transaction-database name MqSend (mqctx,"W", "STDB:C", storage); // init - prepare sql queries int count = 9999; MqSendSTART_E (mqctx); MqSendT_START_E (mqctx); MqSendI32_E (mqctx, 999); MqSendT_END_E (mqctx); MqSendI8_E (mqctx, (MK_I8) (count % SCHAR_MAX)); MqSendI16_E (mqctx, (MK_I16) (count % SHRT_MAX)); MqSendI32_E (mqctx, (MK_I32) (count % INT_MAX)); MqSendDBL_E (mqctx, (MK_DBL) (count % INT_MAX)); MqSendBIN_E (mqctx, MkBinaryCreateSlice(bin,0,10)); MqSendEND_AND_TRANSACTION_E (mqctx, "ECUL", "SDTR", MK_TIMEOUT_NORMAL); MqProcessEvent_E (mqctx, MQ_WAIT_ONCE, timeoutEvent); MqSendSYNC_E (mqctx); // test callnum = 0; StatInit (itemT); while (StatCheck(itemT)) { count = StatCount(itemT); MqSendSTART_E (mqctx); MqSendT_START_E (mqctx); MqSendI32_E (mqctx, 999); MqSendT_END_E (mqctx); MqSendI8_E (mqctx, (MK_I8) (count % SCHAR_MAX)); MqSendI16_E (mqctx, (MK_I16) (count % SHRT_MAX)); MqSendI32_E (mqctx, (MK_I32) (count % INT_MAX)); MqSendDBL_E (mqctx, (MK_DBL) (count % INT_MAX)); MqSendBIN_E (mqctx, MkBinaryCreateSlice(bin,0,(count%SIZE)+1)); MqSendEND_AND_TRANSACTION_E (mqctx, "ECUL", "SDTR", MK_TIMEOUT_NORMAL); }; // wait until all callbacks are processed while (callnum != StatCount(itemT)) { MqProcessEvent_E (mqctx, MQ_WAIT_ONCE, timeoutEvent); } StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); MqServiceDelete_E (mqctx, "SDTR"); } // cleanup StatDelete (&itemT); MkSysSleep_E (MkOBJ(mqctx),1); MqSend_E(mqctx,"W","STDC"); if (storage[0] != '#') { system(systemC); } } // finish the MqSendTRANSACTION performance test // --------------------------------------------------------------------------------------- // MARK_P // start the parent-context creation test if (parentT) { bool onError = false; // init StatTimerSP itemT = StatCreate (mqctx,sec,num); { enum MqStartE start = 0; MQ_CTX *slaves = MkSysCalloc(MK_ERROR_PANIC,sizeof(*slaves),(size_t)wrk); if (MkBufferListCheckOptionBOL_e (largv,"--spawn" ,false,true)) start = MQ_START_SPAWN; if (MkBufferListCheckOptionBOL_e (largv,"--thread" ,false,true)) start = MQ_START_THREAD; if (MkBufferListCheckOptionBOL_e (largv,"--fork" ,false,true)) start = MQ_START_FORK; // create the workers for (int i=0; i<wrk; i++) { MkBufferListReset(wrkargs); switch (start) { case MQ_START_DEFAULT : break; case MQ_START_SPAWN : MkBufferListAppendSTR(wrkargs, "--spawn"); break; case MQ_START_THREAD : MkBufferListAppendSTR(wrkargs, "--thread"); break; case MQ_START_FORK : MkBufferListAppendSTR(wrkargs, "--fork"); break; } MkBufferListAppendVA(wrkargs, "--prefix", "wk-cl-", "--postfix", int2str(i), "@", "--prefix", "wk-sv-", NULL ); MqSlaveWorker_E(mqctx, i+MQ_SLAVE_USER, "PerfWorker", wrkargs); } //system("tree-print.bash"); // loop to create the parent context StatCtxSP stat = StatCtxCreate (mqctx, "--parent"); StatInit (itemT); // start the test { if (num == NUM_DEFAULT) { // test: --num not set, test on --sec // start test on all --wrk for (int i=0; i<wrk; i++) { MkBufferListReset(wrkargs); MkBufferListAppendLA(wrkargs, parentArgv); slaves[i] = MqSlaveGet_e(mqctx,i+MQ_SLAVE_USER); // start test MqSend_E(slaves[i], "E", "STR0:IL", num , wrkargs); } // wait '--sec' seconds MkSysSleep_E(MkOBJ(mqctx), sec); // stop the test and get "count" from worker for (int i=0; i<wrk; i++) { MqSend_E(slaves[i], "C", count_callback, "END0"); } } else { //MqSend(mqctx,"W","MARK:C","start"); // test: --num // start test on all --wrk for (int i=0; i<wrk; i++) { //printV("i=%d, num=%d", i, num) MkBufferListReset(wrkargs); MkBufferListAppendLA(wrkargs, parentArgv); slaves[i] = MqSlaveGet_e(mqctx,i+MQ_SLAVE_USER); // start test MqSend_E(slaves[i], "C", count_callback, "STR0:IL", num , wrkargs); } } // wait for --wrk answers from STR0 (--num) or END0 (--sec) for (int i=0; i<wrk; i++) { check_MkErrorE(MqProcessEvent(mqctx, MQ_WAIT_ONCE, timeoutEvent)) goto error2; } goto end2; // this should not happen !! error2: if (MkErrorIsTIMEOUT_0E()) { MkErrorSetC_2M(mqctx, "TIMEOUT in wait for parent respons, forget to start 'perfserver' with: " "--spawn, --thread or --fork ?"); MkErrorStack_0E(); } onError = true; // continue to "cleanup" the test goto skip_statistics; } end2: // delete the master an ALL slaves //printXI(mqctx, count); StatCtxCalc (stat, itemT, parent_count); StatCtxPrint (stat); StatCtxDelete (&stat); // delete the workers skip_statistics: for (int i=0; i<wrk; i++) { MqSlaveDelete_E(mqctx, i+MQ_SLAVE_USER); slaves[i]=NULL; } MkSysFree(slaves); } // cleanup StatDelete (&itemT); if (onError) goto error; } // --------------------------------------------------------------------------------------- // start the childT-context creation test if (childT) { StatTimerSP itemT = StatCreate (mqctx,sec,num); // fill template configuration MQ_CTX template = MqContextCreate(NULL, mqctx); MqConfigSetName (template, "childT"); { // loop to create the parent context StatCtxSP stat = StatCtxCreate (mqctx, "--child"); StatInit (itemT); while (StatCheck(itemT)) { MQ_CTX ctx = MqContextCreate(NULL,template); MqLinkCreateChild_C (ctx, mqctx, NULL) { MqContextErrorMove(mqctx,ctx); MqContextDelete(ctx); goto error; } MqContextDelete(ctx); } StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); } MqContextDelete(template); // cleanup StatDelete (&itemT); } // --------------------------------------------------------------------------------------- // MARK_S // test: MqBufferStreamS if (busT) { StatTimerSP itemT = StatCreate (mqctx,sec,num); { StatCtxSP stat = StatCtxCreate (mqctx, "--bus"); MK_I8 valY; MK_I16 valS; MK_I32 valI; MK_DBL valD; MK_STRN valC; // init storage… int count = 9999; { MqSendSTART_E (mqctx); MqSendI8_E (mqctx, (MK_I8) (count % SCHAR_MAX)); MqSendI16_E (mqctx, (MK_I16) (count % SHRT_MAX)); MqSendI32_E (mqctx, (MK_I32) (count % INT_MAX)); MqSendDBL_E (mqctx, (MK_DBL) (count % INT_MAX)); MqSendSTR_E (mqctx, "Hallo World!"); MqSendEND_AND_WAIT_E (mqctx, "BUST", MK_TIMEOUT_NORMAL); MqReadI8_E (mqctx, &valY); MqReadI16_E (mqctx, &valS); MqReadI32_E (mqctx, &valI); MqReadDBL_E (mqctx, &valD); MqReadSTR_E (mqctx, &valC); } // test BUST StatInit (itemT); while (StatCheck(itemT)) { count = StatCount(itemT); MqSendSTART_E (mqctx); MqSendI8_E (mqctx, (MK_I8) (count % SCHAR_MAX)); MqSendI16_E (mqctx, (MK_I16) (count % SHRT_MAX)); MqSendI32_E (mqctx, (MK_I32) (count % INT_MAX)); MqSendDBL_E (mqctx, (MK_DBL) (count % INT_MAX)); MqSendSTR_E (mqctx, "Hallo World!"); MqSendEND_AND_WAIT_E (mqctx, "BUST", MK_TIMEOUT_NORMAL); MqReadI8_E (mqctx, &valY); MqReadI16_E (mqctx, &valS); MqReadI32_E (mqctx, &valI); MqReadDBL_E (mqctx, &valD); MqReadSTR_E (mqctx, &valC); } StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); } // cleanup StatDelete (&itemT); } // --------------------------------------------------------------------------------------- // MARK_F // test: MqBufferListS if (bflT) { StatTimerSP itemT = StatCreate (mqctx,sec,num); { StatCtxSP stat = StatCtxCreate (mqctx, "--bfl"); MK_I8 valY; MK_I16 valS; MK_I32 valI; MK_DBL valD; MK_STRN valC; // init storage… int count = 9999; { MqSendSTART_E (mqctx); MqSendI8_E (mqctx, (MK_I8) (count % SCHAR_MAX)); MqSendI16_E (mqctx, (MK_I16) (count % SHRT_MAX)); MqSendI32_E (mqctx, (MK_I32) (count % INT_MAX)); MqSendDBL_E (mqctx, (MK_DBL) (count % INT_MAX)); MqSendSTR_E (mqctx, "Hallo World!"); MqSendEND_AND_WAIT_E (mqctx, "BFLT", MK_TIMEOUT_NORMAL); MqReadI8_E (mqctx, &valY); MqReadI16_E (mqctx, &valS); MqReadI32_E (mqctx, &valI); MqReadDBL_E (mqctx, &valD); MqReadSTR_E (mqctx, &valC); } // test BFLT StatInit (itemT); while (StatCheck(itemT)) { int count = StatCount(itemT); MqSendSTART_E (mqctx); MqSendI8_E (mqctx, (MK_I8) (count % SCHAR_MAX)); MqSendI16_E (mqctx, (MK_I16) (count % SHRT_MAX)); MqSendI32_E (mqctx, (MK_I32) (count % INT_MAX)); MqSendDBL_E (mqctx, (MK_DBL) (count % INT_MAX)); MqSendSTR_E (mqctx, "Hallo World!"); MqSendEND_AND_WAIT_E (mqctx, "BFLT", MK_TIMEOUT_NORMAL); MqReadI8_E (mqctx, &valY); MqReadI16_E (mqctx, &valS); MqReadI32_E (mqctx, &valI); MqReadDBL_E (mqctx, &valD); MqReadSTR_E (mqctx, &valC); } StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); } // cleanup StatDelete (&itemT); } // --------------------------------------------------------------------------------------- // MARK_B // test: binary if (binT) { StatTimerSP itemT = StatCreate (mqctx,sec,num); // fill template configuration { StatCtxSP stat = StatCtxCreate (mqctx, "--bin"); // init int idx = (9999%SIZE)+1; MqSendSTART_E (mqctx); MqSendBIN_E (mqctx, MkBinaryCreateSlice(bin,0,idx)); MqSendEND_E (mqctx, "BINT", 0); MqSendSYNC_E (mqctx); // test BINT StatInit (itemT); while (StatCheck(itemT)) { idx = (StatCount(itemT)%SIZE)+1; MqSendSTART_E (mqctx); MqSendBIN_E (mqctx, MkBinaryCreateSlice(bin,0,idx)); MqSendEND_E (mqctx, "BINT", 0); } // just sync with the server MqSendSYNC_E (mqctx); StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); } // cleanup StatDelete (&itemT); } // --------------------------------------------------------------------------------------- // MARK_S // test: string if (strT) { StatTimerSP itemT = StatCreate (mqctx,sec,num); // fill template configuration { StatCtxSP stat = StatCtxCreate (mqctx, "--str"); // init int idx = (9999%SIZE)+1; MqSendSTART_E (mqctx); char tmp = strD[idx]; strD[idx] = '\0'; enum MkErrorE ret = MqSendSTR (mqctx, strD); strD[idx] = tmp; MkErrorCheck(ret); MqSendEND_E (mqctx, "STRT", 0); MqSendSYNC_E (mqctx); // test STRT StatInit (itemT); while (StatCheck(itemT)) { idx = (StatCount(itemT)%SIZE)+1; MqSendSTART_E (mqctx); char tmp = strD[idx]; strD[idx] = '\0'; enum MkErrorE ret = MqSendSTR (mqctx, strD); strD[idx] = tmp; MkErrorCheck(ret); MqSendEND_E (mqctx, "STRT", 0); } // just sync with the server MqSendSYNC_E (mqctx); StatCtxCalc (stat, itemT, -1); StatCtxPrint (stat); StatCtxDelete (&stat); } // cleanup StatDelete (&itemT); } // cleanup MkDLogC (mqctx, 0, "end: ----------------------------------------\n"); goto exit; error: MkErrorAppendC_2M(mqctx, "use '-h' or '--help' for usage"); exit: MkSysFree(binD); MkSysFree(strD); MkBufferListFree(wrkargs); MkBufferListDelete(parentArgv); return MkErrorStack_0E_Check(); } // package-main int main (int argc, MK_STRN argv[]) { AllRtSetup_NULL; /* printI(MK_RT_REF.error_mk.text.super.buf.var.cursize); printI(MK_RT_REF.error_mk.text.super.buf.storage.size); return 0; */ // setup commandline arguments for later use MK_BFL largv = MkBufferListCreateVC(argc, argv); MQ_CTX mqctx = NULL; // create "PerfClient" factory… and make it to the default. MqFactoryDefault( MqFactoryAdd_1(PerfClient) ); MqFactoryAdd_1(PerfWorker); // inspect commandline-argument for the "factory" to choose… and create a object MqFactoryNew_E (MqFactoryGetCalledL(largv), NULL, &mqctx); if (MqConfigGetIsServer(mqctx)) { // this is the worker for "--spawn" MqLinkCreate_E (mqctx, largv); MqCheckForLeftOverArguments_E (mqctx, largv); MkBufferListDelete(largv); MqProcessEvent_E (mqctx,MQ_WAIT_FOREVER,MK_TIMEOUT_DEFAULT); } else { // this is the frontend MkErrorCheck(PerfClientExec(MK_RT_CALL mqctx, largv)); } error: MkBufferListDelete(largv); MqExit_1(mqctx); return 0; } /** \} client */ // vim: tabstop=8