threadMain.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  1. #ident "ldclt @(#)threadMain.c 1.40 01/05/04"
  2. /** BEGIN COPYRIGHT BLOCK
  3. * This Program is free software; you can redistribute it and/or modify it under
  4. * the terms of the GNU General Public License as published by the Free Software
  5. * Foundation; version 2 of the License.
  6. *
  7. * This Program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  10. *
  11. * You should have received a copy of the GNU General Public License along with
  12. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  13. * Place, Suite 330, Boston, MA 02111-1307 USA.
  14. *
  15. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  16. * right to link the code of this Program with code not covered under the GNU
  17. * General Public License ("Non-GPL Code") and to distribute linked combinations
  18. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  19. * permitted under this exception must only link to the code of this Program
  20. * through those well defined interfaces identified in the file named EXCEPTION
  21. * found in the source code files (the "Approved Interfaces"). The files of
  22. * Non-GPL Code may instantiate templates or use macros or inline functions from
  23. * the Approved Interfaces without causing the resulting work to be covered by
  24. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  25. * additions to the list of Approved Interfaces. You must obey the GNU General
  26. * Public License in all respects for all of the Program code and other code used
  27. * in conjunction with the Program except the Non-GPL Code covered by this
  28. * exception. If you modify this file, you may extend this exception to your
  29. * version of the file, but you are not obligated to do so. If you do not wish to
  30. * provide this exception without modification, you must delete this exception
  31. * statement from your version and license this file solely under the GPL without
  32. * exception.
  33. *
  34. *
  35. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  36. * Copyright (C) 2006 Red Hat, Inc.
  37. * All rights reserved.
  38. * END COPYRIGHT BLOCK **/
  39. #ifdef HAVE_CONFIG_H
  40. # include <config.h>
  41. #endif
  42. /*
  43. FILE : threadMain.c
  44. AUTHOR : Jean-Luc SCHWING
  45. VERSION : 1.0
  46. DATE : 04 December 1998
  47. DESCRIPTION :
  48. This file implements the main/core part of the
  49. threads. The ldap part is in another source file.
  50. LOCAL : None.
  51. HISTORY :
  52. ---------+--------------+------------------------------------------------------
  53. dd/mm/yy | Author | Comments
  54. ---------+--------------+------------------------------------------------------
  55. 04/12/98 | JL Schwing | Creation
  56. ---------+--------------+------------------------------------------------------
  57. 10/12/98 | JL Schwing | 1.2 : Add nb of errors statistics.
  58. ---------+--------------+------------------------------------------------------
  59. 10/12/98 | JL Schwing | 1.3 : Implement asynchronous mode.
  60. ---------+--------------+------------------------------------------------------
  61. 11/12/98 | JL Schwing | 1.4 : Implement max errors threshold.
  62. | fflush(stdout) after each printf.
  63. ---------+--------------+------------------------------------------------------
  64. 14/12/98 | JL Schwing | 1.5 : Implement "-e close".
  65. | Add "thread is dead" message.
  66. ---------+--------------+------------------------------------------------------
  67. 16/12/98 | JL Schwing | 1.6 : Implement "-e add" and "-e delete".
  68. ---------+--------------+------------------------------------------------------
  69. 23/12/98 | JL Schwing | 1.7 : bug fix - crash in msgIdDel().
  70. ---------+--------------+------------------------------------------------------
  71. 28/12/98 | JL Schwing | 1.8 : Add tag asyncHit.
  72. ---------+--------------+------------------------------------------------------
  73. 13/01/99 | JL Schwing | 1.9 : Implement "-e string".
  74. ---------+--------------+------------------------------------------------------
  75. 18/01/99 | JL Schwing | 1.10: Implement "-e randombase".
  76. ---------+--------------+------------------------------------------------------
  77. 21/01/99 | JL Schwing | 1.11: Implement "-e ascii".
  78. ---------+--------------+------------------------------------------------------
  79. 26/02/99 | JL Schwing | 1.12: Improve strict ascii: reject more characters.
  80. ---------+--------------+------------------------------------------------------
  81. 26/02/99 | JL Schwing | 1.13: Quote (aka \) characters rather than reject.
  82. ---------+--------------+------------------------------------------------------
  83. 04/05/99 | JL Schwing | 1.14: Modify msgId*() to memorize attribs as well.
  84. ---------+--------------+------------------------------------------------------
  85. 19/05/99 | JL Schwing | 1.15: Implement "-e rename".
  86. | Exit the thread if status==DEAD
  87. ---------+--------------+------------------------------------------------------
  88. 28/05/99 | JL Schwing | 1.16: Add new option -W (wait).
  89. ---------+--------------+------------------------------------------------------
  90. 06/03/00 | JL Schwing | 1.17: Test malloc() return value.
  91. ---------+--------------+------------------------------------------------------
  92. 18/08/00 | JL Schwing | 1.18: Print begin and end dates.
  93. ---------+--------------+------------------------------------------------------
  94. 25/08/00 | JL Schwing | 1.19: Implement consistent exit status...
  95. | Fix some old legacy code.
  96. ---------+--------------+------------------------------------------------------
  97. 14/11/00 | JL Schwing | 1.20: Will now use utils.c functions.
  98. ---------+--------------+------------------------------------------------------
  99. 17/11/00 | JL Schwing | 1.21: Implement "-e smoothshutdown".
  100. | Add new functions setThreadStatus() getThreadStatus().
  101. ---------+--------------+------------------------------------------------------
  102. 21/11/00 | JL Schwing | 1.22: Implement "-e attreplace=name:mask"
  103. ---------+--------------+------------------------------------------------------
  104. 29/11/00 | JL Schwing | 1.23: Port on NT 4.
  105. ---------+--------------+------------------------------------------------------
  106. 01/12/00 | JL Schwing | 1.24: Port on Linux.
  107. ---------+--------------+------------------------------------------------------
  108. 15/12/00 | JL Schwing | 1.25: Add more trace in VERY_VERBOSE mode.
  109. ---------+--------------+------------------------------------------------------
  110. 18/12/00 | JL Schwing | 1.26: Add new exit status EXIT_INIT.
  111. ---------+--------------+------------------------------------------------------
  112. 05/01/01 | JL Schwing | 1.27: Implement "-e randombinddn" and associated
  113. | "-e randombinddnlow/high"
  114. ---------+--------------+------------------------------------------------------
  115. 08/01/01 | JL Schwing | 1.28: Implement "-e scalab01".
  116. ---------+--------------+------------------------------------------------------
  117. 12/01/01 | JL Schwing | 1.29: Include scalab01.h
  118. ---------+--------------+------------------------------------------------------
  119. 05/03/01 | JL Schwing | 1.30: Bug fix - crash SIGSEGV if no binDN provided.
  120. ---------+--------------+------------------------------------------------------
  121. 14/03/01 | JL Schwing | 1.31: Implement "-e commoncounter"
  122. | Add new function incrementCommonCounter().
  123. ---------+--------------+------------------------------------------------------
  124. 14/03/01 | JL Schwing | 1.32: Implement "-e dontsleeponserverdown".
  125. ---------+--------------+------------------------------------------------------
  126. 15/03/01 | JL Schwing | 1.33: Implement "-e randomattrlist=name:name:name"
  127. | Add new function selectRandomAttrList().
  128. ---------+--------------+------------------------------------------------------
  129. 19/03/01 | JL Schwing | 1.34: Implement "-e genldif=filename"
  130. ---------+--------------+------------------------------------------------------
  131. 23/03/01 | JL Schwing | 1.35: Implements "-e rdn=value".
  132. ---------+--------------+------------------------------------------------------
  133. 28/03/01 | JL Schwing | 1.36: Support -e commoncounter with -e rdn/object
  134. | Add new function incrementCommonCounterObject().
  135. ---------+--------------+------------------------------------------------------
  136. 02/04/01 | JL Schwing | 1.37: Bug fix : large files support for -e genldif.
  137. ---------+--------------+------------------------------------------------------
  138. 11/04/01 | JL Schwing | 1.38: Implement [INCRFROMFILE<NOLOOP>(myfile)]
  139. ---------+--------------+------------------------------------------------------
  140. 03/05/01 | JL Schwing | 1.39: Implement -e randombinddnfromfile=filename.
  141. ---------+--------------+------------------------------------------------------
  142. 04/05/01 | JL Schwing | 1.40: Implement -e bindonly.
  143. ---------+--------------+------------------------------------------------------
  144. */
  145. #include <stdio.h> /* printf(), etc... */
  146. #include <string.h> /* strerror(), etc... */
  147. #include <stdlib.h> /* exit(), etc... */
  148. #include <ctype.h> /* isascii(), etc... */
  149. #include <errno.h> /* errno, etc... */ /*JLS 06-03-00*/
  150. #include <lber.h> /* ldap C-API BER declarations */
  151. #include <ldap.h> /* ldap C-API declarations */
  152. #ifndef _WIN32 /*JLS 29-11-00*/
  153. #include <unistd.h> /* close(), etc... */
  154. #include <pthread.h> /* pthreads(), etc... */
  155. #include <signal.h> /* sigfillset(), etc... */
  156. #endif /*JLS 29-11-00*/
  157. #include "port.h" /* Portability definitions */ /*JLS 29-11-00*/
  158. #include "ldclt.h" /* This tool's include file */
  159. #include "utils.h" /* Utilities functions */ /*JLS 14-11-00*/
  160. #include "scalab01.h" /* Scalab01 specific */ /*JLS 12-01-01*/
  161. /* New */ /*JLS 15-03-01*/
  162. /* ****************************************************************************
  163. FUNCTION : selectRandomAttrList
  164. PURPOSE : Select a random attr list.
  165. INPUT : tttctx = this thread context
  166. OUTPUT : None.
  167. RETURN : The random list.
  168. DESCRIPTION :
  169. *****************************************************************************/
  170. char **
  171. selectRandomAttrList (
  172. thread_context *tttctx)
  173. {
  174. tttctx->attrlist[0] = mctx.attrlist[rndlim(0,mctx.attrlistNb-1)];
  175. return (tttctx->attrlist);
  176. }
  177. /* ****************************************************************************
  178. FUNCTION : randomString
  179. PURPOSE : Return a random string, of length nbDigits.
  180. The string is returned in tttctx->buf2.
  181. INPUT : tttctx = thread context.
  182. nbDigits = number of digits required.
  183. OUTPUT : None.
  184. RETURN : -1 if error, 0 else.
  185. DESCRIPTION :
  186. *****************************************************************************/
  187. int
  188. randomString (
  189. thread_context *tttctx,
  190. int nbDigits)
  191. {
  192. rndstr (tttctx->buf2, nbDigits); /*JLS 14-11-00*/
  193. return (0);
  194. }
  195. /* New */ /*JLS 28-03-01*/
  196. /* ****************************************************************************
  197. FUNCTION : incrementCommonCounterObject
  198. PURPOSE : Purpose of the fct
  199. INPUT : tttctx = thread context
  200. field = field to process
  201. OUTPUT : None.
  202. RETURN : -1 if error or end of loop (no_loop), new value else.
  203. DESCRIPTION :
  204. *****************************************************************************/
  205. int
  206. incrementCommonCounterObject (
  207. thread_context *tttctx,
  208. vers_field *field)
  209. {
  210. int ret; /* Return value */
  211. int val; /* New value */
  212. /*
  213. * Get mutex
  214. */
  215. if ((ret = ldclt_mutex_lock (&(field->cnt_mutex))) != 0)
  216. {
  217. fprintf (stderr, "ldclt[%d]: %s: cannot mutex_lock(field->cnt_mutex), error=%d (%s)\n",
  218. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  219. fflush (stderr);
  220. return (-1);
  221. }
  222. /*
  223. * Compute next value
  224. */
  225. switch (field->how)
  226. {
  227. case HOW_INCR_FROM_FILE:
  228. case HOW_INCR_NB:
  229. if (field->cnt <= field->high) /* Limit not reached */
  230. {
  231. val = field->cnt;
  232. field->cnt++;
  233. }
  234. else
  235. {
  236. val = field->low;
  237. field->cnt = field->low + 1;
  238. }
  239. break;
  240. case HOW_INCR_FROM_FILE_NL:
  241. case HOW_INCR_NB_NOLOOP:
  242. if (field->cnt <= field->high) /* Limit not reached */
  243. {
  244. val = field->cnt;
  245. field->cnt++;
  246. }
  247. else
  248. val = -1; /* Exit thread */
  249. break;
  250. default:
  251. printf ("ldclt[%d]: %s: Illegal how=%d in incrementCommonCounterObject()\n",
  252. mctx.pid, tttctx->thrdId, field->how);
  253. val = -1;
  254. break;
  255. }
  256. /*
  257. * Free mutex
  258. */
  259. if ((ret = ldclt_mutex_unlock (&(field->cnt_mutex))) != 0)
  260. {
  261. fprintf(stderr,"ldclt[%d]: %s: cannot mutex_unlock(field->cnt_mutex), error=%d (%s)\n",
  262. mctx.pid, tttctx->thrdId, ret, strerror (ret));
  263. fflush (stderr);
  264. return (-1);
  265. }
  266. /*
  267. * Maybe a message to print ?
  268. */
  269. if (val < 0)
  270. printf ("ldclt[%d]: %s: Hit top incrementeal value\n", mctx.pid, tttctx->thrdId);
  271. return (val);
  272. }
  273. /* New */ /*JLS 14-03-01*/
  274. /* ****************************************************************************
  275. FUNCTION : incrementCommonCounter
  276. PURPOSE : Purpose of the fct
  277. INPUT : tttctx = thread context
  278. OUTPUT : None.
  279. RETURN : -1 if error or end of loop (no_loop), new value else.
  280. DESCRIPTION :
  281. *****************************************************************************/
  282. int
  283. incrementCommonCounter (
  284. thread_context *tttctx)
  285. {
  286. int ret; /* Return value */
  287. int val; /* New value */
  288. /*
  289. * Get mutex
  290. */
  291. if ((ret = ldclt_mutex_lock (&(mctx.lastVal_mutex))) != 0)
  292. {
  293. fprintf (stderr, "ldclt[%d]: T%03d: cannot mutex_lock(lastVal_mutex), error=%d (%s)\n",
  294. mctx.pid, tttctx->thrdNum, ret, strerror (ret));
  295. fflush (stderr);
  296. return (-1);
  297. }
  298. /*
  299. * Compute next value
  300. */
  301. if ((mctx.mode & NOLOOP) && (mctx.lastVal >= mctx.randomHigh))
  302. val = -1;
  303. else
  304. {
  305. mctx.lastVal += mctx.incr;
  306. if (mctx.lastVal > mctx.randomHigh)
  307. {
  308. if (mctx.mode & NOLOOP)
  309. val = -1;
  310. else
  311. mctx.lastVal -= (mctx.randomHigh-mctx.incr) + mctx.randomLow;
  312. }
  313. val = mctx.lastVal;
  314. }
  315. /*
  316. * Free mutex
  317. */
  318. if ((ret = ldclt_mutex_unlock (&(mctx.lastVal_mutex))) != 0)
  319. {
  320. fprintf(stderr,"ldclt[%d]: T%03d: cannot mutex_unlock(lastVal_mutex), error=%d (%s)\n",
  321. mctx.pid, tttctx->thrdNum, ret, strerror (ret));
  322. fflush (stderr);
  323. return (-1);
  324. }
  325. /*
  326. * Maybe a message to print ?
  327. */
  328. if (val < 0)
  329. printf ("ldclt[%d]: T%03d: Hit top incrementeal value\n", mctx.pid, tttctx->thrdNum);
  330. return (val);
  331. }
  332. /* ****************************************************************************
  333. FUNCTION : incrementNbOpers
  334. PURPOSE : Increment the counters tttctx->nbOpers and
  335. tttctx->totOpers of the given thread.
  336. INPUT : tttctx = thread context.
  337. OUTPUT : None.
  338. RETURN : -1 if error, 0 else.
  339. DESCRIPTION :
  340. *****************************************************************************/
  341. int
  342. incrementNbOpers (
  343. thread_context *tttctx)
  344. {
  345. int ret; /* Return value */
  346. /*
  347. * Get mutex
  348. */
  349. if ((ret = ldclt_mutex_lock (&(tttctx->nbOpers_mutex))) != 0)
  350. {
  351. fprintf (stderr, "ldclt[%d]: T%03d: cannot mutex_lock(), error=%d (%s)\n",
  352. mctx.pid, tttctx->thrdNum, ret, strerror (ret));
  353. fflush (stderr);
  354. return (-1);
  355. }
  356. /*
  357. * Increment counter
  358. */
  359. tttctx->nbOpers++;
  360. /*
  361. * Free mutex
  362. */
  363. if ((ret = ldclt_mutex_unlock (&(tttctx->nbOpers_mutex))) != 0)
  364. {
  365. fprintf (stderr, "ldclt[%d]: T%03d: cannot mutex_unlock(), error=%d (%s)\n",
  366. mctx.pid, tttctx->thrdNum, ret, strerror (ret));
  367. fflush (stderr);
  368. return (-1);
  369. }
  370. /*
  371. * Increment total and check if max value reached
  372. */
  373. tttctx->totOpers++;
  374. if(tttctx->totalReq > -1) {
  375. if (tttctx->totOpers >= tttctx->totalReq) {
  376. if (setThreadStatus(tttctx, MUST_SHUTDOWN) < 0) {
  377. tttctx->status = DEAD; /* Force thread to die! */
  378. }
  379. }
  380. }
  381. return (0);
  382. }
  383. /* ****************************************************************************
  384. FUNCTION : ignoreError
  385. PURPOSE : Returns true or false depending on the given error
  386. should be ignored or not (option -I).
  387. We will sleep() if an error about server down is to be
  388. ignored.
  389. INPUT : err = error number
  390. OUTPUT : None.
  391. RETURN : 1 if should be ignored, 0 else.
  392. DESCRIPTION :
  393. *****************************************************************************/
  394. int
  395. ignoreError (
  396. int err)
  397. {
  398. int i;
  399. for (i=0 ; i<mctx.ignErrNb ; i++)
  400. if (mctx.ignErr[i] == err)
  401. { /*JLS 14-03-01*/
  402. if ((!(mctx.mode & DONT_SLEEP_DOWN)) && /*JLS 14-03-01*/
  403. ((err == LDAP_SERVER_DOWN) || /*JLS 14-03-01*/
  404. (err == LDAP_CONNECT_ERROR))) /*JLS 14-03-01*/
  405. ldclt_sleep (1); /*JLS 14-03-01*/
  406. return (1);
  407. } /*JLS 14-03-01*/
  408. return (0);
  409. }
  410. /* ****************************************************************************
  411. FUNCTION : addErrorStat
  412. PURPOSE : Add the given error number to the statistics.
  413. INPUT : err = error number
  414. OUTPUT : None.
  415. RETURN : -1 if error, 0 else.
  416. DESCRIPTION :
  417. *****************************************************************************/
  418. int
  419. addErrorStat (
  420. int err)
  421. {
  422. int ret; /* Return value */
  423. /*
  424. * Get mutex
  425. */
  426. if ((ret = ldclt_mutex_lock (&(mctx.errors_mutex))) != 0)
  427. {
  428. fprintf (stderr,
  429. "ldclt[%d]: Cannot mutex_lock(errors_mutex), error=%d (%s)\n",
  430. mctx.pid, ret, strerror (ret));
  431. fflush (stderr);
  432. return (-1);
  433. }
  434. /*
  435. * Update the counters
  436. */
  437. if ((err <= 0) || (err >= MAX_ERROR_NB))
  438. {
  439. fprintf (stderr, "ldclt[%d]: Illegal error number %d\n", mctx.pid, err);
  440. fflush (stderr);
  441. mctx.errorsBad++;
  442. }
  443. else
  444. mctx.errors[err]++;
  445. /*
  446. * Release the mutex
  447. */
  448. if ((ret = ldclt_mutex_unlock (&(mctx.errors_mutex))) != 0)
  449. {
  450. fprintf (stderr,
  451. "ldclt[%d]: Cannot mutex_unlock(errors_mutex), error=%d (%s)\n",
  452. mctx.pid, ret, strerror (ret));
  453. fflush (stderr);
  454. return (-1);
  455. }
  456. /*
  457. * Maybe we should ignore this error ?
  458. */
  459. if (!(ignoreError (err)))
  460. {
  461. /*
  462. * Ok, we should not ignore this error...
  463. * Maybe the limit is reached ?
  464. */
  465. if ((err <= 0) || (err >= MAX_ERROR_NB))
  466. {
  467. if (mctx.errorsBad > mctx.maxErrors)
  468. {
  469. printf ("ldclt[%d]: Max error limit reached - exiting.\n", mctx.pid);
  470. (void) printGlobalStatistics(); /*JLS 25-08-00*/
  471. fflush (stdout);
  472. ldclt_sleep (5);
  473. ldcltExit (EXIT_MAX_ERRORS); /*JLS 25-08-00*/
  474. }
  475. }
  476. else
  477. if (mctx.errors[err] > mctx.maxErrors)
  478. {
  479. printf ("ldclt[%d]: Max error limit reached - exiting.\n", mctx.pid);
  480. (void) printGlobalStatistics(); /*JLS 25-08-00*/
  481. fflush (stdout);
  482. ldclt_sleep (5);
  483. ldcltExit (EXIT_MAX_ERRORS); /*JLS 25-08-00*/
  484. }
  485. }
  486. /*
  487. * Normal end
  488. */
  489. return (0);
  490. }
  491. /* ****************************************************************************
  492. FUNCTION : msgIdAdd
  493. PURPOSE : Add a new message id to the pending ones.
  494. INPUT : tttctx = thread's context.
  495. msgid = message id.
  496. str = free string.
  497. dn = dn of the entry
  498. attribs = attributes
  499. OUTPUT : None.
  500. RETURN : -1 if error, 0 else.
  501. DESCRIPTION :
  502. *****************************************************************************/
  503. int
  504. msgIdAdd (
  505. thread_context *tttctx,
  506. int msgid,
  507. char *str,
  508. char *dn,
  509. LDAPMod **attribs)
  510. {
  511. if (mctx.mode & VERY_VERBOSE)
  512. printf ("ldclt[%d]: T%03d: msgIdAdd (%d, %s)\n", mctx.pid, tttctx->thrdNum, msgid, str);
  513. /*
  514. * Add the new cell
  515. */
  516. if (tttctx->firstMsgId == NULL)
  517. {
  518. tttctx->firstMsgId = (msgid_cell *) malloc (sizeof (msgid_cell));
  519. if (tttctx->firstMsgId == NULL) /*JLS 06-03-00*/
  520. { /*JLS 06-03-00*/
  521. printf ("ldclt[%d]: T%03d: cannot malloc(tttctx->firstMsgId), error=%d (%s)\n",
  522. mctx.pid, tttctx->thrdNum, errno, strerror (errno));
  523. return (-1); /*JLS 06-03-00*/
  524. } /*JLS 06-03-00*/
  525. tttctx->lastMsgId = tttctx->firstMsgId;
  526. }
  527. else
  528. {
  529. tttctx->lastMsgId->next = (msgid_cell *) malloc (sizeof (msgid_cell));
  530. if (tttctx->lastMsgId->next == NULL) /*JLS 06-03-00*/
  531. { /*JLS 06-03-00*/
  532. printf ("ldclt[%d]: T%03d: cannot malloc(tttctx->lastMsgId->next), error=%d (%s)\n",
  533. mctx.pid, tttctx->thrdNum, errno, strerror (errno));
  534. return (-1); /*JLS 06-03-00*/
  535. } /*JLS 06-03-00*/
  536. tttctx->lastMsgId = tttctx->lastMsgId->next;
  537. }
  538. /*
  539. * Memorize the information
  540. */
  541. tttctx->lastMsgId->next = NULL;
  542. tttctx->lastMsgId->msgid = msgid;
  543. strncpy (tttctx->lastMsgId->str, str, sizeof(tttctx->lastMsgId->str));
  544. tttctx->lastMsgId->str[sizeof(tttctx->lastMsgId->str)-1] = '\0';
  545. strncpy (tttctx->lastMsgId->dn, dn, sizeof(tttctx->lastMsgId->dn));
  546. tttctx->lastMsgId->dn[sizeof(tttctx->lastMsgId->dn)-1] = '\0';
  547. tttctx->lastMsgId->attribs = attribs;
  548. return (0);
  549. }
  550. /* ****************************************************************************
  551. FUNCTION : msgIdAttribs
  552. PURPOSE : Found the requested message id in the pending list.
  553. INPUT : tttctx = thread's context
  554. msgid = message id
  555. OUTPUT : None
  556. RETURN : The associated attributes, or NULL.
  557. DESCRIPTION :
  558. *****************************************************************************/
  559. LDAPMod **
  560. msgIdAttribs (
  561. thread_context *tttctx,
  562. int msgid)
  563. {
  564. msgid_cell *pt;
  565. if (mctx.mode & VERY_VERBOSE)
  566. printf ("ldclt[%d]: T%03d: msgIdAttribs (%d)\n", mctx.pid, tttctx->thrdNum, msgid);
  567. for (pt = tttctx->firstMsgId ; pt != NULL ; pt = pt->next)
  568. if (pt->msgid == msgid)
  569. return (pt->attribs);
  570. return (NULL);
  571. }
  572. /* ****************************************************************************
  573. FUNCTION : msgIdDN
  574. PURPOSE : Found the requested message id in the pending list.
  575. INPUT : tttctx = thread's context
  576. msgid = message id
  577. OUTPUT : None
  578. RETURN : The associated DN, or NULL.
  579. DESCRIPTION :
  580. *****************************************************************************/
  581. char *
  582. msgIdDN (
  583. thread_context *tttctx,
  584. int msgid)
  585. {
  586. msgid_cell *pt;
  587. if (mctx.mode & VERY_VERBOSE)
  588. printf ("ldclt[%d]: T%03d: msgIdDN (%d)\n", mctx.pid, tttctx->thrdNum, msgid);
  589. for (pt = tttctx->firstMsgId ; pt != NULL ; pt = pt->next)
  590. if (pt->msgid == msgid)
  591. return (pt->dn);
  592. return (NULL);
  593. }
  594. /* ****************************************************************************
  595. FUNCTION : msgIdStr
  596. PURPOSE : Found the requested message id in the pending list.
  597. INPUT : tttctx = thread's context
  598. msgid = message id
  599. OUTPUT : None
  600. RETURN : The associated str, or an error message string.
  601. DESCRIPTION :
  602. *****************************************************************************/
  603. char *
  604. msgIdStr (
  605. thread_context *tttctx,
  606. int msgid)
  607. {
  608. msgid_cell *pt;
  609. if (mctx.mode & VERY_VERBOSE)
  610. printf ("ldclt[%d]: T%03d: msgIdStr (%d)\n", mctx.pid, tttctx->thrdNum, msgid);
  611. for (pt = tttctx->firstMsgId ; pt != NULL ; pt = pt->next)
  612. if (pt->msgid == msgid)
  613. return (pt->str);
  614. return ("Error: msgid not found");
  615. }
  616. /* ****************************************************************************
  617. FUNCTION : msgIdDel
  618. PURPOSE : Delete a message id from the pending ones.
  619. INPUT : tttctx = thread's context
  620. msgid = message id.
  621. freeAttr= true or false depending on freing the attribs
  622. OUTPUT : None.
  623. RETURN : -1 if not found, 0 else.
  624. DESCRIPTION :
  625. *****************************************************************************/
  626. int
  627. msgIdDel (
  628. thread_context *tttctx,
  629. int msgid,
  630. int freeAttr)
  631. {
  632. msgid_cell *pt; /* For the loop */
  633. msgid_cell *ptToFree; /* The cell to free */
  634. if (mctx.mode & VERY_VERBOSE)
  635. printf ("ldclt[%d]: T%03d: msgIdDel (%d)\n", mctx.pid, tttctx->thrdNum, msgid);
  636. /*
  637. * Make sure there is a list !
  638. */
  639. if (tttctx->firstMsgId != NULL)
  640. {
  641. /*
  642. * Maybe it is the first one ?
  643. */
  644. if (tttctx->firstMsgId->msgid == msgid)
  645. {
  646. ptToFree = tttctx->firstMsgId;
  647. tttctx->firstMsgId = tttctx->firstMsgId->next;
  648. if (tttctx->firstMsgId == NULL)
  649. tttctx->lastMsgId = NULL;
  650. free (ptToFree);
  651. return (0);
  652. }
  653. /*
  654. * Let's go through the whole list
  655. */
  656. for (pt = tttctx->firstMsgId ; pt->next != NULL ; pt = pt->next)
  657. if (pt->next->msgid == msgid)
  658. {
  659. /*
  660. * Be carrefull if it is the last element of the list
  661. */
  662. if (pt->next->next == NULL)
  663. tttctx->lastMsgId = pt;
  664. ptToFree = pt->next;
  665. pt->next = ptToFree->next;
  666. if (freeAttr)
  667. if (freeAttrib (ptToFree->attribs) < 0)
  668. return (-1);
  669. /*
  670. * Free the pointer itself
  671. */
  672. free (ptToFree);
  673. return (0);
  674. }
  675. }
  676. /*
  677. * Not found
  678. */
  679. printf ("ldclt[%d]: T%03d: message %d not found.\n", mctx.pid, tttctx->thrdNum, msgid);
  680. fflush (stdout);
  681. return (-1);
  682. }
  683. /* New function */ /*JLS 17-11-00*/
  684. /* ****************************************************************************
  685. FUNCTION : getThreadStatus
  686. PURPOSE : Get the value of a given thread's status.
  687. INPUT : tttctx = thread context
  688. OUTPUT : status = the thread's status
  689. RETURN : -1 if error, 0 else.
  690. DESCRIPTION :
  691. *****************************************************************************/
  692. int
  693. getThreadStatus (
  694. thread_context *tttctx,
  695. int *status)
  696. {
  697. int ret; /* Return code */
  698. if ((ret = ldclt_mutex_lock (&(tttctx->status_mutex))) != 0)
  699. {
  700. fprintf (stderr,
  701. "ldclt[%d]: Cannot mutex_lock(T%03d), error=%d (%s)\n",
  702. mctx.pid, tttctx->thrdNum, ret, strerror (ret));
  703. fprintf (stderr, "ldclt[%d]: Problem in getThreadStatus()\n", mctx.pid);
  704. fflush (stderr);
  705. return (-1);
  706. }
  707. *status = tttctx->status;
  708. if ((ret = ldclt_mutex_unlock (&(tttctx->status_mutex))) != 0)
  709. {
  710. fprintf (stderr,
  711. "ldclt[%d]: Cannot mutex_unlock(T%03d), error=%d (%s)\n",
  712. mctx.pid, tttctx->thrdNum, ret, strerror (ret));
  713. fprintf (stderr, "ldclt[%d]: Problem in getThreadStatus()\n", mctx.pid);
  714. fflush (stderr);
  715. return (-1);
  716. }
  717. return (0);
  718. }
  719. /* New function */ /*JLS 17-11-00*/
  720. /* ****************************************************************************
  721. FUNCTION : setThreadStatus
  722. PURPOSE : Set the value of a given thread's status.
  723. INPUT : tttctx = thread context
  724. status = new status
  725. OUTPUT : None.
  726. RETURN : -1 if error, 0 else.
  727. DESCRIPTION :
  728. *****************************************************************************/
  729. int
  730. setThreadStatus (
  731. thread_context *tttctx,
  732. int status)
  733. {
  734. int ret; /* Return code */
  735. if ((ret = ldclt_mutex_lock (&(tttctx->status_mutex))) != 0)
  736. {
  737. fprintf (stderr,
  738. "ldclt[%d]: Cannot mutex_lock(T%03d), error=%d (%s)\n",
  739. mctx.pid, tttctx->thrdNum, ret, strerror (ret));
  740. fprintf (stderr, "ldclt[%d]: Problem in setThreadStatus()\n", mctx.pid);
  741. fflush (stderr);
  742. return (-1);
  743. }
  744. tttctx->status = status;
  745. if ((ret = ldclt_mutex_unlock (&(tttctx->status_mutex))) != 0)
  746. {
  747. fprintf (stderr,
  748. "ldclt[%d]: Cannot mutex_unlock(T%03d), error=%d (%s)\n",
  749. mctx.pid, tttctx->thrdNum, ret, strerror (ret));
  750. fprintf (stderr, "ldclt[%d]: Problem in setThreadStatus()\n", mctx.pid);
  751. fflush (stderr);
  752. return (-1);
  753. }
  754. return (0);
  755. }
  756. /* ****************************************************************************
  757. FUNCTION : threadMain
  758. PURPOSE : This function is the main function of the client threads
  759. part of this tool.
  760. INPUT : arg = this thread's thread_context
  761. OUTPUT : None.
  762. RETURN : None.
  763. DESCRIPTION :
  764. *****************************************************************************/
  765. void *
  766. threadMain (
  767. void *arg)
  768. {
  769. thread_context *tttctx; /* This thread's context */
  770. int go = 1; /* Thread must continue */
  771. int status; /* Thread's status */ /*JLS 17-11-00*/
  772. /*
  773. * Initialization
  774. */
  775. tttctx = (thread_context *) arg;
  776. if (setThreadStatus (tttctx, CREATED) < 0) /*JLS 17-11-00*/
  777. { /*JLS 17-11-00*/
  778. tttctx->status = DEAD; /*JLS 17-11-00*/
  779. return NULL; /*JLS 17-11-00*/
  780. } /*JLS 17-11-00*/
  781. tttctx->asyncHit = 0;
  782. tttctx->binded = 0;
  783. tttctx->fd = -1;
  784. tttctx->lastVal = mctx.randomLow-1;
  785. tttctx->ldapCtx = NULL;
  786. tttctx->matcheddnp = NULL; /*JLS 15-12-00*/
  787. tttctx->nbOpers = 0;
  788. tttctx->totOpers = 0;
  789. tttctx->pendingNb = 0;
  790. tttctx->firstMsgId = NULL;
  791. tttctx->lastMsgId = NULL;
  792. /*
  793. * Don't forget the buffers !!
  794. * This should save time while redoing random values
  795. */
  796. if ((mctx.mode & NEED_FILTER) || (mctx.mod2 & (M2_GENLDIF|M2_NEED_FILTER))) /*JLS 19-03-01*/
  797. {
  798. if (mctx.mod2 & M2_RDN_VALUE) /*JLS 23-03-01*/
  799. tttctx->bufFilter = (char *) malloc (MAX_FILTER); /*JLS 23-03-01*/
  800. else /*JLS 23-03-01*/
  801. { /*JLS 23-03-01*/
  802. /*
  803. * Variable filter ?
  804. */
  805. tttctx->bufFilter = (char *) malloc (strlen (mctx.filter) + 1);
  806. if (tttctx->bufFilter == NULL) /*JLS 06-03-00*/
  807. { /*JLS 06-03-00*/
  808. printf ("ldclt[%d]: %s: cannot malloc(tttctx->bufFilter), error=%d (%s)\n",
  809. mctx.pid, tttctx->thrdId, errno, strerror (errno));
  810. ldcltExit (EXIT_INIT); /*JLS 18-12-00*/
  811. } /*JLS 06-03-00*/
  812. if (!(mctx.mode & (RANDOM | INCREMENTAL)))
  813. strcpy (tttctx->bufFilter, mctx.filter);
  814. else
  815. {
  816. tttctx->startRandom = strlen (mctx.randomHead);
  817. strcpy (tttctx->bufFilter, mctx.randomHead);
  818. strcpy (&(tttctx->bufFilter[tttctx->startRandom+mctx.randomNbDigit]),
  819. mctx.randomTail);
  820. if (mctx.mode & VERY_VERBOSE)
  821. {
  822. printf ("ldclt[%d]: %s: startRandom = %d\n",
  823. mctx.pid, tttctx->thrdId, tttctx->startRandom);
  824. printf ("ldclt[%d]: %s: randomHead = \"%s\", randomTail = \"%s\"\n",
  825. mctx.pid, tttctx->thrdId, mctx.randomHead, mctx.randomTail);
  826. }
  827. }
  828. } /*JLS 23-03-01*/
  829. /*
  830. * Variable base DN ?
  831. */
  832. tttctx->bufBaseDN = (char *) malloc (strlen (mctx.baseDN) + 1);
  833. if (tttctx->bufBaseDN == NULL) /*JLS 06-03-00*/
  834. { /*JLS 06-03-00*/
  835. printf ("ldclt[%d]: T%03d: cannot malloc(tttctx->bufBaseDN), error=%d (%s)\n",
  836. mctx.pid, tttctx->thrdNum, errno, strerror (errno));
  837. ldcltExit (EXIT_INIT); /*JLS 18-12-00*/
  838. } /*JLS 06-03-00*/
  839. if (!(mctx.mode & RANDOM_BASE))
  840. strcpy (tttctx->bufBaseDN, mctx.baseDN);
  841. else
  842. {
  843. tttctx->startBaseDN = strlen (mctx.baseDNHead);
  844. strcpy (tttctx->bufBaseDN, mctx.baseDNHead);
  845. strcpy (&(tttctx->bufBaseDN[tttctx->startBaseDN+mctx.baseDNNbDigit]),
  846. mctx.baseDNTail);
  847. }
  848. /*
  849. * Variable bind DN ?
  850. * Do not forget the random bind password below that is activated
  851. * at the same time as the random bind DN.
  852. */
  853. if (mctx.bindDN != NULL) /*JLS 05-03-01*/
  854. { /*JLS 05-03-01*/
  855. tttctx->bufBindDN = (char *) malloc (strlen (mctx.bindDN) + 1);
  856. if (tttctx->bufBindDN == NULL)
  857. {
  858. printf ("ldclt[%d]: T%03d: cannot malloc(tttctx->bufBindDN), error=%d (%s)\n",
  859. mctx.pid, tttctx->thrdNum, errno, strerror (errno));
  860. ldcltExit (EXIT_INIT);
  861. }
  862. if (!(mctx.mode & RANDOM_BINDDN))
  863. strcpy (tttctx->bufBindDN, mctx.bindDN);
  864. else
  865. {
  866. tttctx->startBindDN = strlen (mctx.bindDNHead);
  867. strcpy (tttctx->bufBindDN, mctx.bindDNHead);
  868. strcpy (&(tttctx->bufBindDN[tttctx->startBindDN+mctx.bindDNNbDigit]),
  869. mctx.bindDNTail);
  870. }
  871. } /*JLS 05-03-01*/
  872. /*
  873. * Variable bind password ?
  874. * Remember that the random bind password feature is activated
  875. * by the same option as the random bind DN, but has here its own
  876. * code section for the ease of coding.
  877. */
  878. if (mctx.passwd != NULL) /*JLS 05-03-01*/
  879. { /*JLS 05-03-01*/
  880. tttctx->bufPasswd = (char *) malloc (strlen (mctx.passwd) + 1);
  881. if (tttctx->bufPasswd == NULL)
  882. {
  883. printf ("ldclt[%d]: T%03d: cannot malloc(tttctx->bufPasswd), error=%d (%s)\n",
  884. mctx.pid, tttctx->thrdNum, errno, strerror (errno));
  885. ldcltExit (EXIT_INIT);
  886. }
  887. if (!(mctx.mode & RANDOM_BINDDN))
  888. strcpy (tttctx->bufPasswd, mctx.passwd);
  889. else
  890. {
  891. tttctx->startPasswd = strlen (mctx.passwdHead);
  892. strcpy (tttctx->bufPasswd, mctx.passwdHead);
  893. strcpy (&(tttctx->bufPasswd[tttctx->startPasswd+mctx.passwdNbDigit]),
  894. mctx.passwdTail);
  895. }
  896. }
  897. } /*JLS 05-03-01*/
  898. /*
  899. * Bind DN from a file ?
  900. * The trick (mctx.passwd = "foo bar"; ) is needed to
  901. * simplify the code, because in many places we check
  902. * if mctx.passwd exist before sending password.
  903. */
  904. if (mctx.mod2 & M2_RNDBINDFILE) /*JLS 03-05-01*/
  905. { /*JLS 03-05-01*/
  906. tttctx->bufBindDN = (char *) malloc (MAX_DN_LENGTH); /*JLS 03-05-01*/
  907. tttctx->bufPasswd = (char *) malloc (MAX_DN_LENGTH); /*JLS 03-05-01*/
  908. mctx.passwd = "foo bar"; /* trick... */ /*JLS 03-05-01*/
  909. } /*JLS 03-05-01*/
  910. /*
  911. * Variable Authid ?
  912. */
  913. if (mctx.sasl_authid != NULL)
  914. {
  915. tttctx->bufSaslAuthid = (char *) malloc (strlen (mctx.sasl_authid) + 1);
  916. if (tttctx->bufSaslAuthid == NULL)
  917. {
  918. printf ("ldclt[%d]: T%03d: cannot malloc(tttctx->bufSaslAuthid), error=%d (%s)\n",
  919. mctx.pid, tttctx->thrdNum, errno, strerror (errno));
  920. ldcltExit (EXIT_INIT);
  921. }
  922. if (!(mctx.mod2 & M2_RANDOM_SASLAUTHID))
  923. strcpy (tttctx->bufSaslAuthid, mctx.sasl_authid);
  924. else
  925. {
  926. tttctx->startSaslAuthid = strlen (mctx.sasl_authid_head);
  927. strcpy (tttctx->bufSaslAuthid, mctx.sasl_authid_head);
  928. strcpy (&(tttctx->bufSaslAuthid[tttctx->startSaslAuthid+mctx.sasl_authid_nbdigit]),
  929. mctx.sasl_authid_tail);
  930. }
  931. }
  932. /*
  933. * Initiates the attribute replace buffers
  934. */
  935. if (mctx.mode & ATTR_REPLACE) /* New */ /*JLS 21-11-00*/
  936. {
  937. tttctx->bufAttrpl = (char *) malloc (strlen (mctx.attrpl) + 1);
  938. if (tttctx->bufAttrpl == NULL)
  939. {
  940. printf ("ldclt[%d]: T%03d: cannot malloc(tttctx->bufAttrpl), error=%d (%s)\n",
  941. mctx.pid, tttctx->thrdNum, errno, strerror (errno));
  942. ldcltExit (EXIT_INIT); /*JLS 18-12-00*/
  943. }
  944. tttctx->startAttrpl = strlen (mctx.attrplHead);
  945. strcpy (tttctx->bufAttrpl, mctx.attrplHead);
  946. strcpy (&(tttctx->bufAttrpl[tttctx->startAttrpl+mctx.attrplNbDigit]),
  947. mctx.attrplTail);
  948. }
  949. /*
  950. * Initiates the attribute replace buffers attrplName
  951. */
  952. if ( mctx.mod2 & M2_ATTR_REPLACE_FILE )
  953. {
  954. /* bufAttrpl should point to the same memory location that mctx.attrplFileContent points to */
  955. tttctx->bufAttrpl = mctx.attrplFileContent;
  956. if (tttctx->bufAttrpl == NULL)
  957. {
  958. printf ("ldclt[%d]: T%03d: cannot malloc(tttctx->bufAttrpl), error=%d (%s), can we read file [%s]\n", mctx.pid, tttctx->thrdNum, errno, strerror (errno), mctx.attrplFile);
  959. ldcltExit (EXIT_INIT);
  960. }
  961. }
  962. /*
  963. * We are ready to go !
  964. */
  965. status = RUNNING; /*JLS 17-11-00*/
  966. if (setThreadStatus (tttctx, RUNNING) < 0) /*JLS 17-11-00*/
  967. status = DEAD; /*JLS 17-11-00*/
  968. /*
  969. * Let's go !
  970. */
  971. while (go && (status != DEAD) && (status != MUST_SHUTDOWN)) /*JLS 17-11-00*/
  972. {
  973. if (mctx.waitSec > 0)
  974. { /*JLS 17-11-00*/
  975. ldclt_sleep (mctx.waitSec);
  976. /*
  977. * Maybe we should shutdown ?
  978. */
  979. if (getThreadStatus (tttctx, &status) < 0) /*JLS 17-11-00*/
  980. break; /*JLS 17-11-00*/
  981. if (status == MUST_SHUTDOWN) /*JLS 17-11-00*/
  982. break; /*JLS 17-11-00*/
  983. } /*JLS 17-11-00*/
  984. /*
  985. * Do a LDAP request
  986. */
  987. if (tttctx->mode & ADD_ENTRIES)
  988. if (doAddEntry (tttctx) < 0)
  989. {
  990. go = 0;
  991. continue;
  992. }
  993. if (tttctx->mode & ATTR_REPLACE) /*JLS 21-11-00*/
  994. if (doAttrReplace (tttctx) < 0) /*JLS 21-11-00*/
  995. { /*JLS 21-11-00*/
  996. go = 0; /*JLS 21-11-00*/
  997. continue; /*JLS 21-11-00*/
  998. } /*JLS 21-11-00*/
  999. if (mctx.mod2 & M2_ATTR_REPLACE_FILE )
  1000. if (doAttrFileReplace (tttctx) < 0)
  1001. {
  1002. go = 0;
  1003. continue;
  1004. }
  1005. if (tttctx->mode & DELETE_ENTRIES)
  1006. if (doDeleteEntry (tttctx) < 0)
  1007. {
  1008. go = 0;
  1009. continue;
  1010. }
  1011. if (mctx.mod2 & M2_BINDONLY) /*JLS 04-05-01*/
  1012. if (doBindOnly (tttctx) < 0) /*JLS 04-05-01*/
  1013. { /*JLS 04-05-01*/
  1014. go = 0; /*JLS 04-05-01*/
  1015. continue; /*JLS 04-05-01*/
  1016. } /*JLS 04-05-01*/
  1017. if (tttctx->mode & EXACT_SEARCH)
  1018. if (doExactSearch (tttctx) < 0)
  1019. {
  1020. go = 0;
  1021. continue;
  1022. }
  1023. if (tttctx->mode & RENAME_ENTRIES)
  1024. if (doRename (tttctx) < 0)
  1025. {
  1026. go = 0;
  1027. continue;
  1028. }
  1029. /*
  1030. * Maybe a specific scenario ?
  1031. */
  1032. if (tttctx->mode & SCALAB01) /*JLS 08-01-01*/
  1033. if (doScalab01 (tttctx) < 0) /*JLS 08-01-01*/
  1034. { /*JLS 08-01-01*/
  1035. go = 0; /*JLS 08-01-01*/
  1036. continue; /*JLS 08-01-01*/
  1037. } /*JLS 08-01-01*/
  1038. /*
  1039. * Maybe genldif mode ?
  1040. */
  1041. if (mctx.mod2 & M2_GENLDIF) /*JLS 19-03-01*/
  1042. if (doGenldif (tttctx) < 0) /*JLS 19-03-01*/
  1043. { /*JLS 19-03-01*/
  1044. ldclt_flush_genldif(); /*JLS 02-04-01*/
  1045. go = 0; /*JLS 19-03-01*/
  1046. continue; /*JLS 19-03-01*/
  1047. } /*JLS 19-03-01*/
  1048. if (mctx.mod2 & M2_ABANDON)
  1049. {
  1050. if (doAbandon (tttctx) < 0)
  1051. {
  1052. go = 0;
  1053. continue;
  1054. }
  1055. }
  1056. /*
  1057. * Check the thread's status
  1058. */
  1059. if (getThreadStatus (tttctx, &status) < 0) /*JLS 17-11-00*/
  1060. break; /*JLS 17-11-00*/
  1061. }
  1062. /*
  1063. * End of thread
  1064. */
  1065. /* [156984] once setting "DEAD", nothing should be done in the context */
  1066. /* moved the dead message above setThreadStatus(DEAD) */
  1067. printf ("ldclt[%d]: T%03d: thread is dead.\n", mctx.pid, tttctx->thrdNum);
  1068. fflush (stdout);
  1069. if (setThreadStatus (tttctx, DEAD) < 0) /*JLS 17-11-00*/
  1070. { /*JLS 17-11-00*/
  1071. ldclt_sleep (1); /*JLS 17-11-00*/
  1072. tttctx->status = DEAD; /* Force it !!! */ /*JLS 17-11-00*/
  1073. } /*JLS 17-11-00*/
  1074. return (arg);
  1075. }
  1076. /* End of file */