/* * _thread_update_node_energy calls _read_ipmi_values and updates all values * for node consumption */ static int _thread_update_node_energy(void) { int rc = SLURM_SUCCESS; if (local_energy->current_watts == NO_VAL) return rc; rc = _read_ipmi_values(); if (rc == SLURM_SUCCESS) { uint32_t additional_consumption; if (previous_update_time == 0) { additional_consumption = 0; previous_update_time = last_update_time; } else { additional_consumption = _get_additional_consumption( previous_update_time, last_update_time, local_energy->base_watts, local_energy->current_watts); } if (local_energy->current_watts != 0) { local_energy->base_watts = local_energy->current_watts; local_energy->current_watts = last_update_watt; local_energy->previous_consumed_energy = local_energy->consumed_energy; local_energy->consumed_energy += additional_consumption; local_energy->base_consumed_energy = additional_consumption; } if (local_energy->current_watts == 0) { local_energy->consumed_energy = 0; local_energy->base_watts = 0; local_energy->current_watts = last_update_watt; } local_energy->poll_time = time(NULL); } if (debug_flags & DEBUG_FLAG_ENERGY) { info("ipmi-thread = %d sec, current %d Watts, " "consumed %d Joules %d new", (int) (last_update_time - previous_update_time), local_energy->current_watts, local_energy->consumed_energy, local_energy->base_consumed_energy); } return rc; }
/* * _thread_update_node_energy calls _read_ipmi_values and updates all values * for node consumption */ static int _thread_update_node_energy(void) { xcc_raw_single_data_t *xcc_raw; static uint16_t overflows = 0; /* Number of overflows of the counter */ int elapsed = 0; static uint64_t first_consumed_energy = 0; xcc_raw = _read_ipmi_values(); if (!xcc_raw) { error("%s could not read XCC ipmi values", __func__); return SLURM_ERROR; } if (!xcc_energy.poll_time) { /* * First number from the slurmd. We will figure out the usage * by subtracting this each time. */ first_consumed_energy = xcc_raw->j; xcc_energy.consumed_energy = 0; xcc_energy.base_consumed_energy = 0; xcc_energy.previous_consumed_energy = 0; xcc_energy.ave_watts = 0; } else { xcc_energy.previous_consumed_energy = xcc_energy.consumed_energy; /* Detect first overflow */ if (!overflows && xcc_raw->j < xcc_energy.consumed_energy) { xcc_energy.consumed_energy = IPMI_XCC_OVERFLOW - first_consumed_energy + xcc_raw->j; overflows++; } else if (!overflows && (xcc_raw->j >= xcc_energy.consumed_energy)) { xcc_energy.consumed_energy = xcc_raw->j; xcc_energy.consumed_energy -= first_consumed_energy; } else if (overflows) { /* * Offset = First overflow + consecutive overflows * If it happens that the offset + xcc_raw->j is less * than the past consumed energy, it means that we * overflowed and must add a new overflow to the count */ uint64_t offset = IPMI_XCC_OVERFLOW - first_consumed_energy + (IPMI_XCC_OVERFLOW * (overflows-1)); if ((offset + xcc_raw->j) < xcc_energy.consumed_energy) { overflows++; xcc_energy.consumed_energy = offset + IPMI_XCC_OVERFLOW + xcc_raw->j; } else { xcc_energy.consumed_energy += offset + xcc_raw->j; } } xcc_energy.base_consumed_energy = xcc_energy.consumed_energy - xcc_energy.previous_consumed_energy; elapsed = xcc_raw->s - xcc_energy.poll_time; } xcc_energy.poll_time = xcc_raw->s; xfree(xcc_raw); if (elapsed && xcc_energy.base_consumed_energy) { static uint64_t readings = 0; xcc_energy.current_watts = round((double)xcc_energy.base_consumed_energy / (double)elapsed); /* ave_watts is used as TresUsageOutAve (AvePower) */ xcc_energy.ave_watts = ((xcc_energy.ave_watts * readings) + xcc_energy.current_watts) / (readings + 1); readings++; } if (debug_flags & DEBUG_FLAG_ENERGY) { info("%s: XCC current_watts: %u consumed energy last interval: %"PRIu64"(current reading %"PRIu64") Joules, elapsed time: %u Seconds, first read energy counter val: %"PRIu64" ave watts: %u", __func__, xcc_energy.current_watts, xcc_energy.base_consumed_energy, xcc_energy.consumed_energy, elapsed, first_consumed_energy, xcc_energy.ave_watts); } return SLURM_SUCCESS; }