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 <membership.h> 40#include <pwd.h> 41#include <uuid/uuid.h> 42 43#if DEBUG 44# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) 45#else 46# define debug(fmt, args...) 47#endif 48 49 50// Correct use case 51// 52// mbr_check_membership -E -L -S -W -B 200 -C 10 -g 1211-1213 -u 5000-5200 53// 54// libMicro default benchmark run options are "-E -C 200 -L -S -W" 55// 56// -B is batch size: loop iteration per each benchmark run. (default: 100) 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// -u uid range in the form of "min-max". For example, -u 5000-5200 62// -g gid range or gid 63 64/* 65 * Your state variables should live in the tsd_t struct below 66 */ 67typedef struct { 68} tsd_t; 69 70#define INVALID_ID -1 71 72static uid_t uid_min = INVALID_ID; 73static gid_t gid_min = INVALID_ID;; 74 75static int uid_range = 0; // uid_max = uid_min + uid_range 76static int gid_range = 0; // gid_max = gid_min + gid_range 77 78static uuid_t *u_uuid_list = NULL; // user uuid list 79static uuid_t *g_uuid_list = NULL; // group uuid list 80 81int 82benchmark_init() 83{ 84 debug("benchmark_init"); 85 (void) sprintf(lm_optstr, "g:u:"); 86 87 lm_tsdsize = sizeof(tsd_t); 88 lm_defB = 100; 89 90 (void) sprintf(lm_usage, 91 "\n ------- mbr_check_membership specific options\n" 92 " [-u UID range (min-max)]\n" 93 " [-g GID or GID range (gid or min-max)]\n" 94 "\n" ); 95 return (0); 96} 97 98int 99parse_range(uint *min, int *offset, char *buf) 100{ 101 char *value, *tmp_ptr = strdup(buf); 102 int range=0; 103 debug("parse_range"); 104 105 value = strsep(&tmp_ptr, "-"); 106 *min = atoi(value); 107 debug("min = %d", *min); 108 if (tmp_ptr) { 109 value = strsep(&tmp_ptr, "-"); 110 range = atoi(value); 111 if (range < *min) { 112 printf("max id should be larger than min id\n"); 113 return -1; 114 } 115 *offset = range - *min; 116 debug("range = %d", *offset); 117 } 118 119 return 0; 120 121} 122 123/* 124 * This is where you parse your lower-case arguments. 125 */ 126int 127benchmark_optswitch(int opt, char *optarg) 128{ 129 debug("benchmark_optswitch"); 130 131 switch (opt) { 132 case 'g': // GID or GID range 133 return parse_range( &gid_min, &gid_range, optarg); 134 break; 135 136 case 'u': // UID range 137 return parse_range( &uid_min, &uid_range, optarg); 138 break; 139 default: 140 return -1; 141 } 142 143 return 0; 144} 145 146 147// Initialize all structures that will be used in benchmark() 148// 1. make local or network node for OD query 149// 2. create user key 150int 151benchmark_initrun(void *tsd) 152{ 153 int i; 154 //tsd_t *ts = (tsd_t *)tsd; 155 156 debug("benchmark_initrun"); 157 158 if (uid_min == INVALID_ID || gid_min == INVALID_ID) { 159 printf("Both -u and -g need to be specified\n"); 160 return -1; 161 } 162 163 // create an array of usernames to use in benchmark before their use 164 // realtime generation in benchmark effects performance measurements 165 166 u_uuid_list = malloc( sizeof(*u_uuid_list) * (uid_range+1) ); 167 g_uuid_list = malloc( sizeof(*g_uuid_list) * (gid_range+1) ); 168 169 for (i = 0; i <= uid_range; i++) { 170 171 if (mbr_uid_to_uuid(uid_min+i, u_uuid_list[i])) { 172 printf("error converting uid %d to UUID\n", uid_min+i); 173 return -1; 174 } 175 } 176 177 for (i = 0; i <= gid_range; i++) { 178 179 if (mbr_gid_to_uuid(gid_min+i, g_uuid_list[i])) { 180 printf("error converting gid %d to UUID\n", gid_min+i); 181 return -1; 182 } 183 } 184 185 return (0); 186} 187 188int 189benchmark(void *tsd, result_t *res) 190{ 191 int i, index, gindex, err, isMember=0; 192 //tsd_t *ts = (tsd_t *)tsd; 193 194#ifdef DEBUG 195 uid_t uid; 196 int id_type; 197#endif 198 199 res->re_errors = 0; 200 201 // debug("in to benchmark - optB = %i", lm_optB); 202 203 for (i = 0; i < lm_optB; i++) { 204 205 index = random() % (uid_range+1); 206 gindex = random() % (gid_range+1); 207 err = mbr_check_membership(u_uuid_list[index], g_uuid_list[gindex], &isMember); 208 209#ifdef DEBUG 210 //mbr_uuid_to_id(u_uuid_list[index], &uid, &id_type); 211 //debug ("loop %d: uid %d is %s (gindex %d)", i, uid, (isMember)?"member":"not a member", gindex); 212#endif 213 214 if (err) { 215 if (err == EIO) { 216 debug("mbr_check_membership returned EIO. Unable to communicate with DS daemon"); 217 } 218 else if (err == ENOENT) { 219 debug("mbr_check_membership returned ENOENT. User not found"); 220 } 221 else { 222 debug("error: %s", strerror(err)); 223 } 224 res->re_errors++; 225 } 226 } 227 res->re_count = i; 228 229 return (0); 230} 231 232 233// We need to release all the structures we allocated in benchmark_initrun() 234int 235benchmark_finirun(void *tsd) 236{ 237 //tsd_t *ts = (tsd_t *)tsd; 238 239 debug("benchmark_result: deallocating structures"); 240 241 free(u_uuid_list); 242 free(g_uuid_list); 243 244 return (0); 245} 246 247char * 248benchmark_result() 249{ 250 static char result = '\0'; 251 debug("benchmark_result"); 252 return (&result); 253} 254 255