1/* 2 * Copyright (c) 2006 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <unistd.h> 30#include <stdlib.h> 31#include <stdio.h> 32#include <stdbool.h> 33#include <errno.h> 34#include <string.h> 35 36// add additional headers needed here. 37 38#include "../libmicro.h" 39#include <grp.h> 40#include <uuid/uuid.h> 41 42#if DEBUG 43# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) 44#else 45# define debug(fmt, args...) 46#endif 47 48 49// Correct use case 50// 51// getgrnam -E -L -S -W -B 200 -C 10 -r 10 52// 53// libMicro default benchmark run options are "-E -L -S -W -C 200" 54// 55// -B is batch size: loop iteration per each benchmark run. Needs to match # of 56// real lookups. This is total number of lookups to issue. 57// -C is min sample number: how many benchmark needs to run to get proper sample 58// 1 is mimumum, but you get at least 3 benchmark run 59// samples. Do not set to zero. Default is 200 for most 60// runs in libMicro. 61// -r is the number of total groups (from "local_test_group1" to "local_test_group#") 62 63extern int gL1CacheEnabled; 64 65/* 66 * Your state variables should live in the tsd_t struct below 67 */ 68typedef struct { 69} tsd_t; 70 71// temporary buffer size 72#define BUFSIZE 200 73 74// the number of record lookup to issue is covered by standard option optB 75static int optRecords = 10; // the number of total records 76 77// This will use local users (local_test_*) 78static char *default_gprefix = "ds_test_group"; 79 80#define GROUPNAME_LEN 30 81static char *grpname_list; 82 83int 84benchmark_init() 85{ 86 debug("benchmark_init"); 87 (void) sprintf(lm_optstr, "l:r:g:"); 88 89 lm_tsdsize = sizeof (tsd_t); 90 lm_defB = 100; 91 92 (void) sprintf(lm_usage, 93 "\n ------- getgrnam specific options (default: *)\n" 94 " [-r total number of group records (10*)]\n" 95 " [-g group prefix(ds_test_group)]\n" 96 "\n" ); 97 return (0); 98} 99 100/* 101 * This is where you parse your lower-case arguments. 102 */ 103int 104benchmark_optswitch(int opt, char *optarg) 105{ 106 debug("benchmark_optswitch"); 107 108 switch (opt) { 109 case 'r': // total number of records. default is 100 110 optRecords = atoi(optarg); 111 debug("optRecords = %d\n", optRecords); 112 break; 113 114 case 'l': 115 gL1CacheEnabled = atoi(optarg); 116 break; 117 118 case 'g': // base name for the groups to use 119 default_gprefix = strdup(optarg); 120 debug("default_gprefix = %s\n", default_gprefix); 121 break; 122 123 default: 124 return -1; 125 } 126 127 return 0; 128} 129 130 131// Initialize all structures that will be used in benchmark() 132// moved template init from benchmark_initworker -> benchmark_initrun 133// since username_list is static across threads and processes 134// 135int 136benchmark_initrun() 137{ 138 int i; 139 140 debug("\nbenchmark_initrun"); 141 142 // create an array of usernames to use in benchmark before their use 143 // realtime generation in benchmark effects performance measurements 144 grpname_list = malloc( optRecords * GROUPNAME_LEN ); 145 if (!grpname_list) { 146 debug ("malloc error"); 147 exit (1); 148 } 149 150 for (i = 0; i < optRecords; i++) { 151 sprintf(&grpname_list[i*GROUPNAME_LEN], "%s%d", default_gprefix, i+1); 152 debug("creating group name %s", &grpname_list[i*GROUPNAME_LEN]); 153 } 154 155 return (0); 156} 157 158 159int 160benchmark(void *tsd, result_t *res) 161{ 162 int i, err; 163 struct group *grp = NULL; 164 165 res->re_errors = 0; 166 167 debug("in to benchmark - optB = %i", lm_optB); 168 srandom(getpid()); 169 170 for (i = 0; i < lm_optB; i++) { 171 int index = (random() % optRecords) * GROUPNAME_LEN; 172 173 if (lm_optT > 1) { 174 struct group gd; 175 struct group *grp_ptr = &gd; 176 struct group *tmp_ptr; 177 char gbuf[BUFSIZE]; 178 179 err = getgrnam_r( &grpname_list[index], grp_ptr, gbuf, BUFSIZE, &tmp_ptr); 180 // non-NULL err means failure and NULL result ptr means no matching 181 // entry 182 if (err) { 183 debug("error: %s -> %s", &grpname_list[index], strerror(err)); 184 res->re_errors++; 185 } 186 else if ( !tmp_ptr) { 187 debug("not found: %s", &grpname_list[index] ); 188 res->re_errors++; 189 } 190 } 191 else { 192 errno = 0; 193 grp = getgrnam( &grpname_list[index] ); 194 195 if (!grp) { 196 if (errno) { 197 debug("error: %s -> %s", &grpname_list[index], strerror(errno)); 198 res->re_errors++; 199 } 200 else { 201 debug("not found: %s", &grpname_list[index] ); 202 res->re_errors++; 203 } 204 } 205 } 206 } 207 res->re_count = i; 208 209 return (0); 210} 211 212// We need to release all the structures we allocated in benchmark_initrun() 213int 214benchmark_finirun(void *tsd) 215{ 216 // tsd_t *ts = (tsd_t *)tsd; 217 debug("benchmark_finiworker: deallocating structures"); 218 219 free (grpname_list); 220 221 return (0); 222} 223 224char * 225benchmark_result() 226{ 227 static char result = '\0'; 228 debug("benchmark_result"); 229 return (&result); 230} 231 232