static ERL_NIF_TERM read_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ks_returner_t *ret; ERL_NIF_TERM term, statistics; ks_handle_t *handle; ks_instance_t *ksi; ks_nvpair_t *nvpair; char *ks_number; ks_selector_t *selector; int matched; ret = new_returner(env); if (argc < 1 || argc > 6) { return EKSTAT_RETURN(enif_make_badarg(ret->env)); } if (!enif_get_resource(env, argv[0], kstat_handle, (void **)(&handle))) { return EKSTAT_RETURN(enif_make_badarg(ret->env)); } selector = new_selector(ret); if (ret->ready == B_TRUE) { if ((void *)(selector) != NULL) { free_selector(selector); } return EKSTAT_RETURN(ret->term); } switch (argc) { case 2: (void) ks_selector_arg(ret, &selector->ks_class, argv[1]); break; case 3: (void) ks_selector_arg(ret, &selector->ks_class, argv[1]); (void) ks_selector_arg(ret, &selector->ks_module, argv[2]); break; case 4: (void) ks_selector_arg(ret, &selector->ks_class, argv[1]); (void) ks_selector_arg(ret, &selector->ks_module, argv[2]); (void) ks_selector_arg(ret, &selector->ks_instance, argv[3]); break; case 5: (void) ks_selector_arg(ret, &selector->ks_class, argv[1]); (void) ks_selector_arg(ret, &selector->ks_module, argv[2]); (void) ks_selector_arg(ret, &selector->ks_instance, argv[3]); (void) ks_selector_arg(ret, &selector->ks_name, argv[4]); break; case 6: (void) ks_selector_arg(ret, &selector->ks_class, argv[1]); (void) ks_selector_arg(ret, &selector->ks_module, argv[2]); (void) ks_selector_arg(ret, &selector->ks_instance, argv[3]); (void) ks_selector_arg(ret, &selector->ks_name, argv[4]); (void) ks_selector_arg(ret, &selector->ks_statistic, argv[5]); break; default: break; } if (ret->ready == B_TRUE) { free_selector(selector); return EKSTAT_RETURN(ret->term); } term = enif_make_list(env, 0); /* Iterate over each instance */ for (ksi = list_head(&handle->instances_list); ksi != NULL; ksi = list_next(&handle->instances_list, ksi)) { matched = 0; statistics = (ERL_NIF_TERM)(NULL); (void) asprintf(&ks_number, "%d", ksi->ks_instance); if ( !(ks_match(ret, ksi->ks_module, &selector->ks_module) && ks_match(ret, ksi->ks_name, &selector->ks_name) && ks_match(ret, ks_number, &selector->ks_instance) && ks_match(ret, ksi->ks_class, &selector->ks_class)) ) { free(ks_number); if (ret->ready == B_TRUE) { free_selector(selector); return EKSTAT_RETURN(ret->term); } continue; } free(ks_number); /* Finally iterate over each statistic */ for (nvpair = list_head(&ksi->ks_nvlist); nvpair != NULL; nvpair = list_next(&ksi->ks_nvlist, nvpair)) { if (!ks_match(ret, nvpair->name, &selector->ks_statistic)) { if (ret->ready == B_TRUE) { free_selector(selector); return EKSTAT_RETURN(ret->term); } continue; } if ((void *)(statistics) == NULL) { statistics = enif_make_list(env, 0); } matched = 1; statistics = enif_make_list_cell(env, ks_nvpair_term(ret, nvpair), statistics); } if (matched == 1) { term = enif_make_list_cell(env, ks_instance_term(ret, ksi, statistics), term); } } free_selector(selector); return EKSTAT_RETURN(term); }
/* * Iterate over all kernel statistics and save matches. */ static void ks_instances_read(kstat_ctl_t *kc) { kstat_raw_reader_t save_raw = NULL; kid_t id; ks_selector_t *selector; ks_instance_t *ksi; ks_instance_t *tmp; kstat_t *kp; boolean_t skip; for (kp = kc->kc_chain; kp != NULL; kp = kp->ks_next) { /* Don't bother storing the kstat headers */ if (strncmp(kp->ks_name, "kstat_", 6) == 0) { continue; } /* Don't bother storing raw stats we don't understand */ if (kp->ks_type == KSTAT_TYPE_RAW) { save_raw = lookup_raw_kstat_fn(kp->ks_module, kp->ks_name); if (save_raw == NULL) { #ifdef REPORT_UNKNOWN (void) fprintf(stderr, "Unknown kstat type %s:%d:%s - " "%d of size %d\n", kp->ks_module, kp->ks_instance, kp->ks_name, kp->ks_ndata, kp->ks_data_size); #endif continue; } } /* * Iterate over the list of selectors and skip * instances we dont want. We filter for statistics * later, as we dont know them yet. */ skip = B_TRUE; selector = list_head(&selector_list); while (selector != NULL) { if (ks_match(kp->ks_module, &selector->ks_module) && ks_match(kp->ks_name, &selector->ks_name)) { skip = B_FALSE; break; } selector = list_next(&selector_list, selector); } if (skip) { continue; } /* * Allocate a new instance and fill in the values * we know so far. */ ksi = (ks_instance_t *)malloc(sizeof (ks_instance_t)); if (ksi == NULL) { perror("malloc"); exit(3); } list_link_init(&ksi->ks_next); (void) strlcpy(ksi->ks_zone, "global", KSTAT_STRLEN); (void) strlcpy(ksi->ks_module, kp->ks_module, KSTAT_STRLEN); (void) strlcpy(ksi->ks_name, kp->ks_name, KSTAT_STRLEN); (void) strlcpy(ksi->ks_class, kp->ks_class, KSTAT_STRLEN); ksi->ks_instance = kp->ks_instance; ksi->ks_snaptime = kp->ks_snaptime; ksi->ks_type = kp->ks_type; list_create(&ksi->ks_nvlist, sizeof (ks_nvpair_t), offsetof(ks_nvpair_t, nv_next)); SAVE_HRTIME_X(ksi, "crtime", kp->ks_crtime); SAVE_HRTIME_X(ksi, "snaptime", kp->ks_snaptime); if (g_pflg) { SAVE_STRING_X(ksi, "class", kp->ks_class); } /* Insert this instance into a sorted list */ tmp = list_head(&instances_list); while (tmp != NULL && compare_instances(ksi, tmp) > 0) tmp = list_next(&instances_list, tmp); list_insert_before(&instances_list, tmp, ksi); /* Read the actual statistics */ id = kstat_read(kc, kp, NULL); if (id == -1) { #ifdef REPORT_UNKNOWN perror("kstat_read"); #endif continue; } switch (kp->ks_type) { case KSTAT_TYPE_RAW: save_raw(kp, ksi); break; case KSTAT_TYPE_NAMED: save_named(kp, ksi); break; case KSTAT_TYPE_INTR: save_intr(kp, ksi); break; case KSTAT_TYPE_IO: save_io(kp, ksi); break; case KSTAT_TYPE_TIMER: save_timer(kp, ksi); break; default: assert(B_FALSE); /* Invalid type */ break; } } }