libpkix_buildthreads.c (9417B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 * libpkixBuildThreads.c 6 * 7 * libpkix Builder Performance Evaluation application (multi-threaded) 8 * 9 */ 10 11 #include <stdio.h> 12 #include <string.h> 13 14 #include "secutil.h" 15 16 #include "nspr.h" 17 #include "prtypes.h" 18 #include "prtime.h" 19 #include "prlong.h" 20 21 #include "pk11func.h" 22 #include "secasn1.h" 23 #include "cert.h" 24 #include "cryptohi.h" 25 #include "secoid.h" 26 #include "certdb.h" 27 #include "nss.h" 28 29 #include "pkix.h" 30 #include "pkix_tools.h" 31 #include "pkix_pl_cert.h" 32 33 #include "testutil.h" 34 #include "testutil_nss.h" 35 36 static void *plContext = NULL; 37 38 #undef pkixTempResult 39 #define PERF_DECREF(obj) \ 40 { \ 41 PKIX_Error *pkixTempResult = NULL; \ 42 if (obj) { \ 43 pkixTempResult = PKIX_PL_Object_DecRef((PKIX_PL_Object *)(obj), plContext); \ 44 obj = NULL; \ 45 } \ 46 } 47 48 static void finish(char *message, int code); 49 50 typedef struct ThreadDataStr tData; 51 52 struct ThreadDataStr { 53 CERTCertificate *anchor; 54 char *eecertName; 55 PRIntervalTime duration; 56 CERTCertDBHandle *handle; 57 PRUint32 iterations; 58 }; 59 60 #define PKIX_LOGGER_ON 1 61 62 #ifdef PKIX_LOGGER_ON 63 64 char *logLevels[] = { 65 "None", 66 "Fatal Error", 67 "Error", 68 "Warning", 69 "Debug", 70 "Trace" 71 }; 72 73 static PKIX_Error * 74 loggerCallback( 75 PKIX_Logger *logger, 76 PKIX_PL_String *message, 77 PKIX_UInt32 logLevel, 78 PKIX_ERRORCLASS logComponent, 79 void *plContext) 80 { 81 char *msg = NULL; 82 static int callCount = 0; 83 84 msg = PKIX_String2ASCII(message, plContext); 85 printf("Logging %s (%s): %s\n", 86 logLevels[logLevel], 87 PKIX_ERRORCLASSNAMES[logComponent], 88 msg); 89 PR_Free((void *)msg); 90 91 return (NULL); 92 } 93 94 #endif /* PKIX_LOGGER_ON */ 95 96 static void 97 ThreadEntry(void *data) 98 { 99 tData *tdata = (tData *)data; 100 PRIntervalTime duration = tdata->duration; 101 PRIntervalTime start = PR_IntervalNow(); 102 103 PKIX_List *anchors = NULL; 104 PKIX_ProcessingParams *procParams = NULL; 105 PKIX_BuildResult *buildResult = NULL; 106 CERTCertificate *nsseecert; 107 PKIX_PL_Cert *eeCert = NULL; 108 PKIX_CertStore *certStore = NULL; 109 PKIX_List *certStores = NULL; 110 PKIX_ComCertSelParams *certSelParams = NULL; 111 PKIX_CertSelector *certSelector = NULL; 112 PKIX_PL_Date *nowDate = NULL; 113 void *state = NULL; /* only relevant with non-blocking I/O */ 114 void *nbioContext = NULL; /* only relevant with non-blocking I/O */ 115 116 PR_ASSERT(duration); 117 if (!duration) { 118 return; 119 } 120 121 do { 122 123 /* libpkix code */ 124 125 /* keep more update time, testing cache */ 126 PKIX_PL_Date_Create_UTCTime(NULL, &nowDate, plContext); 127 128 /* CertUsage is 0x10 and no NSS arena */ 129 /* We haven't determined how we obtain the value of wincx */ 130 131 nsseecert = CERT_FindCertByNicknameOrEmailAddr(tdata->handle, 132 tdata->eecertName); 133 if (!nsseecert) 134 finish("Unable to find eecert.\n", 1); 135 136 pkix_pl_Cert_CreateWithNSSCert(nsseecert, &eeCert, plContext); 137 138 PKIX_List_Create(&anchors, plContext); 139 140 /* 141 * This code is retired. 142 * pkix_pl_Cert_CreateWithNSSCert 143 * (tdata->anchor, &anchorCert, NULL); 144 * PKIX_TrustAnchor_CreateWithCert(anchorCert, &anchor, NULL); 145 * PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, NULL); 146 */ 147 148 PKIX_ProcessingParams_Create(anchors, &procParams, plContext); 149 150 PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_TRUE, plContext); 151 152 PKIX_ProcessingParams_SetDate(procParams, nowDate, plContext); 153 154 /* create CertSelector with target certificate in params */ 155 156 PKIX_ComCertSelParams_Create(&certSelParams, plContext); 157 158 PKIX_ComCertSelParams_SetCertificate(certSelParams, eeCert, plContext); 159 160 PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext); 161 162 PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext); 163 164 PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext); 165 166 PKIX_PL_Pk11CertStore_Create(&certStore, plContext); 167 168 PKIX_List_Create(&certStores, plContext); 169 PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore, plContext); 170 PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext); 171 172 PKIX_BuildChain(procParams, 173 &nbioContext, 174 &state, 175 &buildResult, 176 NULL, 177 plContext); 178 179 /* 180 * As long as we use only CertStores with blocking I/O, we 181 * know we must be done at this point. 182 */ 183 184 if (!buildResult) { 185 (void)fprintf(stderr, "libpkix BuildChain failed.\n"); 186 PORT_Assert(0); 187 return; 188 } 189 190 tdata->iterations++; 191 192 PERF_DECREF(nowDate); 193 PERF_DECREF(anchors); 194 PERF_DECREF(procParams); 195 PERF_DECREF(buildResult); 196 PERF_DECREF(certStore); 197 PERF_DECREF(certStores); 198 PERF_DECREF(certSelParams); 199 PERF_DECREF(certSelector); 200 PERF_DECREF(eeCert); 201 202 } while ((PR_IntervalNow() - start) < duration); 203 } 204 205 static void 206 Test( 207 CERTCertificate *anchor, 208 char *eecertName, 209 PRIntervalTime duration, 210 CERTCertDBHandle *handle, 211 PRUint32 threads) 212 { 213 tData data; 214 tData **alldata; 215 PRIntervalTime starttime, endtime, elapsed; 216 PRUint32 msecs; 217 float total = 0; 218 PRThread **pthreads = NULL; 219 PRUint32 i = 0; 220 221 data.duration = duration; 222 data.anchor = anchor; 223 data.eecertName = eecertName; 224 data.handle = handle; 225 226 data.iterations = 0; 227 228 starttime = PR_IntervalNow(); 229 pthreads = (PRThread **)PR_Malloc(threads * sizeof(PRThread *)); 230 alldata = (tData **)PR_Malloc(threads * sizeof(tData *)); 231 for (i = 0; i < threads; i++) { 232 alldata[i] = (tData *)PR_Malloc(sizeof(tData)); 233 *alldata[i] = data; 234 pthreads[i] = 235 PR_CreateThread(PR_USER_THREAD, 236 ThreadEntry, 237 (void *)alldata[i], 238 PR_PRIORITY_NORMAL, 239 PR_GLOBAL_THREAD, 240 PR_JOINABLE_THREAD, 241 0); 242 } 243 244 for (i = 0; i < threads; i++) { 245 tData *args = alldata[i]; 246 PR_JoinThread(pthreads[i]); 247 total += args->iterations; 248 PR_Free((void *)args); 249 } 250 251 PR_Free((void *)pthreads); 252 PR_Free((void *)alldata); 253 endtime = PR_IntervalNow(); 254 255 endtime = PR_IntervalNow(); 256 elapsed = endtime - starttime; 257 msecs = PR_IntervalToMilliseconds(elapsed); 258 total /= msecs; 259 total *= 1000; 260 (void)fprintf(stdout, "%f operations per second.\n", total); 261 } 262 263 static void 264 finish(char *message, int code) 265 { 266 (void)printf(message); 267 exit(code); 268 } 269 270 static void 271 usage(char *progname) 272 { 273 (void)printf("Usage : %s <-d certStoreDirectory> <duration> <threads> " 274 "<anchorNickname> <eecertNickname>\n\n", 275 progname); 276 finish("", 0); 277 } 278 279 int 280 libpkix_buildthreads(int argc, char **argv) 281 { 282 CERTCertDBHandle *handle = NULL; 283 CERTCertificate *eecert = NULL; 284 PRIntervalTime duration = PR_SecondsToInterval(1); 285 PRUint32 threads = 1; 286 PKIX_UInt32 actualMinorVersion; 287 PKIX_UInt32 j = 0; 288 PKIX_Logger *logger = NULL; 289 void *wincx = NULL; 290 291 /* if (argc != 5) -- when TrustAnchor used to be on command line */ 292 if (argc != 4) { 293 usage(argv[0]); 294 } 295 if (atoi(argv[1]) > 0) { 296 duration = PR_SecondsToInterval(atoi(argv[1])); 297 } 298 if (atoi(argv[2]) > 0) { 299 threads = atoi(argv[2]); 300 } 301 302 PKIX_PL_NssContext_Create(certificateUsageEmailSigner, PKIX_FALSE, 303 NULL, &plContext); 304 305 handle = CERT_GetDefaultCertDB(); 306 PR_ASSERT(handle); 307 308 #ifdef PKIX_LOGGER_ON 309 310 /* set logger to log trace and up */ 311 PKIX_SetLoggers(NULL, plContext); 312 PKIX_Logger_Create(loggerCallback, NULL, &logger, plContext); 313 PKIX_Logger_SetMaxLoggingLevel(logger, PKIX_LOGGER_LEVEL_WARNING, plContext); 314 PKIX_AddLogger(logger, plContext); 315 316 #endif /* PKIX_LOGGER_ON */ 317 318 /* 319 * This code is retired 320 * anchor = CERT_FindCertByNicknameOrEmailAddr(handle, argv[3]); 321 * if (!anchor) finish("Unable to find anchor.\n", 1); 322 * 323 * eecert = CERT_FindCertByNicknameOrEmailAddr(handle, argv[4]); 324 325 * if (!eecert) finish("Unable to find eecert.\n", 1); 326 * 327 * Test(anchor, eecert, duration, threads); 328 */ 329 330 Test(NULL, argv[3], duration, handle, threads); 331 332 PERF_DECREF(logger); 333 334 PKIX_Shutdown(plContext); 335 336 return (0); 337 }