1/* 2 * Samba, configurable PMDA 3 * 4 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of version 2 of the GNU General Public License as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it would be useful, but 11 * WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 * 14 * Further, this software is distributed without any warranty that it is 15 * free of the rightful claim of any third person regarding infringement 16 * or the like. Any license provided herein, whether implied or 17 * otherwise, applies only to this software file. Patent licenses, if 18 * any, provided herein do not apply to combinations of this program with 19 * other software, or any other product whatsoever. 20 * 21 * You should have received a copy of the GNU General Public License along 22 * with this program; if not, write the Free Software Foundation, Inc., 59 23 * Temple Place - Suite 330, Boston MA 02111-1307, USA. 24 * 25 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 26 * Mountain View, CA 94043, or: 27 * 28 * http://www.sgi.com 29 * 30 * For further information regarding this notice, see: 31 * 32 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 33 */ 34 35typedef int BOOL; 36 37#define IRIX 1 38 39#include <stdio.h> 40#include <sys/shm.h> 41#include <pcp/pmapi.h> 42#ifdef IRIX 43#include <pcp/impl.h> 44#endif 45#include <pcp/pmda.h> 46#include "domain.h" 47#include "profile.h" 48#include "metrics.h" 49 50static pmdaInstid *counttime = NULL; 51static pmdaInstid *bytes = NULL; 52 53/* 54 * List of instance domains 55 */ 56 57static pmdaIndom indomtab[] = { 58 {COUNT_TIME_INDOM,0,NULL}, 59 {BYTE_INDOM,0,NULL} 60}; 61/* 62 * all metrics supported in this PMDA - one table entry for each 63 */ 64 65static pmdaMetric metrictab[] = { 66/* smbd.smb_count */ 67 { NULL, { PMDA_PMID(0,0), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 68 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 69/* smbd.uid_changes */ 70 { NULL, { PMDA_PMID(0,1), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 71 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 72/* statcache.lookups */ 73 { NULL, { PMDA_PMID(1,0), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 74 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 75/* statcache.misses */ 76 { NULL, { PMDA_PMID(1,1), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 77 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 78/* statcache.hits */ 79 { NULL, { PMDA_PMID(1,2), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 80 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 81/* writecache.num_caches */ 82 { NULL, { PMDA_PMID(2,0), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, 83 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 84/* writecache.allocated_caches */ 85 { NULL, { PMDA_PMID(2,1), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_INSTANT, 86 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 87/* writecache.read_hits */ 88 { NULL, { PMDA_PMID(2,2), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 89 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 90/* writecache.total_writes */ 91 { NULL, { PMDA_PMID(2,3), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 92 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 93/* writecache.init_writes */ 94 { NULL, { PMDA_PMID(2,4), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 95 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 96/* writecache.abutted_writes */ 97 { NULL, { PMDA_PMID(2,5), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 98 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 99/* writecache.perfect_writes */ 100 { NULL, { PMDA_PMID(2,6), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 101 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 102/* writecache.direct_writes */ 103 { NULL, { PMDA_PMID(2,7), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 104 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 105/* writecache.non_oplock_writes */ 106 { NULL, { PMDA_PMID(2,8), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 107 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 108/* writecache.seek_flush */ 109 { NULL, { PMDA_PMID(2,9), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 110 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 111/* writecache.read_flush */ 112 { NULL, { PMDA_PMID(2,10), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 113 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 114/* writecache.write_flush */ 115 { NULL, { PMDA_PMID(2,11), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 116 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 117/* writecache.readraw_flush */ 118 { NULL, { PMDA_PMID(2,12), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 119 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 120/* writecache.oplock_rel_flush */ 121 { NULL, { PMDA_PMID(2,13), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 122 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 123/* writecache.close_flush */ 124 { NULL, { PMDA_PMID(2,14), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 125 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 126/* writecache.sync_flush */ 127 { NULL, { PMDA_PMID(2,15), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 128 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 129/* writecache.size_change_flush */ 130 { NULL, { PMDA_PMID(2,16), PM_TYPE_U32, PM_INDOM_NULL, PM_SEM_COUNTER, 131 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 132/* counts instance domain */ 133 { NULL, { PMDA_PMID(3,0), PM_TYPE_U32, COUNT_TIME_INDOM, PM_SEM_COUNTER, 134 { 0,0,1,0,0,PM_COUNT_ONE} }, }, 135/* times instance domain */ 136 { NULL, { PMDA_PMID(4,0), PM_TYPE_U32, COUNT_TIME_INDOM, PM_SEM_COUNTER, 137 { 0,1,0,0,PM_TIME_USEC,0} }, }, 138/* bytes instance domain */ 139 { NULL, { PMDA_PMID(5,0), PM_TYPE_U32, BYTE_INDOM, PM_SEM_COUNTER, 140 { 1,0,0,PM_SPACE_BYTE,0,0} }, } 141 142}; 143 144extern int errno; 145struct profile_stats *stats; 146struct profile_header *shmheader; 147int shmid = -1; 148 149 150int 151samba_fetchCallBack(pmdaMetric *mdesc, unsigned int inst, pmAtomValue *atom) 152{ 153 __pmID_int *idp = (__pmID_int *)&(mdesc->m_desc.pmid); 154 155 156 if (inst != PM_IN_NULL && mdesc->m_desc.indom == PM_INDOM_NULL) 157 return PM_ERR_INST; 158 159 if (idp->cluster == 0) { 160 switch (idp->item) { 161 case 0: /* smbd.smb_count */ 162 atom->ul = stats->smb_count; 163 break; 164 case 1: /* smb.uid_changes */ 165 atom->ul = stats->uid_changes; 166 break; 167 default: 168 return PM_ERR_PMID; 169 } 170 } 171 else if (idp->cluster == 1) { /* statcache */ 172 switch (idp->item) { 173 case 0: /* statcache.lookups */ 174 atom->ul = stats->statcache_lookups; 175 break; 176 case 1: /* statcache.misses */ 177 atom->ul = stats->statcache_misses; 178 break; 179 case 2: /* statcache.hits */ 180 atom->ul = stats->statcache_hits; 181 break; 182 default: 183 return PM_ERR_PMID; 184 } 185 } 186 else if (idp->cluster == 2) { /* writecache */ 187 switch (idp->item) { 188 case 0: /* writecache.num_caches */ 189 atom->ul = stats->writecache_num_write_caches; 190 break; 191 case 1: /* writecache.allocated_caches */ 192 atom->ul = stats->writecache_allocated_write_caches; 193 break; 194 case 2: /* writecache.read_hits */ 195 atom->ul = stats->writecache_read_hits; 196 break; 197 case 3: /* writecache.total_writes */ 198 atom->ul = stats->writecache_total_writes; 199 break; 200 case 4: /* writecache.init_writes */ 201 atom->ul = stats->writecache_init_writes; 202 break; 203 case 5: /* writecache.abutted_writes */ 204 atom->ul = stats->writecache_abutted_writes; 205 break; 206 case 6: /* writecache.perfect_writes */ 207 atom->ul = stats->writecache_num_perfect_writes; 208 break; 209 case 7: /* writecache.direct_writes */ 210 atom->ul = stats->writecache_direct_writes; 211 break; 212 case 8: /* writecache.non_oplock_writes */ 213 atom->ul = stats->writecache_non_oplock_writes; 214 break; 215 case 9: /* writecache.seek_flush */ 216 atom->ul = stats->writecache_flushed_writes[SEEK_FLUSH]; 217 break; 218 case 10: /* writecache.read_flush */ 219 atom->ul = stats->writecache_flushed_writes[READ_FLUSH]; 220 break; 221 case 11: /* writecache.write_flush */ 222 atom->ul = stats->writecache_flushed_writes[WRITE_FLUSH]; 223 break; 224 case 12: /* writecache.readraw_flush */ 225 atom->ul = stats->writecache_flushed_writes[READRAW_FLUSH]; 226 break; 227 case 13: /* writecache.oplock_rel_flush */ 228 atom->ul = stats->writecache_flushed_writes[OPLOCK_RELEASE_FLUSH]; 229 break; 230 case 14: /* writecache.close_flush */ 231 atom->ul = stats->writecache_flushed_writes[CLOSE_FLUSH]; 232 break; 233 case 15: /* writecache.sync_flush */ 234 atom->ul = stats->writecache_flushed_writes[SYNC_FLUSH]; 235 break; 236 case 16: /* writecache.size_change_flush */ 237 atom->ul = stats->writecache_flushed_writes[SIZECHANGE_FLUSH]; 238 break; 239 default: 240 return PM_ERR_PMID; 241 } 242 } 243 else if (idp->cluster == 3) { /* counts */ 244 if (idp->item == 0) { 245 if (inst < indomtab[COUNT_TIME_INDOM].it_numinst) { 246 unsigned *p; 247 248 p = (unsigned *)((unsigned)stats + samba_counts[inst].offset); 249 atom->ul = *p; 250 } 251 else 252 return PM_ERR_INST; 253 } 254 else 255 return PM_ERR_PMID; 256 } 257 else if (idp->cluster == 4) { /* times */ 258 if (idp->item == 0) { 259 if (inst < indomtab[COUNT_TIME_INDOM].it_numinst) { 260 unsigned *p; 261 262 p = (unsigned *)((unsigned)stats + samba_times[inst].offset); 263 atom->ul = *p; 264 } 265 else 266 return PM_ERR_INST; 267 } 268 else 269 return PM_ERR_PMID; 270 } 271 else if (idp->cluster == 5) { /* bytes */ 272 if (idp->item == 0) { 273 if (inst < indomtab[BYTE_INDOM].it_numinst) { 274 unsigned *p; 275 276 p = (unsigned *)((unsigned)stats + samba_bytes[inst].offset); 277 atom->ul = *p; 278 } 279 else 280 return PM_ERR_INST; 281 } 282 else 283 return PM_ERR_PMID; 284 } 285 else 286 return PM_ERR_PMID; 287 return 0; 288} 289 290 291void 292samba_init(pmdaInterface *dp) 293{ 294 int inst_count, i; 295 296 if (dp->status != 0) 297 return; 298 299 if ((shmid = shmget(PROF_SHMEM_KEY, 0, 0)) == -1) { 300 fprintf(stderr, "shmid: %s\n", strerror(errno)); 301 fprintf(stderr, "samba not compiled with profile support or not running\n"); 302 exit(1); 303 } 304 shmheader = (struct profile_header *)shmat(shmid, NULL, SHM_RDONLY); 305 if ((int)shmheader == -1) { 306 fprintf(stderr, "shmat: %s\n", strerror(errno)); 307 exit(1); 308 } 309 310/* 311 * Initialize lists of instances 312 */ 313 314 inst_count = sizeof(samba_counts)/sizeof(samba_counts[0]); 315 counttime = (pmdaInstid *)malloc(inst_count * sizeof(pmdaInstid)); 316 if (counttime == NULL) { 317 __pmNoMem("count&time",inst_count * sizeof(pmdaInstid),PM_FATAL_ERR); 318 /* NOTREACHED*/ 319 } 320 for (i = 0; i < inst_count; i++) { 321 counttime[i].i_inst = i; 322 counttime[i].i_name = samba_counts[i].name; 323 } 324 indomtab[COUNT_TIME_INDOM].it_numinst = inst_count; 325 indomtab[COUNT_TIME_INDOM].it_set = counttime; 326 327 inst_count = sizeof(samba_bytes)/sizeof(samba_bytes[0]); 328 bytes = (pmdaInstid *)malloc(inst_count * sizeof(pmdaInstid)); 329 if (bytes == NULL) { 330 __pmNoMem("bytes",inst_count * sizeof(pmdaInstid),PM_FATAL_ERR); 331 /* NOTREACHED*/ 332 } 333 for (i = 0; i < inst_count; i++) { 334 bytes[i].i_inst = i; 335 bytes[i].i_name = samba_bytes[i].name; 336 } 337 indomtab[BYTE_INDOM].it_numinst = inst_count; 338 indomtab[BYTE_INDOM].it_set = bytes; 339 340 341 pmdaSetFetchCallBack(dp, samba_fetchCallBack); 342 pmdaInit(dp, indomtab, sizeof(indomtab)/sizeof(indomtab[0]), 343 metrictab, sizeof(metrictab)/sizeof(metrictab[0])); 344 345 /* validate the data */ 346 if (!shmheader) /* not mapped yet */ 347 fprintf(stderr, "samba_init: shmem not mapped\n"); 348 else if (shmheader->prof_shm_magic != PROF_SHM_MAGIC) 349 fprintf(stderr, "samba_init: bad magic\n"); 350 else if (shmheader->prof_shm_version != PROF_SHM_VERSION) 351 fprintf(stderr, "samba_init: bad version %X\n", 352 shmheader->prof_shm_version); 353 else { 354 stats = &shmheader->stats; 355 return; /* looks OK */ 356 } 357 exit(1); 358} 359 360 361int 362main(int argc, char **argv) 363{ 364 int err = 0; 365 char *p; 366 pmdaInterface dispatch; 367 368 for (p = pmProgname = argv[0]; *p; p++) 369 if (*p == '/') pmProgname = p+1; 370 371 pmdaDaemon(&dispatch, PMDA_INTERFACE_2, pmProgname, SAMBA, 372 "samba.log", "/var/pcp/pmdas/samba/help"); 373 374 if (pmdaGetOpt(argc, argv, "D:d:l:?", &dispatch, &err) != EOF) { 375 fprintf(stderr, "Usage: %s [options]\n\n\ 376Options:\n\ 377 -d domain use domain (numeric) for metrics domain of PMDA\n\ 378 -l logfile write log into logfile rather than using default log name\n", 379 pmProgname); 380 exit(1); 381 } 382 383 pmdaOpenLog(&dispatch); 384 samba_init(&dispatch); 385 pmdaConnect(&dispatch); 386 pmdaMain(&dispatch); 387 388 exit(0); 389 /*NOTREACHED*/ 390} 391