/* * Given a double, multiple by FLOAT_MULT and then * typecast to a uint64_t in host byte order, convert to network byte order * store in buffer, and adjust buffer counters. * NOTE: There is an IEEE standard format for double. */ void packdouble(double val, Buf buffer) { uint64_t nl; union { double d; uint64_t u; } uval; /* The 0.5 is here to round off. We have found on systems going out * more than 15 decimals will mess things up, but this corrects it. */ uval.d = (val * FLOAT_MULT); nl = HTON_uint64(uval.u); if (remaining_buf(buffer) < sizeof(nl)) { if ((buffer->size + BUF_SIZE) > MAX_BUF_SIZE) { error("%s: Buffer size limit exceeded (%u > %u)", __func__, (buffer->size + BUF_SIZE), MAX_BUF_SIZE); return; } buffer->size += BUF_SIZE; xrealloc_nz(buffer->head, buffer->size); } memcpy(&buffer->head[buffer->processed], &nl, sizeof(nl)); buffer->processed += sizeof(nl); }
/* * Given a 64-bit integer in host byte order, convert to network byte order * store in buffer, and adjust buffer counters. */ void pack64(uint64_t val, Buf buffer) { uint64_t nl = HTON_uint64(val); if (remaining_buf(buffer) < sizeof(nl)) { if (buffer->size > (MAX_BUF_SIZE - BUF_SIZE)) { error("pack64: buffer size too large"); return; } buffer->size += BUF_SIZE; xrealloc(buffer->head, buffer->size); } memcpy(&buffer->head[buffer->processed], &nl, sizeof(nl)); buffer->processed += sizeof(nl); }
/* * Given a 64-bit integer in host byte order, convert to network byte order * store in buffer, and adjust buffer counters. */ void pack64(uint64_t val, Buf buffer) { uint64_t nl = HTON_uint64(val); if (remaining_buf(buffer) < sizeof(nl)) { if ((buffer->size + BUF_SIZE) > MAX_BUF_SIZE) { error("%s: Buffer size limit exceeded (%u > %u)", __func__, (buffer->size + BUF_SIZE), MAX_BUF_SIZE); return; } buffer->size += BUF_SIZE; xrealloc_nz(buffer->head, buffer->size); } memcpy(&buffer->head[buffer->processed], &nl, sizeof(nl)); buffer->processed += sizeof(nl); }
static void *_heartbeat_thread(void *no_data) { /* * The frequency needs to be faster than slurmctld_timeout, * or the backup controller may try to assume control. * One-fourth is very conservative, one-half should be sufficient. * Have it happen at least every 30 seconds if the timeout is quite * large. */ int beat = MIN(slurmctld_conf.slurmctld_timeout / 4, 30); time_t now; uint64_t nl; struct timespec ts = {0, 0}; char *reg_file, *new_file; int fd; debug("Heartbeat thread started, beating every %d seconds.", beat); slurm_mutex_lock(&heartbeat_mutex); while (heart_beating) { now = time(NULL); ts.tv_sec = now + beat; debug3("Heartbeat at %ld", now); /* * Rebuild file path each beat just in case someone changes * StateSaveLocation and runs reconfigure. */ reg_file = xstrdup_printf("%s/heartbeat", slurmctld_conf.state_save_location); new_file = xstrdup_printf("%s.new", reg_file); nl = HTON_uint64((uint64_t) now); fd = open(new_file, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC, 0600); if (fd < 0) { error("%s: heartbeat file creation failed to %s.", __func__, new_file); goto delay; } if (write(fd, &nl, sizeof(uint64_t)) != sizeof(uint64_t)) { error("%s: heartbeat write failed to %s.", __func__, new_file); close(fd); (void) unlink(new_file); goto delay; } if (write(fd, &backup_inx, sizeof(int)) != sizeof(int)) { error("%s: heartbeat write failed to %s.", __func__, new_file); close(fd); (void) unlink(new_file); goto delay; } if (fsync_and_close(fd, "heartbeat")) { (void) unlink(new_file); goto delay; } /* shuffle files around */ (void) unlink(reg_file); if (link(new_file, reg_file)) debug("%s: unable to create link for %s -> %s, %m", __func__, new_file, reg_file); (void) unlink(new_file); delay: xfree(reg_file); xfree(new_file); slurm_cond_timedwait(&heartbeat_cond, &heartbeat_mutex, &ts); } slurm_mutex_unlock(&heartbeat_mutex); return NULL; }