/* given a username, a jobname, and a start time, lookup (or create) the id for this job */ int scr_log_job(const char* username, const char* jobname, time_t start) { int rc = SCR_SUCCESS; if (scr_db_enable) { if (username != NULL && jobname != NULL) { int rc = scr_mysql_register_job(username, jobname, start, &scr_db_jobid); if (rc != SCR_SUCCESS) { scr_err("Failed to register job for username %s and jobname %s, disabling database logging @ %s:%d", username, jobname, __FILE__, __LINE__ ); scr_db_enable = 0; rc = SCR_FAILURE; } } else { scr_err("Failed to read username or jobname from environment, disabling database logging @ %s:%d", __FILE__, __LINE__ ); scr_db_enable = 0; rc = SCR_FAILURE; } } return rc; }
/* pack an unsigned 64 bit value to specified buffer in network order */ int scr_pack_uint64_t(void* buf, size_t buf_size, size_t* buf_pos, uint64_t val) { /* check that we have a valid pointer to a buffer position value */ if (buf == NULL || buf_pos == NULL) { scr_err("NULL pointer to buffer or buffer position @ %s:%d", __FILE__, __LINE__ ); return SCR_FAILURE; } /* get current buffer position */ size_t pos = *buf_pos; /* compute final buffer position */ size_t pos_final = pos + sizeof(val); /* check that we won't overrun the buffer */ if (pos_final > buf_size) { scr_err("Attempting to pack too many bytes into buffer @ %s:%d", __FILE__, __LINE__ ); return SCR_FAILURE; } /* convert value to network order */ uint64_t val_network = scr_hton64(val); /* pack value into buffer */ memcpy(buf + pos, &val_network, sizeof(val_network)); /* update position */ *buf_pos = pos_final; return SCR_SUCCESS; }
/* connects to the SCR log database */ int scr_mysql_connect() { #ifdef HAVE_LIBMYSQLCLIENT /* create our type-string-to-id cache */ scr_db_types = scr_hash_new(); if (scr_db_types == NULL) { scr_err("Failed to create a hash to cache type string to id lookups @ %s:%d", __FILE__, __LINE__ ); return SCR_FAILURE; } /* initialize our database structure */ mysql_init(&scr_mysql); /* connect to the database */ if (! mysql_real_connect(&scr_mysql, scr_db_host, scr_db_user, scr_db_pass, scr_db_name, 0, NULL, 0)) { scr_err("Failed to connect to SCR log database %s on host %s @ %s:%d", scr_db_name, scr_db_host, __FILE__, __LINE__ ); return SCR_FAILURE; } #endif return SCR_SUCCESS; }
int scr_file_unlock(const char* file, int fd) { #ifdef SCR_FILE_LOCK_USE_FLOCK if (flock(fd, LOCK_UN) != 0) { scr_err("Failed to acquire file lock on %s: flock(%d, %d) errno=%d %s @ %s:%d", file, fd, LOCK_UN, errno, strerror(errno), __FILE__, __LINE__ ); return SCR_FAILURE; } #endif #ifdef SCR_FILE_LOCK_USE_FCNTL struct flock lck; lck.l_type = F_UNLCK; lck.l_whence = 0; lck.l_start = 0L; lck.l_len = 0L; //locking the entire file if(fcntl(fd, F_SETLK, &lck) < 0) { scr_err("Failed to acquire file read lock on %s: fnctl(%d, %d) errno=%d %s @ %s:%d", file, fd, F_UNLCK, errno, strerror(errno), __FILE__, __LINE__ ); return SCR_FAILURE; } #endif return SCR_SUCCESS; }
/* given a string, convert it to a double and write that value to val */ int scr_atod(char* str, double* val) { /* check that we have a string */ if (str == NULL) { scr_err("scr_atod: Can't convert NULL string to double @ %s:%d", __FILE__, __LINE__ ); return SCR_FAILURE; } /* check that we have a value to write to */ if (val == NULL) { scr_err("scr_atod: NULL address to store value @ %s:%d", __FILE__, __LINE__ ); return SCR_FAILURE; } /* convert string to double */ errno = 0; double value = strtod(str, NULL); if (errno == 0) { /* got a valid double, set our output parameter */ *val = value; } else { /* could not interpret value */ scr_err("scr_atod: Invalid double: %s @ %s:%d", str, __FILE__, __LINE__ ); return SCR_FAILURE; } return SCR_SUCCESS; }
/* lookup name in table, insert if it doesn't exist, and return id */ int scr_mysql_read_write_id(const char* table, const char* name, unsigned long* id) { int rc = SCR_SUCCESS; #ifdef HAVE_LIBMYSQLCLIENT /* if the value is already in the database, return its id */ rc = scr_mysql_read_id(table, name, id); if (rc == SCR_SUCCESS) { return SCR_SUCCESS; } /* didn't find the value in the db, so let's add it */ /* escape parameter */ char* qname = scr_mysql_quote_string(name); /* check that we got valid strings for each of our parameters */ if (qname == NULL) { scr_err("Failed to escape and quote one or more arguments @ %s:%d", __FILE__, __LINE__ ); return SCR_FAILURE; } /* construct the query */ char query[1024]; int n = snprintf(query, sizeof(query), "INSERT IGNORE INTO `%s` (`id`,`name`) VALUES (NULL, %s) ;", table, qname ); /* free the strings as they are now encoded into the query */ scr_free(&qname); /* check that we were able to construct the query ok */ if (n >= sizeof(query)) { scr_err("Insufficient buffer space (%lu bytes) to build query (%lu bytes) @ %s:%d", sizeof(query), n, __FILE__, __LINE__ ); return SCR_FAILURE; } /* execute the query */ if (scr_db_debug >= 1) { scr_dbg(0, "%s", query); } if (mysql_real_query(&scr_mysql, query, (unsigned int) strlen(query))) { scr_err("Insert failed, query = (%s), error = (%s) @ %s:%d", query, mysql_error(&scr_mysql), __FILE__, __LINE__ ); /* don't return failure, since another process may have just beat us to the punch */ /*return SCR_FAILURE;*/ } /* alright, now we should be able to read the id */ rc = scr_mysql_read_id(table, name, id); #endif return rc; }
/* lookups a type string and returns its id, * inserts string into types table if not found, * caches lookups to avoid database reading more than once */ int scr_mysql_type_id(const char* type, int* id) { #ifdef HAVE_LIBMYSQLCLIENT /* check that we don't have a NULL string */ if (type == NULL) { scr_err("Type string is NULL @ %s:%d", __FILE__, __LINE__ ); return SCR_FAILURE; } /* first check the hash in case we can avoid reading from the database */ unsigned long tmp_id; if (scr_hash_util_get_unsigned_long(scr_db_types, type, &tmp_id) == SCR_SUCCESS) { /* found our id from the hash, convert to an int and return */ *id = (int) tmp_id; return SCR_SUCCESS; } /* failed to find our id in the hash, lookup the id for our jobname */ if (scr_mysql_read_write_id("types", type, &tmp_id) != SCR_SUCCESS) { scr_err("Failed to find type_id for %s @ %s:%d", type, __FILE__, __LINE__ ); return SCR_FAILURE; } /* got our id, now cache the lookup */ scr_hash_util_set_unsigned_long(scr_db_types, type, tmp_id); /* cast the id down to an int */ *id = (int) tmp_id; #endif return SCR_SUCCESS; }
/* read in the summary file from dir */ static int scr_summary_read_v6(const scr_path* dir, scr_hash* summary_hash) { /* check that we got a pointer to a hash */ if (summary_hash == NULL) { return SCR_FAILURE; } /* assume that we'll fail */ int rc = SCR_FAILURE; /* build the summary filename */ scr_path* summary_path = scr_path_dup(dir); scr_path_append_str(summary_path, ".scr"); scr_path_append_str(summary_path, "summary.scr"); char* summary_file = scr_path_strdup(summary_path); /* check whether we can read the file before we actually try, * we take this step to avoid printing an error in scr_hash_read */ if (scr_file_is_readable(summary_file) != SCR_SUCCESS) { goto cleanup; } /* read in the summary hash file */ if (scr_hash_read(summary_file, summary_hash) != SCR_SUCCESS) { scr_err("Reading summary file %s @ %s:%d", summary_file, __FILE__, __LINE__ ); goto cleanup; } /* read the version from the summary hash */ int version; if (scr_hash_util_get_int(summary_hash, SCR_SUMMARY_KEY_VERSION, &version) != SCR_SUCCESS) { scr_err("Failed to read version from summary file %s @ %s:%d", summary_file, __FILE__, __LINE__ ); goto cleanup; } /* check that the version number matches */ if (version != SCR_SUMMARY_FILE_VERSION_6) { scr_err("Summary file %s is version %d instead of version %d @ %s:%d", summary_file, version, SCR_SUMMARY_FILE_VERSION_6, __FILE__, __LINE__ ); goto cleanup; } /* if we made it here, we successfully read the summary file as a hash */ rc = SCR_SUCCESS; cleanup: /* free the summary file string */ scr_free(&summary_file); scr_path_delete(&summary_path); return rc; }
/* allocate and return a string containing the node name */ char* scr_env_nodename() { char* name = NULL; #ifndef SCR_BGQ /* we just use the string returned by gethostname */ char hostname[256]; if (gethostname(hostname, sizeof(hostname)) == 0) { name = strdup(hostname); } else { scr_err("Call to gethostname failed @ %s:%d", __FILE__, __LINE__ ); } #else /* here, we derive a string from the personality */ Personality_t personality; unsigned int x, y, m, n, j, c; Kernel_GetPersonality(&personality, sizeof(personality)); bg_decodeComputeCardCoreOnNodeBoardUCI(personality.Kernel_Config.UCI,&x,&y,&m,&n,&j,&c); /* construct the hostname */ char hostname[256]; int num = snprintf( hostname, sizeof(hostname), "R%X%X-M%d-N%02d-J%02d-A%dof%d-B%dof%d-C%dof%d-D%dof%d-E%dof%d", x, y, m, n, j, personality.Network_Config.Acoord, personality.Network_Config.Anodes, personality.Network_Config.Bcoord, personality.Network_Config.Bnodes, personality.Network_Config.Ccoord, personality.Network_Config.Cnodes, personality.Network_Config.Dcoord, personality.Network_Config.Dnodes, personality.Network_Config.Ecoord, personality.Network_Config.Enodes ); /* check that we constructed the hostname correctly */ if (num < 0) { /* error */ scr_err("Error calling snprintf when building hostname rc=%d @ %s:%d", num, __FILE__, __LINE__ ); } else if (num >= sizeof(hostname)) { /* name was truncated */ scr_err("Temporary buffer of %d bytes too small to construct hostname, needed %d bytes @ %s:%d", sizeof(hostname), num, __FILE__, __LINE__ ); } else { /* duplicate the name */ name = strdup(hostname); } #endif return name; }
int file_dump(char * file, float *buf, size_t size) { ssize_t n = 0; int retries = 10; int fd; fd = open(file, O_WRONLY | O_CREAT, S_IREAD | S_IWRITE) ; if (fd < 0) { fprintf(stderr, "Error: %s", file); exit(1); } while (n < size) { ssize_t rc = write(fd, (char*) buf + n, size - n); // fprintf(stderr, "data: %d\n", rc); if (rc > 0) { n += rc; } else if (rc == 0) { /* something bad happened, print an error and abort */ scr_err("Error writing %s: write(%d, %x, %ld) returned 0 @ %s:%d", file, fd, (char*) buf + n, size - n, __FILE__, __LINE__ ); exit(1); } else { /* (rc < 0) */ /* got an error, check whether it was serious */ if (errno == EINTR || errno == EAGAIN) { continue; } /* something worth printing an error about */ retries--; if (retries) { /* print an error and try again */ scr_err("Error writing %s: write(%d, %x, %ld) errno=%d %m @ %s:%d", file, fd, (char*) buf + n, size - n, errno, __FILE__, __LINE__ ); } else { /* too many failed retries, give up */ scr_err("Giving up write to %s: write(%d, %x, %ld) errno=%d %m @ %s:%d", file, fd, (char*) buf + n, size - n, errno, __FILE__, __LINE__ ); exit(1); } } } close(fd); return n; }
/* recursively create directory and subdirectories */ int scr_mkdir(const char* dir, mode_t mode) { int rc = SCR_SUCCESS; /* With dirname, either the original string may be modified or the function may return a * pointer to static storage which will be overwritten by the next call to dirname, * so we need to strdup both the argument and the return string. */ /* extract leading path from dir = full path - basename */ char* dircopy = strdup(dir); char* path = strdup(dirname(dircopy)); /* if we can read path or path=="." or path=="/", then there's nothing to do, * otherwise, try to create it */ if (access(path, R_OK) < 0 && strcmp(path,".") != 0 && strcmp(path,"/") != 0) { rc = scr_mkdir(path, mode); } /* if we can write to path, try to create subdir within path */ if (access(path, W_OK) == 0 && rc == SCR_SUCCESS) { int tmp_rc = mkdir(dir, mode); if (tmp_rc < 0) { if (errno == EEXIST) { /* don't complain about mkdir for a directory that already exists */ scr_free(&dircopy); scr_free(&path); return SCR_SUCCESS; } else { scr_err("Creating directory: mkdir(%s, %x) path=%s errno=%d %s @ %s:%d", dir, mode, path, errno, strerror(errno), __FILE__, __LINE__ ); rc = SCR_FAILURE; } } } else { scr_err("Cannot write to directory: %s @ %s:%d", path, __FILE__, __LINE__ ); rc = SCR_FAILURE; } /* free our dup'ed string and return error code */ scr_free(&dircopy); scr_free(&path); return rc; }
int process_args(int argc, char **argv, struct arglist* args) { int ckpt; /* define our options */ static struct option long_options[] = { {"dir", required_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {0, 0, 0, 0} }; /* set our options to default values */ args->dir = NULL; /* loop through and process all options */ int c; do { /* read in our next option */ int option_index = 0; c = getopt_long(argc, argv, "d:h", long_options, &option_index); switch (c) { case 'd': /* directory containing nodes file */ args->dir = optarg; break; case 'h': /* print help message and exit */ print_usage(); break; case '?': /* getopt_long printed an error message */ break; default: if (c != -1) { /* missed an option */ scr_err("%s: Option '%s' specified but not processed", PROG, argv[option_index]); } } } while (c != -1); /* check that we got a directory name */ if (args->dir == NULL) { scr_err("%s: Must specify directory containing nodes file via '--dir <dir>'", PROG); return 0; } return 1; }
/* environment specific init/finalize */ int scr_env_init(void) { #ifdef SCR_RESOURCE_MANAGER_PMIX /* init pmix */ int retval = PMIx_Init(&scr_pmix_proc, NULL, 0); if (retval != PMIX_SUCCESS) { scr_err("PMIx_Init failed: rc=%d @ %s:%d", retval, __FILE__, __LINE__ ); return SCR_FAILURE; } scr_dbg(1, "PMIx_Init succeeded @ %s:%d", __FILE__, __LINE__); #endif /* SCR_MACHINE_TYPE == SCR_PMIX */ #ifdef HAVE_LIBCPPR /* attempt to init cppr */ int cppr_ret = cppr_status(); if (cppr_ret != CPPR_SUCCESS) { scr_abort(-1, "libcppr cppr_status() failed: %d '%s' @ %s:%d", cppr_ret, cppr_err_to_str(cppr_ret), __FILE__, __LINE__ ); } scr_dbg(1, "#bold CPPR is present @ %s:%d", __FILE__, __LINE__); #endif /* HAVE_LIBCPPR */ return SCR_SUCCESS; }
/* allocate a new string, having escaped all internal quotes * using mysql_real_escape_string, escaping is needed * in case values to be inserted have quotes, * caller is responsible for freeing string */ char* scr_mysql_quote_string(const char* value) { #ifdef HAVE_LIBMYSQLCLIENT if (value != NULL) { /* start with a leading single quote, escape internal quotes * by adding a leading backslash (could double length of input * string), then end with trailing single quote and * terminating NUL */ int n = strlen(value); char* q = (char*) malloc(2*n+1+2); if (q != NULL) { q[0] = '\''; mysql_real_escape_string(&scr_mysql, &q[1], value, n); n = strlen(q); q[n] = '\''; q[n+1] = '\0'; return q; } else { scr_err("Failed to allocate buffer space to encode string %s @ %s:%d", value, __FILE__, __LINE__ ); return NULL; } } else { return strdup("NULL"); } #else return NULL; #endif }
/* read line from file into buf with given size */ ssize_t scr_read_line(const char* file, int fd, char* buf, size_t size) { /* read up to size-1 bytes from fd into buf until we find a newline or EOF */ ssize_t n = 0; int found_end = 0; while (n < size-1 && !found_end) { /* read a character from the file */ char c; ssize_t nread = scr_read(file, fd, &c, sizeof(c)); if (nread > 0) { /* we read a character, copy it over to the buffer */ buf[n] = c; n++; /* check whether we hit the end of the line */ if (c == '\n') { found_end = 1; } } else if (nread == 0) { /* we hit the end of the file */ found_end = 1; } else { /* nread < 0 */ /* we hit an error */ scr_err("Error reading from file %s @ %s:%d", file, __FILE__, __LINE__ ); return -1; } } /* tack on the NULL character */ buf[n] = '\0'; /* if we exit the while loop but didn't find the end of the line, the buffer was too small */ if (!found_end) { scr_err("Buffer too small to read line from file %s @ %s:%d", file, __FILE__, __LINE__ ); return -1; } /* NOTE: we don't want to count the NULL which we added, but there is no need to adjust n here */ return n; }
/* seek file descriptor to specified position */ int scr_lseek(const char* file, int fd, off_t pos, int whence) { off_t rc = lseek(fd, pos, whence); if (rc == (off_t)-1) { scr_err("Error seeking %s: errno=%d %s @ %s:%d", file, errno, strerror(errno), __FILE__, __LINE__ ); return SCR_FAILURE; } return SCR_SUCCESS; }
/* read config files and store contents */ int scr_param_init() { /* allocate storage and read in config files if we haven't already */ if (scr_param_ref_count == 0) { /* allocate hash object to hold names we cannot read from the * environment */ scr_no_user_hash = scr_hash_new(); scr_hash_set(scr_no_user_hash, "SCR_CNTL_BASE", scr_hash_new()); /* allocate hash object to store values from user config file, * if specified */ char* user_file = user_config_path(); if (user_file != NULL) { scr_user_hash = scr_hash_new(); scr_config_read(user_file, scr_user_hash); } scr_free(&user_file); /* allocate hash object to store values from system config file */ scr_system_hash = scr_hash_new(); scr_config_read(scr_config_file, scr_system_hash); /* initialize our hash to cache lookups to getenv */ scr_env_hash = scr_hash_new(); /* warn user if he set any parameters in his environment or user * config file which aren't permitted */ scr_hash_elem* elem; for (elem = scr_hash_elem_first(scr_no_user_hash); elem != NULL; elem = scr_hash_elem_next(elem)) { /* get the parameter name */ char* key = scr_hash_elem_key(elem); char* env_val = getenv(key); scr_hash* env_hash = scr_hash_get(scr_user_hash, key); /* check whether this is set in the environment */ if (env_val != NULL || env_hash != NULL) { scr_err("%s cannot be set in the environment or user configuration file, ignoring setting", key ); } } } /* increment our reference count */ scr_param_ref_count++; return SCR_SUCCESS; }
/* make a good attempt to write to file (retries, if necessary, return error if fail) */ ssize_t scr_write_attempt(const char* file, int fd, const void* buf, size_t size) { ssize_t n = 0; int retries = 10; while (n < size) { ssize_t rc = write(fd, (char*) buf + n, size - n); if (rc > 0) { n += rc; } else if (rc == 0) { /* something bad happened, print an error and abort */ scr_err("Error writing file %s write returned 0 @ %s:%d", file, __FILE__, __LINE__ ); return -1; } else { /* (rc < 0) */ /* got an error, check whether it was serious */ if (errno == EINTR || errno == EAGAIN) { continue; } /* something worth printing an error about */ retries--; if (retries) { /* print an error and try again */ scr_err("Error writing file %s errno=%d %s @ %s:%d", file, errno, strerror(errno), __FILE__, __LINE__ ); } else { /* too many failed retries, give up */ scr_err("Giving up write of file %s errno=%d %s @ %s:%d", file, errno, strerror(errno), __FILE__, __LINE__ ); return -1; } } } return n; }
/* remove directory */ int scr_rmdir(const char* dir) { /* delete directory */ int rc = rmdir(dir); if (rc < 0) { /* whoops, something failed when we tried to delete our directory */ scr_err("Error deleting directory: %s (rmdir returned %d %s) @ %s:%d", dir, rc, strerror(errno), __FILE__, __LINE__ ); return SCR_FAILURE; } return SCR_SUCCESS; }
/* reliable read from file descriptor (retries, if necessary, until hard error) */ ssize_t scr_read(const char* file, int fd, void* buf, size_t size) { ssize_t n = 0; int retries = 10; while (n < size) { int rc = read(fd, (char*) buf + n, size - n); if (rc > 0) { n += rc; } else if (rc == 0) { /* EOF */ return n; } else { /* (rc < 0) */ /* got an error, check whether it was serious */ if (errno == EINTR || errno == EAGAIN) { continue; } /* something worth printing an error about */ retries--; if (retries) { /* print an error and try again */ scr_err("Error reading %s: read(%d, %x, %ld) errno=%d %s @ %s:%d", file, fd, (char*) buf + n, size - n, errno, strerror(errno), __FILE__, __LINE__ ); } else { /* too many failed retries, give up */ scr_err("Giving up read of %s: read(%d, %x, %ld) errno=%d %s @ %s:%d", file, fd, (char*) buf + n, size - n, errno, strerror(errno), __FILE__, __LINE__ ); exit(1); } } } return n; }
/* unpack an unsigned 64 bit value to specified buffer in host order */ int scr_unpack_uint64_t(void* buf, size_t buf_size, size_t* buf_pos, uint64_t* val) { /* check that we have a valid pointer to a buffer position value */ if (buf == NULL || buf_pos == NULL || val == NULL) { scr_err("NULL pointer to buffer, buffer position, or value @ %s:%d", __FILE__, __LINE__ ); return SCR_FAILURE; } /* get current buffer position */ size_t pos = *buf_pos; /* compute final buffer position */ size_t pos_final = pos + sizeof(uint64_t); /* check that we won't overrun the buffer */ if (pos_final > buf_size) { scr_err("Attempting to unpack too many bytes into buffer @ %s:%d", __FILE__, __LINE__ ); return SCR_FAILURE; } /* read value from buffer (stored in network order) */ uint64_t val_network; memcpy(&val_network, buf + pos, sizeof(val_network)); /* conver to host order */ *val = scr_ntoh64(val_network); /* update position */ *buf_pos = pos_final; return SCR_SUCCESS; }
/* initialize the logging */ int scr_log_init() { int rc = SCR_SUCCESS; /* read in parameters */ char* value = NULL; scr_param_init(); /* check whether SCR logging DB is enabled */ if ((value = scr_param_get("SCR_DB_ENABLE")) != NULL) { scr_db_enable = atoi(value); } /* read in the debug level for database log messages */ if ((value = scr_param_get("SCR_DB_DEBUG")) != NULL) { scr_db_debug = atoi(value); } /* SCR log DB connection parameters */ if ((value = scr_param_get("SCR_DB_HOST")) != NULL) { scr_db_host = strdup(value); } if ((value = scr_param_get("SCR_DB_USER")) != NULL) { scr_db_user = strdup(value); } if ((value = scr_param_get("SCR_DB_PASS")) != NULL) { scr_db_pass = strdup(value); } if ((value = scr_param_get("SCR_DB_NAME")) != NULL) { scr_db_name = strdup(value); } scr_param_finalize(); /* connect to the database, if enabled */ if (scr_db_enable) { if (scr_mysql_connect() != SCR_SUCCESS) { scr_err("Failed to connect to SCR logging database, disabling database logging @ %s:%d", __FILE__, __LINE__ ); scr_db_enable = 0; rc = SCR_FAILURE; } } return rc; }
/* given an element, set its key and hash fields */ static scr_hash_elem* scr_hash_elem_init(scr_hash_elem* elem, const char* key, scr_hash* hash) { if (elem != NULL) { if (key != NULL) { elem->key = strdup(key); } else { /* bad idea to allow key to be set to NULL */ elem->key = NULL; scr_err("Setting hash element key to NULL @ %s:%d", __FILE__, __LINE__ ); } elem->hash = hash; } return elem; }
/* for file name listed in meta, fetch that file from src_dir and store * a copy in dst_dir, record full path to copy in newfile, and * return whether operation succeeded */ static int scr_fetch_file( const char* dst_file, const char* src_dir, const scr_meta* meta) { int rc = SCR_SUCCESS; /* build full path to source file */ scr_path* path_src_file = scr_path_from_str(dst_file); scr_path_basename(path_src_file); scr_path_prepend_str(path_src_file, src_dir); char* src_file = scr_path_strdup(path_src_file); /* fetch the file */ uLong crc; uLong* crc_p = NULL; if (scr_crc_on_flush) { crc_p = &crc; } rc = scr_file_copy(src_file, dst_file, scr_file_buf_size, crc_p); /* check that crc matches crc stored in meta */ uLong meta_crc; if (scr_meta_get_crc32(meta, &meta_crc) == SCR_SUCCESS) { if (rc == SCR_SUCCESS && scr_crc_on_flush && crc != meta_crc) { rc = SCR_FAILURE; scr_err("CRC32 mismatch detected when fetching file from %s to %s @ %s:%d", src_file, dst_file, __FILE__, __LINE__ ); /* TODO: would be good to log this, but right now only rank 0 * can write log entries */ /* if (scr_log_enable) { time_t now = scr_log_seconds(); scr_log_event("CRC32 MISMATCH", filename, NULL, &now, NULL); } */ } } /* free path and string for source file */ scr_free(&src_file); scr_path_delete(&path_src_file); return rc; }
/* allocate and return a string containing the current username */ char* scr_env_username() { char* name = NULL; /* read $USER environment variable for username */ char* value; if ((value = getenv("USER")) != NULL) { name = strdup(value); if (name == NULL) { scr_err("Failed to allocate memory to record username (%s) @ %s:%d", value, __FILE__, __LINE__ ); } } return name; }
/* open file with specified flags and mode, retry open a few times on failure */ int scr_open(const char* file, int flags, ...) { /* extract the mode (see man 2 open) */ int mode_set = 0; mode_t mode = 0; if (flags & O_CREAT) { va_list ap; va_start(ap, flags); mode = va_arg(ap, mode_t); va_end(ap); mode_set = 1; } int fd = -1; if (mode_set) { fd = open(file, flags, mode); } else { fd = open(file, flags); } if (fd < 0) { scr_dbg(1, "Opening file: open(%s) errno=%d %s @ %s:%d", file, errno, strerror(errno), __FILE__, __LINE__ ); /* try again */ int tries = SCR_OPEN_TRIES; while (tries && fd < 0) { usleep(SCR_OPEN_USLEEP); if (mode_set) { fd = open(file, flags, mode); } else { fd = open(file, flags); } tries--; } /* if we still don't have a valid file, consider it an error */ if (fd < 0) { scr_err("Opening file: open(%s) errno=%d %s @ %s:%d", file, errno, strerror(errno), __FILE__, __LINE__ ); } } return fd; }
static int scr_compute_crc(scr_filemap* map, int id, int rank, const char* file) { /* compute crc for the file */ uLong crc_file; if (scr_crc32(file, &crc_file) != SCR_SUCCESS) { scr_err("Failed to compute crc for file %s @ %s:%d", file, __FILE__, __LINE__ ); return SCR_FAILURE; } /* allocate a new meta data object */ scr_meta* meta = scr_meta_new(); if (meta == NULL) { scr_abort(-1, "Failed to allocate meta data object @ %s:%d", __FILE__, __LINE__ ); } /* read meta data from filemap */ if (scr_filemap_get_meta(map, id, rank, file, meta) != SCR_SUCCESS) { return SCR_FAILURE; } int rc = SCR_SUCCESS; /* read crc value from meta data */ uLong crc_meta; if (scr_meta_get_crc32(meta, &crc_meta) == SCR_SUCCESS) { /* check that the values are the same */ if (crc_file != crc_meta) { rc = SCR_FAILURE; } } else { /* record crc in filemap */ scr_meta_set_crc32(meta, crc_file); scr_filemap_set_meta(map, id, rank, file, meta); } /* free our meta data object */ scr_meta_delete(&meta); return rc; }
/* fsync and close file */ int scr_close(const char* file, int fd) { /* fsync first */ if (fsync(fd) < 0) { /* print warning that fsync failed */ scr_dbg(2, "Failed to fsync file descriptor: %s errno=%d %s @ file %s:%d", file, errno, strerror(errno), __FILE__, __LINE__ ); } /* now close the file */ if (close(fd) != 0) { /* hit an error, print message */ scr_err("Closing file descriptor %d for file %s: errno=%d %s @ %s:%d", fd, file, errno, strerror(errno), __FILE__, __LINE__ ); return SCR_FAILURE; } return SCR_SUCCESS; }
/* opens specified file and waits on a lock before returning the file descriptor */ int scr_open_with_lock(const char* file, int flags, mode_t mode) { /* open the file */ int fd = scr_open(file, flags, mode); if (fd < 0) { scr_err("Opening file for write: scr_open(%s) errno=%d %s @ %s:%d", file, errno, strerror(errno), __FILE__, __LINE__ ); return fd; } /* acquire an exclusive file lock */ int ret = scr_file_lock_write(file, fd); if (ret != SCR_SUCCESS) { close(fd); return ret; } /* return the opened file descriptor */ return fd; }
/* read in the summary file from dir */ static int scr_summary_read_v5(const scr_path* dir, scr_hash* summary_hash) { /* check that we got a pointer to a hash */ if (summary_hash == NULL) { return SCR_FAILURE; } /* assume that we'll fail */ int rc = SCR_FAILURE; /* build the summary filename */ scr_path* summary_path = scr_path_dup(dir); scr_path_append_str(summary_path, "summary.scr"); char* summary_file = scr_path_strdup(summary_path); /* check whether we can read the file before we actually try, * we take this step to avoid printing an error in scr_hash_read */ if (scr_file_is_readable(summary_file) != SCR_SUCCESS) { goto cleanup; } /* read in the summary hash file */ if (scr_hash_read_path(summary_path, summary_hash) != SCR_SUCCESS) { scr_err("Reading summary file %s @ %s:%d", summary_file, __FILE__, __LINE__ ); goto cleanup; } /* if we made it here, we successfully read the summary file as a hash */ rc = SCR_SUCCESS; cleanup: /* free the summary path */ scr_free(&summary_file); scr_path_delete(&summary_path); return rc; }