コード例 #1
0
ファイル: as_mysql_cluster.c プロジェクト: FredHutch/slurm
extern int as_mysql_node_up(mysql_conn_t *mysql_conn,
			    struct node_record *node_ptr,
			    time_t event_time)
{
	char* query;
	int rc = SLURM_SUCCESS;

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	if (!mysql_conn->cluster_name) {
		error("%s:%d no cluster name", THIS_FILE, __LINE__);
		return SLURM_ERROR;
	}

	query = xstrdup_printf(
		"update \"%s_%s\" set time_end=%ld where "
		"time_end=0 and node_name='%s';",
		mysql_conn->cluster_name, event_table,
		event_time, node_ptr->name);
	debug4("%d(%s:%d) query\n%s",
	       mysql_conn->conn, THIS_FILE, __LINE__, query);
	rc = mysql_db_query(mysql_conn, query);
	xfree(query);
	return rc;
}
コード例 #2
0
ファイル: as_mysql_cluster.c プロジェクト: CornellCAC/slurm
extern int as_mysql_node_down(mysql_conn_t *mysql_conn,
			      struct node_record *node_ptr,
			      time_t event_time, char *reason,
			      uint32_t reason_uid)
{
	uint16_t cpus;
	int rc = SLURM_SUCCESS;
	char *query = NULL;
	char *my_reason;

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	if (!node_ptr) {
		error("No node_ptr given!");
		return SLURM_ERROR;
	}

	if (slurmctld_conf.fast_schedule && !slurmdbd_conf)
		cpus = node_ptr->config_ptr->cpus;
	else
		cpus = node_ptr->cpus;

	if (reason)
		my_reason = slurm_add_slash_to_quotes(reason);
	else
		my_reason = slurm_add_slash_to_quotes(node_ptr->reason);

	debug2("inserting %s(%s) with %u cpus",
	       node_ptr->name, mysql_conn->cluster_name, cpus);

	query = xstrdup_printf(
		"update \"%s_%s\" set time_end=%ld where "
		"time_end=0 and node_name='%s';",
		mysql_conn->cluster_name, event_table,
		event_time, node_ptr->name);
	/* If you are clean-restarting the controller over and over again you
	 * could get records that are duplicates in the database.  If
	 * this is the case we will zero out the time_end we are
	 * just filled in.  This will cause the last time to be erased
	 * from the last restart, but if you are restarting things
	 * this often the pervious one didn't mean anything anyway.
	 * This way we only get one for the last time we let it run.
	 */
	xstrfmtcat(query,
		   "insert into \"%s_%s\" "
		   "(node_name, state, cpu_count, time_start, "
		   "reason, reason_uid) "
		   "values ('%s', %u, %u, %ld, '%s', %u) "
		   "on duplicate key update time_end=0;",
		   mysql_conn->cluster_name, event_table,
		   node_ptr->name, node_ptr->node_state,
		   cpus, event_time, my_reason, reason_uid);
	debug4("%d(%s:%d) query\n%s",
	       mysql_conn->conn, THIS_FILE, __LINE__, query);
	rc = mysql_db_query(mysql_conn, query);
	xfree(query);
	xfree(my_reason);
	return rc;
}
コード例 #3
0
static int _remove_clusters_from_fed(mysql_conn_t *mysql_conn, List clusters)
{
	int   rc    = SLURM_SUCCESS;
	char *query = NULL;
	char *name  = NULL;
	char *names = NULL;
	ListIterator itr = NULL;

	xassert(clusters);

	itr = list_iterator_create(clusters);
	while ((name = list_next(itr)))
	       xstrfmtcat(names, "%s'%s'", names ? "," : "", name );

	xstrfmtcat(query, "UPDATE %s "
		   	  "SET federation='', fed_id=0, fed_state=%u "
			  "WHERE name IN (%s) and deleted=0",
		   cluster_table, CLUSTER_FED_STATE_NA, names);

	if (debug_flags & DEBUG_FLAG_FEDR)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);

	rc = mysql_db_query(mysql_conn, query);
	xfree(query);
	if (rc)
		error("Failed to remove clusters %s from federation", names);
	xfree(names);

	return rc;
}
コード例 #4
0
ファイル: as_mysql_cluster.c プロジェクト: FredHutch/slurm
extern int as_mysql_register_ctld(mysql_conn_t *mysql_conn,
				  char *cluster, uint16_t port)
{
	char *query = NULL;
	char *address = NULL;
	char hostname[255];
	time_t now = time(NULL);
	uint32_t flags = slurmdb_setup_cluster_flags();
	int rc = SLURM_SUCCESS;

	if (slurmdbd_conf)
		fatal("clusteracct_storage_g_register_ctld "
		      "should never be called from the slurmdbd.");

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	if (!mysql_conn->cluster_name) {
		error("%s:%d no cluster name", THIS_FILE, __LINE__);
		return SLURM_ERROR;
	}

	if (!mysql_conn->cluster_name)
		mysql_conn->cluster_name = xstrdup(cluster);

	info("Registering slurmctld for cluster %s at port %u in database.",
	     cluster, port);
	gethostname(hostname, sizeof(hostname));

	/* check if we are running on the backup controller */
	if (slurmctld_conf.backup_controller
	    && !strcmp(slurmctld_conf.backup_controller, hostname)) {
		address = slurmctld_conf.backup_addr;
	} else
		address = slurmctld_conf.control_addr;

	query = xstrdup_printf(
		"update %s set deleted=0, mod_time=%ld, "
		"control_host='%s', control_port=%u, last_port=%u, "
		"rpc_version=%d, dimensions=%d, flags=%u, "
		"plugin_id_select=%d where name='%s';",
		cluster_table, now, address, port, port, SLURM_PROTOCOL_VERSION,
		SYSTEM_DIMENSIONS, flags, select_get_plugin_id(), cluster);
	xstrfmtcat(query,
		   "insert into %s "
		   "(timestamp, action, name, actor, info) "
		   "values (%ld, %d, '%s', '%s', '%s %u %u %u %u');",
		   txn_table,
		   now, DBD_MODIFY_CLUSTERS, cluster,
		   slurmctld_conf.slurm_user_name, address, port,
		   SYSTEM_DIMENSIONS, flags, select_get_plugin_id());

	if (debug_flags & DEBUG_FLAG_DB_ASSOC)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);

	rc = mysql_db_query(mysql_conn, query);
	xfree(query);
	return rc;
}
コード例 #5
0
static int _add_clusters_to_fed(mysql_conn_t *mysql_conn, List clusters,
				const char *fed)
{
	int   rc      = SLURM_SUCCESS;
	char *query   = NULL;
	char *name    = NULL;
	char *names   = NULL;
	char *indexes = NULL;
	ListIterator itr = NULL;
	int   last_id = -1;

	xassert(fed);
	xassert(clusters);

	itr = list_iterator_create(clusters);
	while ((name = list_next(itr))) {
		int id;
		if ((rc = as_mysql_get_fed_cluster_id(mysql_conn, name, fed,
						      last_id, &id)))
			goto end_it;
		last_id = id;
		xstrfmtcat(indexes, "WHEN name='%s' THEN %d ", name, id);
		xstrfmtcat(names, "%s'%s'", names ? "," : "", name);
	}

	/* Keep the same fed_state if the cluster isn't changing feds.
	 * Also note that mysql evaluates from left to right and uses the
	 * updated column values in case statements. So the check for federation
	 * in the fed_state case statement must happen before fed_state is set
	 * or the federation will always equal the federation in the case
	 * statement.  */
	xstrfmtcat(query, "UPDATE %s "
		   	  "SET "
			  "fed_state = CASE WHEN federation='%s' THEN fed_state ELSE %u END, "
			  "fed_id = CASE %s END, "
		   	  "federation='%s' "
			  "WHERE name IN (%s) and deleted=0",
		   cluster_table, fed, CLUSTER_FED_STATE_ACTIVE, indexes, fed,
		   names);

	if (debug_flags & DEBUG_FLAG_FEDR)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);

	rc = mysql_db_query(mysql_conn, query);
	if (rc)
		error("Failed to add clusters %s to federation %s",
		      names, fed);

end_it:
	xfree(query);
	xfree(names);
	xfree(indexes);
	list_iterator_destroy(itr);

	return rc;
}
コード例 #6
0
extern int as_mysql_fix_runaway_jobs(mysql_conn_t *mysql_conn, uint32_t uid,
				     List runaway_jobs)
{
	char *query = NULL, *job_ids = NULL;
	slurmdb_job_rec_t *job = NULL;
	ListIterator iter = NULL;
	int rc = SLURM_SUCCESS;
	slurmdb_job_rec_t *first_job;

	list_sort(runaway_jobs, _job_sort_by_start_time);
	first_job = list_peek(runaway_jobs);

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	if (!is_user_min_admin_level(mysql_conn, uid, SLURMDB_ADMIN_OPERATOR)) {
		slurmdb_user_rec_t user;

		memset(&user, 0, sizeof(slurmdb_user_rec_t));
		user.uid = uid;

		if (!is_user_any_coord(mysql_conn, &user)) {
			error("Only admins/operators/coordinators "
			      "can fix runaway jobs");
			return ESLURM_ACCESS_DENIED;
		}
	}

	iter = list_iterator_create(runaway_jobs);
	while ((job = list_next(iter))) {
		xstrfmtcat(job_ids, "%s%d", ((job_ids) ? "," : ""), job->jobid);
	}

	query = xstrdup_printf("UPDATE \"%s_%s\" SET time_end="
			       "GREATEST(time_start, time_eligible, time_submit), "
			       "state=%d WHERE id_job IN (%s);",
			       mysql_conn->cluster_name, job_table,
			       JOB_COMPLETE, job_ids);

	if (debug_flags & DEBUG_FLAG_DB_QUERY)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);
	mysql_db_query(mysql_conn, query);
	xfree(query);
	xfree(job_ids);

	/* Set rollup to the the last day of the previous month of the first
	 * runaway job */
	rc = _first_job_roll_up(mysql_conn, first_job->start);
	if (rc != SLURM_SUCCESS) {
		error("Failed to fix runaway jobs");
		return SLURM_ERROR;
	}

	return rc;
}
コード例 #7
0
ファイル: as_mysql_resv.c プロジェクト: RSE-Cambridge/slurm
extern int as_mysql_remove_resv(mysql_conn_t *mysql_conn,
				slurmdb_reservation_rec_t *resv)
{
	int rc = SLURM_SUCCESS;
	char *query = NULL;

	if (!resv) {
		error("No reservation was given to remove");
		return SLURM_ERROR;
	}

	if (!resv->id) {
		error("An id is needed to remove a reservation.");
		return SLURM_ERROR;
	}

	if (!resv->time_start) {
		error("A start time is needed to remove a reservation.");
		return SLURM_ERROR;
	}

	if (!resv->cluster || !resv->cluster[0]) {
		error("A cluster name is needed to remove a reservation.");
		return SLURM_ERROR;
	}


	/* first delete the resv that hasn't happened yet. */
	query = xstrdup_printf("delete from \"%s_%s\" where time_start > %ld "
			       "and id_resv=%u and time_start=%ld;",
			       resv->cluster, resv_table, resv->time_start_prev,
			       resv->id,
			       resv->time_start);
	/* then update the remaining ones with a deleted flag and end
	 * time of the time_start_prev which is set to when the
	 * command was issued */
	xstrfmtcat(query,
		   "update \"%s_%s\" set time_end=%ld, "
		   "deleted=1 where deleted=0 and "
		   "id_resv=%u and time_start=%ld;",
		   resv->cluster, resv_table, resv->time_start_prev,
		   resv->id, resv->time_start);

	if (debug_flags & DEBUG_FLAG_DB_RESV)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);

	rc = mysql_db_query(mysql_conn, query);

	xfree(query);

	return rc;
}
コード例 #8
0
ファイル: as_mysql_rollup.c プロジェクト: artpol84/slurm
static int _process_cluster_usage(mysql_conn_t *mysql_conn,
				  char *cluster_name,
				  time_t curr_start, time_t curr_end,
				  time_t now, local_cluster_usage_t *c_usage)
{
	int rc = SLURM_SUCCESS;
	char *query = NULL;
	ListIterator itr;
	local_tres_usage_t *loc_tres;

	if (!c_usage)
		return rc;
	/* Now put the lists into the usage tables */

	xassert(c_usage->loc_tres);
	itr = list_iterator_create(c_usage->loc_tres);
	while ((loc_tres = list_next(itr))) {
		_setup_cluster_tres_usage(mysql_conn, cluster_name,
					  curr_start, curr_end, now,
					  c_usage->start, loc_tres, &query);
	}
	list_iterator_destroy(itr);

	if (!query)
		return rc;

	xstrfmtcat(query,
		   " on duplicate key update "
		   "mod_time=%ld, count=VALUES(count), "
		   "alloc_secs=VALUES(alloc_secs), "
		   "down_secs=VALUES(down_secs), "
		   "pdown_secs=VALUES(pdown_secs), "
		   "idle_secs=VALUES(idle_secs), "
		   "over_secs=VALUES(over_secs), "
		   "resv_secs=VALUES(resv_secs)",
		   now);

	/* Spacing out the inserts here instead of doing them
	   all at once in the end proves to be faster.  Just FYI
	   so we don't go testing again and again.
	*/
	if (debug_flags & DEBUG_FLAG_DB_USAGE)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);
	rc = mysql_db_query(mysql_conn, query);
	xfree(query);
	if (rc != SLURM_SUCCESS)
		error("Couldn't add cluster hour rollup");

	return rc;
}
コード例 #9
0
ファイル: as_mysql_resv.c プロジェクト: RSE-Cambridge/slurm
extern int as_mysql_add_resv(mysql_conn_t *mysql_conn,
			     slurmdb_reservation_rec_t *resv)
{
	int rc = SLURM_SUCCESS;
	char *cols = NULL, *vals = NULL, *extra = NULL,
		*query = NULL;

	if (!resv) {
		error("No reservation was given to add.");
		return SLURM_ERROR;
	}

	if (!resv->id) {
		error("We need an id to add a reservation.");
		return SLURM_ERROR;
	}
	if (!resv->time_start) {
		error("We need a start time to add a reservation.");
		return SLURM_ERROR;
	}
	if (!resv->cluster || !resv->cluster[0]) {
		error("We need a cluster name to add a reservation.");
		return SLURM_ERROR;
	}

	_setup_resv_limits(resv, &cols, &vals, &extra);

	xstrfmtcat(query,
		   "insert into \"%s_%s\" (id_resv%s) values (%u%s) "
		   "on duplicate key update deleted=0%s;",
		   resv->cluster, resv_table, cols, resv->id, vals, extra);

	if (debug_flags & DEBUG_FLAG_DB_RESV)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);

	rc = mysql_db_query(mysql_conn, query);

	xfree(query);
	xfree(cols);
	xfree(vals);
	xfree(extra);

	return rc;
}
コード例 #10
0
ファイル: as_mysql_resv.c プロジェクト: Cray/slurm
extern int as_mysql_remove_resv(mysql_conn_t *mysql_conn,
				slurmdb_reservation_rec_t *resv)
{
	int rc = SLURM_SUCCESS;
	char *query = NULL;//, *tmp_extra = NULL;

	if (!resv) {
		error("No reservation was given to edit");
		return SLURM_ERROR;
	}

	if (!resv->id || !resv->time_start || !resv->cluster) {
		error("We need an id, start time, and cluster "
		      "name to edit a reservation.");
		return SLURM_ERROR;
	}


	/* first delete the resv that hasn't happened yet. */
	query = xstrdup_printf("delete from \"%s_%s\" where time_start > %ld "
			       "and id_resv=%u and time_start=%ld;",
			       resv->cluster, resv_table, resv->time_start_prev,
			       resv->id,
			       resv->time_start);
	/* then update the remaining ones with a deleted flag and end
	 * time of the time_start_prev which is set to when the
	 * command was issued */
	xstrfmtcat(query,
		   "update \"%s_%s\" set time_end=%ld, "
		   "deleted=1 where deleted=0 and "
		   "id_resv=%u and time_start=%ld;",
		   resv->cluster, resv_table, resv->time_start_prev,
		   resv->id, resv->time_start);

	debug3("%d(%s:%d) query\n%s",
	       mysql_conn->conn, THIS_FILE, __LINE__, query);

	rc = mysql_db_query(mysql_conn, query);

	xfree(query);

	return rc;
}
コード例 #11
0
ファイル: as_mysql_resv.c プロジェクト: Cray/slurm
extern int as_mysql_add_resv(mysql_conn_t *mysql_conn,
			     slurmdb_reservation_rec_t *resv)
{
	int rc = SLURM_SUCCESS;
	char *cols = NULL, *vals = NULL, *extra = NULL,
		*query = NULL;//, *tmp_extra = NULL;

	if (!resv) {
		error("No reservation was given to edit");
		return SLURM_ERROR;
	}

	if (!resv->id) {
		error("We need an id to edit a reservation.");
		return SLURM_ERROR;
	}
	if (!resv->time_start) {
		error("We need a start time to edit a reservation.");
		return SLURM_ERROR;
	}
	if (!resv->cluster || !resv->cluster[0]) {
		error("We need a cluster name to edit a reservation.");
		return SLURM_ERROR;
	}

	_setup_resv_limits(resv, &cols, &vals, &extra);

	xstrfmtcat(query,
		   "insert into \"%s_%s\" (id_resv%s) values (%u%s) "
		   "on duplicate key update deleted=0%s;",
		   resv->cluster, resv_table, cols, resv->id, vals, extra);
	debug3("%d(%s:%d) query\n%s",
	       mysql_conn->conn, THIS_FILE, __LINE__, query);

	rc = mysql_db_query(mysql_conn, query);

	xfree(query);
	xfree(cols);
	xfree(vals);
	xfree(extra);

	return rc;
}
コード例 #12
0
/*
 * Remove all clusters from federation.
 * IN: mysql_conn - mysql connection
 * IN: fed - fed to remove clusters from
 * IN: exceptions - list of clusters to not remove.
 */
static int _remove_all_clusters_from_fed(mysql_conn_t *mysql_conn,
					 const char *fed, List exceptions)
{
	int   rc    = SLURM_SUCCESS;
	char *query = NULL;
	char *exception_names = NULL;

	if (exceptions && list_count(exceptions)) {
		char *tmp_name;
		ListIterator itr;

		itr = list_iterator_create(exceptions);
		while ((tmp_name = list_next(itr)))
			xstrfmtcat(exception_names, "%s'%s'",
				   (exception_names) ? "," : "",
				   tmp_name);
		list_iterator_destroy(itr);
	}

	xstrfmtcat(query, "UPDATE %s "
		   	  "SET federation='', fed_id=0, fed_state=%u "
			  "WHERE federation='%s' and deleted=0",
		   cluster_table, CLUSTER_FED_STATE_NA, fed);
	if (exception_names)
		xstrfmtcat(query, " AND name NOT IN (%s)", exception_names);

	if (debug_flags & DEBUG_FLAG_FEDR)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);

	rc = mysql_db_query(mysql_conn, query);
	xfree(query);
	if (rc)
		error("Failed to remove all clusters from federation %s", fed);

	if (exception_names)
		xfree(exception_names);

	return rc;
}
コード例 #13
0
ファイル: as_mysql_user.c プロジェクト: BYUHPC/slurm
static int _change_user_name(mysql_conn_t *mysql_conn, slurmdb_user_rec_t *user)
{
	int rc = SLURM_SUCCESS;
	char *query = NULL;
	ListIterator itr = NULL;
	char *cluster_name = NULL;

	xassert(user->old_name);
	xassert(user->name);

	slurm_mutex_lock(&as_mysql_cluster_list_lock);
	itr = list_iterator_create(as_mysql_cluster_list);
	while ((cluster_name = list_next(itr))) {
		// Change assoc_tables
		xstrfmtcat(query, "update \"%s_%s\" set user='******' "
			   "where user='******';", cluster_name, assoc_table,
			   user->name, user->old_name);
		// Change wckey_tables
		xstrfmtcat(query, "update \"%s_%s\" set user='******' "
			   "where user='******';", cluster_name, wckey_table,
			   user->name, user->old_name);
	}
	list_iterator_destroy(itr);
	slurm_mutex_unlock(&as_mysql_cluster_list_lock);
	// Change coord_tables
	xstrfmtcat(query, "update %s set user='******' where user='******';",
		   acct_coord_table, user->name, user->old_name);

	debug3("%d(%s:%d) query\n%s",
	       mysql_conn->conn, THIS_FILE, __LINE__, query);
	rc = mysql_db_query(mysql_conn, query);
	xfree(query);

	if (rc != SLURM_SUCCESS)
		reset_mysql_conn(mysql_conn);

	return rc;
}
コード例 #14
0
static int _first_job_roll_up(mysql_conn_t *mysql_conn, time_t first_start)
{
	int rc = SLURM_SUCCESS;
	char *query;
	struct tm start_tm;
	time_t month_start;

	/* set up the month period */
	if (!slurm_localtime_r(&first_start, &start_tm)) {
		error("mktime for start failed for rollup\n");
		return SLURM_ERROR;
	}

	// Go to the last day of the previous month for rollup start
	start_tm.tm_sec = 0;
	start_tm.tm_min = 0;
	start_tm.tm_hour = 0;
	start_tm.tm_mday = 0;
	start_tm.tm_isdst = -1;
	month_start = slurm_mktime(&start_tm);

	query = xstrdup_printf("UPDATE \"%s_%s\" SET hourly_rollup = %ld, "
			       "daily_rollup = %ld, monthly_rollup = %ld",
			       mysql_conn->cluster_name, last_ran_table,
			       month_start, month_start, month_start);

	if (debug_flags & DEBUG_FLAG_DB_QUERY)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);
	rc = mysql_db_query(mysql_conn, query);
	if (rc != SLURM_SUCCESS)
		error("%s Failed to rollup at the end of previous month",
		      __func__);

	xfree(query);
	return rc;
}
コード例 #15
0
extern int as_mysql_monthly_rollup(mysql_conn_t *mysql_conn,
				   char *cluster_name,
				   time_t start, time_t end,
				   uint16_t archive_data)
{
	int rc = SLURM_SUCCESS;
	struct tm start_tm;
	time_t curr_start = start;
	time_t curr_end;
	time_t now = time(NULL);
	char *query = NULL;
	uint16_t track_wckey = slurm_get_track_wckey();

	if (!localtime_r(&curr_start, &start_tm)) {
		error("Couldn't get localtime from month start %ld",
		      curr_start);
		return SLURM_ERROR;
	}
	start_tm.tm_sec = 0;
	start_tm.tm_min = 0;
	start_tm.tm_hour = 0;
	start_tm.tm_mday = 1;
	start_tm.tm_mon++;
	start_tm.tm_isdst = -1;
	curr_end = mktime(&start_tm);

	while (curr_start < end) {
		if (debug_flags & DEBUG_FLAG_DB_USAGE)
			DB_DEBUG(mysql_conn->conn,
				 "curr month is now %ld-%ld",
				 curr_start, curr_end);
/* 		info("start %s", slurm_ctime(&curr_start)); */
/* 		info("end %s", slurm_ctime(&curr_end)); */
		query = xstrdup_printf(
			"insert into \"%s_%s\" (creation_time, "
			"mod_time, id_assoc, "
			"time_start, alloc_cpu_secs, consumed_energy) select "
			"%ld, %ld, id_assoc, "
			"%ld, @ASUM:=SUM(alloc_cpu_secs), "
			"@ESUM:=SUM(consumed_energy) "
			"from \"%s_%s\" where "
			"(time_start < %ld && time_start >= %ld) "
			"group by id_assoc on duplicate key update "
			"mod_time=%ld, alloc_cpu_secs=@ASUM, "
			"consumed_energy=@ESUM;",
			cluster_name, assoc_month_table, now, now, curr_start,
			cluster_name, assoc_day_table,
			curr_end, curr_start, now);
		/* We group on deleted here so if there are no entries
		   we don't get an error, just nothing is returned.
		   Else we get a bunch of NULL's
		*/
		xstrfmtcat(query,
			   "insert into \"%s_%s\" (creation_time, "
			   "mod_time, time_start, cpu_count, "
			   "alloc_cpu_secs, down_cpu_secs, pdown_cpu_secs, "
			   "idle_cpu_secs, over_cpu_secs, resv_cpu_secs, "
			   "consumed_energy) "
			   "select %ld, %ld, "
			   "%ld, @CPU:=MAX(cpu_count), "
			   "@ASUM:=SUM(alloc_cpu_secs), "
			   "@DSUM:=SUM(down_cpu_secs), "
			   "@PDSUM:=SUM(pdown_cpu_secs), "
			   "@ISUM:=SUM(idle_cpu_secs), "
			   "@OSUM:=SUM(over_cpu_secs), "
			   "@RSUM:=SUM(resv_cpu_secs), "
			   "@ESUM:=SUM(consumed_energy) from \"%s_%s\" where "
			   "(time_start < %ld && time_start >= %ld) "
			   "group by deleted "
			   "on duplicate key update "
			   "mod_time=%ld, cpu_count=@CPU, "
			   "alloc_cpu_secs=@ASUM, down_cpu_secs=@DSUM, "
			   "pdown_cpu_secs=@PDSUM, idle_cpu_secs=@ISUM, "
			   "over_cpu_secs=@OSUM, resv_cpu_secs=@RSUM, "
			   "consumed_energy=@ESUM;",
			   cluster_name, cluster_month_table,
			   now, now, curr_start,
			   cluster_name, cluster_day_table,
			   curr_end, curr_start, now);
		if (track_wckey) {
			xstrfmtcat(query,
				   "insert into \"%s_%s\" "
				   "(creation_time, mod_time, "
				   "id_wckey, time_start, alloc_cpu_secs, "
				   "consumed_energy) "
				   "select %ld, %ld, id_wckey, %ld, "
				   "@ASUM:=SUM(alloc_cpu_secs), "
				   "@ESUM:=SUM(consumed_energy) "
				   "from \"%s_%s\" where (time_start < %ld && "
				   "time_start >= %ld) "
				   "group by id_wckey on duplicate key update "
				   "mod_time=%ld, alloc_cpu_secs=@ASUM, "
				   "consumed_energy=@ESUM;",
				   cluster_name, wckey_month_table,
				   now, now, curr_start,
				   cluster_name, wckey_day_table,
				   curr_end, curr_start, now);
		}
		if (debug_flags & DEBUG_FLAG_DB_USAGE)
			DB_DEBUG(mysql_conn->conn, "query\n%s", query);
		rc = mysql_db_query(mysql_conn, query);
		xfree(query);
		if (rc != SLURM_SUCCESS) {
			error("Couldn't add day rollup");
			return SLURM_ERROR;
		}

		curr_start = curr_end;
		if (!localtime_r(&curr_start, &start_tm)) {
			error("Couldn't get localtime from month start %ld",
			      curr_start);
		}
		start_tm.tm_sec = 0;
		start_tm.tm_min = 0;
		start_tm.tm_hour = 0;
		start_tm.tm_mday = 1;
		start_tm.tm_mon++;
		start_tm.tm_isdst = -1;
		curr_end = mktime(&start_tm);
	}

	/* go check to see if we archive and purge */
	rc = _process_purge(mysql_conn, cluster_name, archive_data,
			    SLURMDB_PURGE_MONTHS);

	return rc;
}
コード例 #16
0
ファイル: as_mysql_acct.c プロジェクト: CornellCAC/slurm
extern int as_mysql_add_accts(mysql_conn_t *mysql_conn, uint32_t uid,
			      List acct_list)
{
	ListIterator itr = NULL;
	int rc = SLURM_SUCCESS;
	slurmdb_account_rec_t *object = NULL;
	char *cols = NULL, *vals = NULL, *query = NULL, *txn_query = NULL;
	time_t now = time(NULL);
	char *user_name = NULL;
	char *extra = NULL, *tmp_extra = NULL;

	int affect_rows = 0;
	List assoc_list = list_create(slurmdb_destroy_association_rec);

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	user_name = uid_to_string((uid_t) uid);
	itr = list_iterator_create(acct_list);
	while ((object = list_next(itr))) {
		if (!object->name || !object->name[0]
		    || !object->description || !object->description[0]
		    || !object->organization || !object->organization[0]) {
			error("We need an account name, description, and "
			      "organization to add. %s %s %s",
			      object->name, object->description,
			      object->organization);
			rc = SLURM_ERROR;
			continue;
		}
		xstrcat(cols, "creation_time, mod_time, name, "
			"description, organization");
		xstrfmtcat(vals, "%ld, %ld, '%s', '%s', '%s'",
			   now, now, object->name,
			   object->description, object->organization);
		xstrfmtcat(extra, ", description='%s', organization='%s'",
			   object->description, object->organization);

		query = xstrdup_printf(
			"insert into %s (%s) values (%s) "
			"on duplicate key update deleted=0, mod_time=%ld %s;",
			acct_table, cols, vals,
			now, extra);
		if (debug_flags & DEBUG_FLAG_DB_ASSOC)
			DB_DEBUG(mysql_conn->conn, "query\n%s", query);
		rc = mysql_db_query(mysql_conn, query);
		xfree(cols);
		xfree(vals);
		xfree(query);
		if (rc != SLURM_SUCCESS) {
			error("Couldn't add acct");
			xfree(extra);
			continue;
		}
		affect_rows = last_affected_rows(mysql_conn);
		/* if (debug_flags & DEBUG_FLAG_DB_ASSOC) */
		/* 	DB_DEBUG(mysql_conn->conn, "affected %d", affect_rows); */

		if (!affect_rows) {
			if (debug_flags & DEBUG_FLAG_DB_ASSOC)
				DB_DEBUG(mysql_conn->conn, "nothing changed");
			xfree(extra);
			continue;
		}

		/* we always have a ', ' as the first 2 chars */
		tmp_extra = slurm_add_slash_to_quotes(extra+2);

		if (txn_query)
			xstrfmtcat(txn_query,
				   ", (%ld, %u, '%s', '%s', '%s')",
				   now, DBD_ADD_ACCOUNTS, object->name,
				   user_name, tmp_extra);
		else
			xstrfmtcat(txn_query,
				   "insert into %s "
				   "(timestamp, action, name, actor, info) "
				   "values (%ld, %u, '%s', '%s', '%s')",
				   txn_table,
				   now, DBD_ADD_ACCOUNTS, object->name,
				   user_name, tmp_extra);
		xfree(tmp_extra);
		xfree(extra);

		if (!object->assoc_list)
			continue;

		list_transfer(assoc_list, object->assoc_list);
	}
	list_iterator_destroy(itr);
	xfree(user_name);

	if (rc != SLURM_ERROR) {
		if (txn_query) {
			xstrcat(txn_query, ";");
			rc = mysql_db_query(mysql_conn,
					    txn_query);
			xfree(txn_query);
			if (rc != SLURM_SUCCESS) {
				error("Couldn't add txn");
				rc = SLURM_SUCCESS;
			}
		}
	} else
		xfree(txn_query);

	if (list_count(assoc_list)) {
		if (as_mysql_add_assocs(mysql_conn, uid, assoc_list)
		    == SLURM_ERROR) {
			error("Problem adding user associations");
			rc = SLURM_ERROR;
		}
	}
	list_destroy(assoc_list);

	return rc;
}
コード例 #17
0
ファイル: as_mysql_cluster.c プロジェクト: FredHutch/slurm
extern List as_mysql_remove_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
				     slurmdb_cluster_cond_t *cluster_cond)
{
	ListIterator itr = NULL;
	List ret_list = NULL;
	List tmp_list = NULL;
	int rc = SLURM_SUCCESS;
	char *object = NULL;
	char *extra = NULL, *query = NULL, *cluster_name = NULL,
		*name_char = NULL, *assoc_char = NULL;
	time_t now = time(NULL);
	char *user_name = NULL;
	slurmdb_wckey_cond_t wckey_cond;
	MYSQL_RES *result = NULL;
	MYSQL_ROW row;
	bool jobs_running = 0;

	if (!cluster_cond) {
		error("we need something to change");
		return NULL;
	}

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return NULL;

	if (!is_user_min_admin_level(
		    mysql_conn, uid, SLURMDB_ADMIN_SUPER_USER)) {
		errno = ESLURM_ACCESS_DENIED;
		return NULL;
	}

	/* force to only do non-deleted clusters */
	cluster_cond->with_deleted = 0;
	_setup_cluster_cond_limits(cluster_cond, &extra);

	if (!extra) {
		error("Nothing to remove");
		return NULL;
	}

	query = xstrdup_printf("select name from %s%s;", cluster_table, extra);
	xfree(extra);
	if (!(result = mysql_db_query_ret(
		      mysql_conn, query, 0))) {
		xfree(query);
		return NULL;
	}
	rc = 0;
	ret_list = list_create(slurm_destroy_char);

	if (!mysql_num_rows(result)) {
		mysql_free_result(result);
		errno = SLURM_NO_CHANGE_IN_DATA;
		if (debug_flags & DEBUG_FLAG_DB_ASSOC)
			DB_DEBUG(mysql_conn->conn,
				 "didn't effect anything\n%s", query);
		xfree(query);
		return ret_list;
	}
	xfree(query);

	assoc_char = xstrdup_printf("t2.acct='root'");

	user_name = uid_to_string((uid_t) uid);
	while ((row = mysql_fetch_row(result))) {
		char *object = xstrdup(row[0]);
		if (!jobs_running)
			list_append(ret_list, object);

		xfree(name_char);
		xstrfmtcat(name_char, "name='%s'", object);
		if (jobs_running)
			xfree(object);
		/* We should not need to delete any cluster usage just set it
		 * to deleted */
		xstrfmtcat(query,
			   "update \"%s_%s\" set time_end=%ld where time_end=0;"
			   "update \"%s_%s\" set mod_time=%ld, deleted=1;"
			   "update \"%s_%s\" set mod_time=%ld, deleted=1;"
			   "update \"%s_%s\" set mod_time=%ld, deleted=1;",
			   object, event_table, now,
			   object, cluster_day_table, now,
			   object, cluster_hour_table, now,
			   object, cluster_month_table, now);
		if ((rc = remove_common(mysql_conn, DBD_REMOVE_CLUSTERS, now,
					user_name, cluster_table,
					name_char, assoc_char, object,
					ret_list, &jobs_running))
		    != SLURM_SUCCESS)
			break;
	}
	mysql_free_result(result);
	xfree(user_name);
	xfree(name_char);
	xfree(assoc_char);

	if (rc != SLURM_SUCCESS) {
		FREE_NULL_LIST(ret_list);
		return NULL;
	}
	if (!jobs_running) {
		if (debug_flags & DEBUG_FLAG_DB_ASSOC)
			DB_DEBUG(mysql_conn->conn, "query\n%s", query);
		rc = mysql_db_query(mysql_conn, query);
		xfree(query);
		if (rc != SLURM_SUCCESS) {
			reset_mysql_conn(mysql_conn);
			FREE_NULL_LIST(ret_list);
			return NULL;
		}

		/* We need to remove these clusters from the wckey table */
		memset(&wckey_cond, 0, sizeof(slurmdb_wckey_cond_t));
		wckey_cond.cluster_list = ret_list;
		tmp_list = as_mysql_remove_wckeys(mysql_conn, uid, &wckey_cond);
		FREE_NULL_LIST(tmp_list);

		itr = list_iterator_create(ret_list);
		while ((object = list_next(itr))) {
			if ((rc = remove_cluster_tables(mysql_conn, object))
			    != SLURM_SUCCESS)
				break;
			cluster_name = xstrdup(object);
			if (addto_update_list(mysql_conn->update_list,
					      SLURMDB_REMOVE_CLUSTER,
					      cluster_name) != SLURM_SUCCESS)
				xfree(cluster_name);
		}
		list_iterator_destroy(itr);

		if (rc != SLURM_SUCCESS) {
			reset_mysql_conn(mysql_conn);
			FREE_NULL_LIST(ret_list);
			errno = rc;
			return NULL;
		}
		errno = SLURM_SUCCESS;
	} else
		errno = ESLURM_JOBS_RUNNING_ON_ASSOC;

	return ret_list;
}
コード例 #18
0
ファイル: as_mysql_cluster.c プロジェクト: FredHutch/slurm
extern int as_mysql_cluster_tres(mysql_conn_t *mysql_conn,
				 char *cluster_nodes, char **tres_str_in,
				 time_t event_time)
{
	char* query;
	int rc = SLURM_SUCCESS;
	int first = 0;
	MYSQL_RES *result = NULL;
	MYSQL_ROW row;

	xassert(tres_str_in);

 	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	if (!mysql_conn->cluster_name) {
		error("%s:%d no cluster name", THIS_FILE, __LINE__);
		return SLURM_ERROR;
	}

	/* Record the processor count */
	query = xstrdup_printf(
		"select tres, cluster_nodes from \"%s_%s\" where "
		"time_end=0 and node_name='' and state=0 limit 1",
		mysql_conn->cluster_name, event_table);
	if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) {
		xfree(query);
		if (mysql_errno(mysql_conn->db_conn) == ER_NO_SUCH_TABLE)
			rc = ESLURM_ACCESS_DENIED;
		else
			rc = SLURM_ERROR;
		return rc;
	}
	xfree(query);

	/* we only are checking the first one here */
	if (!(row = mysql_fetch_row(result))) {
		debug("We don't have an entry for this machine %s "
		      "most likely a first time running.",
		      mysql_conn->cluster_name);

		/* Get all nodes in a down state and jobs pending or running.
		 * This is for the first time a cluster registers
		 *
		 * We will return ACCOUNTING_FIRST_REG so this
		 * is taken care of since the message thread
		 * may not be up when we run this in the controller or
		 * in the slurmdbd.
		 */
		if (!*tres_str_in) {
			rc = 0;
			goto end_it;
		}

		first = 1;
		goto add_it;
	}

	/* If tres is NULL we want to return the tres for this cluster */
	if (!*tres_str_in) {
		*tres_str_in = xstrdup(row[0]);
		goto end_it;
	} else if (xstrcmp(*tres_str_in, row[0])) {
		debug("%s has changed tres from %s to %s",
		      mysql_conn->cluster_name,
		      row[0], *tres_str_in);
	} else {
		if (debug_flags & DEBUG_FLAG_DB_EVENT)
			DB_DEBUG(mysql_conn->conn,
				 "We have the same tres as before for %s, "
				 "no need to update the database.",
				 mysql_conn->cluster_name);

		if (cluster_nodes) {
			if (!row[1][0]) {
				debug("Adding cluster nodes '%s' to "
				      "last instance of cluster '%s'.",
				      cluster_nodes, mysql_conn->cluster_name);
				query = xstrdup_printf(
					"update \"%s_%s\" set "
					"cluster_nodes='%s' "
					"where time_end=0 and node_name=''",
					mysql_conn->cluster_name,
					event_table, cluster_nodes);
				(void) mysql_db_query(mysql_conn, query);
				xfree(query);
				goto update_it;
			} else if (!strcmp(cluster_nodes, row[1])) {
				if (debug_flags & DEBUG_FLAG_DB_EVENT)
					DB_DEBUG(mysql_conn->conn,
						 "we have the same nodes "
						 "in the cluster "
						 "as before no need to "
						 "update the database.");
				goto update_it;
			}
		}

		goto end_it;
	}

	/* reset all the entries for this cluster since the tres
	   changed some of the downed nodes may have gone away.
	   Request them again with ACCOUNTING_FIRST_REG */
	query = xstrdup_printf(
		"update \"%s_%s\" set time_end=%ld where time_end=0",
		mysql_conn->cluster_name, event_table, event_time);
	rc = mysql_db_query(mysql_conn, query);
	xfree(query);
	first = 1;
	if (rc != SLURM_SUCCESS)
		goto end_it;
add_it:
	query = xstrdup_printf(
		"insert into \"%s_%s\" (cluster_nodes, tres, "
		"time_start, reason) "
		"values ('%s', '%s', %ld, 'Cluster Registered TRES');",
		mysql_conn->cluster_name, event_table,
		cluster_nodes, *tres_str_in, event_time);
	(void) mysql_db_query(mysql_conn, query);
	xfree(query);
update_it:
	query = xstrdup_printf(
		"update \"%s_%s\" set time_end=%ld where time_end=0 "
		"and state=%u and node_name='';",
		mysql_conn->cluster_name, event_table, event_time,
		NODE_STATE_DOWN);
	rc = mysql_db_query(mysql_conn, query);
	xfree(query);
end_it:
	mysql_free_result(result);
	if (first && rc == SLURM_SUCCESS)
		rc = ACCOUNTING_FIRST_REG;

	return rc;
}
コード例 #19
0
ファイル: as_mysql_cluster.c プロジェクト: FredHutch/slurm
extern int as_mysql_fini_ctld(mysql_conn_t *mysql_conn,
			      slurmdb_cluster_rec_t *cluster_rec)
{
	int rc = SLURM_SUCCESS;
	time_t now = time(NULL);
	char *query = NULL;
	bool free_it = false;

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	/* Here we need to check make sure we are updating the entry
	   correctly just incase the backup has already gained
	   control.  If we check the ip and port it is a pretty safe
	   bet we have the right ctld.
	*/
	query = xstrdup_printf(
		"update %s set mod_time=%ld, control_host='', "
		"control_port=0 where name='%s' && "
		"control_host='%s' && control_port=%u;",
		cluster_table, now, cluster_rec->name,
		cluster_rec->control_host, cluster_rec->control_port);
	if (debug_flags & DEBUG_FLAG_DB_EVENT)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);
	rc = mysql_db_query(mysql_conn, query);
	xfree(query);

	if (rc != SLURM_SUCCESS)
		return SLURM_ERROR;

	if (!last_affected_rows(mysql_conn)
	    || (slurmdbd_conf && !slurmdbd_conf->track_ctld))
		return rc;

	/* If tres is NULL we can get the current number of tres by
	   sending NULL for the tres param in the as_mysql_cluster_tres
	   function.
	*/
	if (!cluster_rec->tres_str) {
		free_it = true;
		as_mysql_cluster_tres(
			mysql_conn, cluster_rec->control_host,
			&cluster_rec->tres_str, now);
	}

	/* Since as_mysql_cluster_tres could change the
	   last_affected_rows we can't group this with the above
	   return.
	*/
	if (!cluster_rec->tres_str)
		return rc;

	/* If we affected things we need to now drain the nodes in the
	 * cluster.  This is to give better stats on accounting that
	 * the ctld was gone so no jobs were able to be scheduled.  We
	 * drain the nodes since the rollup functionality understands
	 * how to deal with that and running jobs so we don't get bad
	 * info.
	 */
	query = xstrdup_printf(
		"insert into \"%s_%s\" (tres, state, time_start, reason) "
		"values ('%s', %u, %ld, 'slurmctld disconnect');",
		cluster_rec->name, event_table,
		cluster_rec->tres_str, NODE_STATE_DOWN, (long)now);

	if (free_it)
		xfree(cluster_rec->tres_str);

	if (debug_flags & DEBUG_FLAG_DB_EVENT)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);
	rc = mysql_db_query(mysql_conn, query);
	xfree(query);

	return rc;
}
コード例 #20
0
ファイル: as_mysql_cluster.c プロジェクト: FredHutch/slurm
extern int as_mysql_add_clusters(mysql_conn_t *mysql_conn, uint32_t uid,
				 List cluster_list)
{
	ListIterator itr = NULL;
	int rc = SLURM_SUCCESS;
	slurmdb_cluster_rec_t *object = NULL;
	char *cols = NULL, *vals = NULL, *extra = NULL,
		*query = NULL, *tmp_extra = NULL;
	time_t now = time(NULL);
	char *user_name = NULL;
	int affect_rows = 0;
	int added = 0;
	List assoc_list = NULL;
	slurmdb_assoc_rec_t *assoc = NULL;

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	if (!is_user_min_admin_level(mysql_conn, uid, SLURMDB_ADMIN_SUPER_USER))
		return ESLURM_ACCESS_DENIED;

	assoc_list = list_create(slurmdb_destroy_assoc_rec);

	user_name = uid_to_string((uid_t) uid);
	/* Since adding tables make it so you can't roll back, if
	   there is an error there is no way to easily remove entries
	   in the database, so we will create the tables first and
	   then after that works out then add them to the mix.
	*/
	itr = list_iterator_create(cluster_list);
	while ((object = list_next(itr))) {
		if (!object->name || !object->name[0]) {
			error("We need a cluster name to add.");
			rc = SLURM_ERROR;
			list_remove(itr);
			continue;
		}
		if ((rc = create_cluster_tables(mysql_conn,
						object->name))
		    != SLURM_SUCCESS) {
			xfree(extra);
			xfree(cols);
			xfree(vals);
			added = 0;
			if (mysql_errno(mysql_conn->db_conn)
			    == ER_WRONG_TABLE_NAME)
				rc = ESLURM_BAD_NAME;
			goto end_it;
		}
	}

	/* Now that all the tables were created successfully lets go
	   ahead and add it to the system.
	*/
	list_iterator_reset(itr);
	while ((object = list_next(itr))) {
		xstrcat(cols, "creation_time, mod_time, acct");
		xstrfmtcat(vals, "%ld, %ld, 'root'", now, now);
		xstrfmtcat(extra, ", mod_time=%ld", now);
		if (object->root_assoc)
			setup_assoc_limits(object->root_assoc, &cols,
					   &vals, &extra,
					   QOS_LEVEL_SET, 1);
		xstrfmtcat(query,
			   "insert into %s (creation_time, mod_time, "
			   "name, classification) "
			   "values (%ld, %ld, '%s', %u) "
			   "on duplicate key update deleted=0, mod_time=%ld, "
			   "control_host='', control_port=0, "
			   "classification=%u, flags=0",
			   cluster_table,
			   now, now, object->name, object->classification,
			   now, object->classification);
		if (debug_flags & DEBUG_FLAG_DB_ASSOC)
			DB_DEBUG(mysql_conn->conn, "query\n%s", query);
		rc = mysql_db_query(mysql_conn, query);
		xfree(query);
		if (rc != SLURM_SUCCESS) {
			error("Couldn't add cluster %s", object->name);
			xfree(extra);
			xfree(cols);
			xfree(vals);
			added=0;
			break;
		}

		affect_rows = last_affected_rows(mysql_conn);

		if (!affect_rows) {
			debug2("nothing changed %d", affect_rows);
			xfree(extra);
			xfree(cols);
			xfree(vals);
			continue;
		}

		xstrfmtcat(query,
			   "insert into \"%s_%s\" (%s, lft, rgt) "
			   "values (%s, 1, 2) "
			   "on duplicate key update deleted=0, "
			   "id_assoc=LAST_INSERT_ID(id_assoc)%s;",
			   object->name, assoc_table, cols,
			   vals,
			   extra);

		xfree(cols);
		xfree(vals);
		if (debug_flags & DEBUG_FLAG_DB_ASSOC)
			DB_DEBUG(mysql_conn->conn, "query\n%s", query);

		rc = mysql_db_query(mysql_conn, query);
		xfree(query);

		if (rc != SLURM_SUCCESS) {
			error("Couldn't add cluster root assoc");
			xfree(extra);
			added=0;
			break;
		}

		/* we always have a ', ' as the first 2 chars */
		tmp_extra = slurm_add_slash_to_quotes(extra+2);

		xstrfmtcat(query,
			   "insert into %s "
			   "(timestamp, action, name, actor, info) "
			   "values (%ld, %u, '%s', '%s', '%s');",
			   txn_table, now, DBD_ADD_CLUSTERS,
			   object->name, user_name, tmp_extra);
		xfree(tmp_extra);
		xfree(extra);
		debug4("%d(%s:%d) query\n%s",
		       mysql_conn->conn, THIS_FILE, __LINE__, query);

		rc = mysql_db_query(mysql_conn, query);
		xfree(query);
		if (rc != SLURM_SUCCESS) {
			error("Couldn't add txn");
		} else {
			ListIterator check_itr;
			char *tmp_name;

			added++;
			/* add it to the list and sort */
			slurm_mutex_lock(&as_mysql_cluster_list_lock);
			check_itr = list_iterator_create(as_mysql_cluster_list);
			while ((tmp_name = list_next(check_itr))) {
				if (!strcmp(tmp_name, object->name))
					break;
			}
			list_iterator_destroy(check_itr);
			if (!tmp_name) {
				list_append(as_mysql_cluster_list,
					    xstrdup(object->name));
				list_sort(as_mysql_cluster_list,
					  (ListCmpF)slurm_sort_char_list_asc);
			} else
				error("Cluster %s(%s) appears to already be in "
				      "our cache list, not adding.", tmp_name,
				      object->name);
			slurm_mutex_unlock(&as_mysql_cluster_list_lock);
		}
		/* Add user root by default to run from the root
		 * association.  This gets popped off so we need to
		 * read it every time here.
		 */
		assoc = xmalloc(sizeof(slurmdb_assoc_rec_t));
		slurmdb_init_assoc_rec(assoc, 0);
		list_append(assoc_list, assoc);

		assoc->cluster = xstrdup(object->name);
		assoc->user = xstrdup("root");
		assoc->acct = xstrdup("root");
		assoc->is_def = 1;

		if (as_mysql_add_assocs(mysql_conn, uid, assoc_list)
		    == SLURM_ERROR) {
			error("Problem adding root user association");
			rc = SLURM_ERROR;
		}
	}
end_it:
	list_iterator_destroy(itr);
	xfree(user_name);

	FREE_NULL_LIST(assoc_list);

	if (!added)
		reset_mysql_conn(mysql_conn);

	return rc;
}
コード例 #21
0
ファイル: as_mysql_user.c プロジェクト: BYUHPC/slurm
extern int as_mysql_add_users(mysql_conn_t *mysql_conn, uint32_t uid,
			      List user_list)
{
	ListIterator itr = NULL;
	int rc = SLURM_SUCCESS;
	slurmdb_user_rec_t *object = NULL;
	char *cols = NULL, *vals = NULL, *query = NULL, *txn_query = NULL;
	time_t now = time(NULL);
	char *user_name = NULL;
	char *extra = NULL, *tmp_extra = NULL;
	int affect_rows = 0;
	List assoc_list = list_create(slurmdb_destroy_association_rec);
	List wckey_list = list_create(slurmdb_destroy_wckey_rec);

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	user_name = uid_to_string((uid_t) uid);
	itr = list_iterator_create(user_list);
	while ((object = list_next(itr))) {
		if (!object->name || !object->name[0]) {
			error("We need a user name and "
			      "default acct to add.");
			rc = SLURM_ERROR;
			continue;
		}
		xstrcat(cols, "creation_time, mod_time, name");
		xstrfmtcat(vals, "%ld, %ld, '%s'",
			   (long)now, (long)now, object->name);

		if (object->admin_level != SLURMDB_ADMIN_NOTSET) {
			xstrcat(cols, ", admin_level");
			xstrfmtcat(vals, ", %u", object->admin_level);
			xstrfmtcat(extra, ", admin_level=%u",
				   object->admin_level);
		} else
			xstrfmtcat(extra, ", admin_level=%u",
				   SLURMDB_ADMIN_NONE);

		query = xstrdup_printf(
			"insert into %s (%s) values (%s) "
			"on duplicate key update deleted=0, mod_time=%ld %s;",
			user_table, cols, vals,
			(long)now, extra);
		xfree(cols);
		xfree(vals);

		rc = mysql_db_query(mysql_conn, query);
		xfree(query);
		if (rc != SLURM_SUCCESS) {
			error("Couldn't add user %s", object->name);
			xfree(extra);
			continue;
		}

		affect_rows = last_affected_rows(mysql_conn);
		if (!affect_rows) {
			debug("nothing changed");
			xfree(extra);
			continue;
		}

		if (addto_update_list(mysql_conn->update_list, SLURMDB_ADD_USER,
				      object) == SLURM_SUCCESS)
			list_remove(itr);

		/* we always have a ', ' as the first 2 chars */
		tmp_extra = slurm_add_slash_to_quotes(extra+2);

		if (txn_query)
			xstrfmtcat(txn_query,
				   ", (%ld, %u, '%s', '%s', '%s')",
				   (long)now, DBD_ADD_USERS, object->name,
				   user_name, tmp_extra);
		else
			xstrfmtcat(txn_query,
				   "insert into %s "
				   "(timestamp, action, name, actor, info) "
				   "values (%ld, %u, '%s', '%s', '%s')",
				   txn_table,
				   (long)now, DBD_ADD_USERS, object->name,
				   user_name, tmp_extra);
		xfree(tmp_extra);
		xfree(extra);

		/* For < 2.2 systems we need to set the is_def flag in
		   the default association/wckey so as to make sure we get
		   it set correctly.
		*/
		if (object->assoc_list) {
			slurmdb_association_rec_t *assoc = NULL;
			ListIterator assoc_itr =
				list_iterator_create(object->assoc_list);
			while ((assoc = list_next(assoc_itr))) {
				/* We need to mark all of the
				   associations with this account
				   since there could be multiple
				   clusters here.
				*/
				if (!strcmp(assoc->acct, object->default_acct))
					assoc->is_def = 1;
			}
			list_iterator_destroy(assoc_itr);
			list_transfer(assoc_list, object->assoc_list);
		}

		if (object->wckey_list) {
			if (object->default_wckey) {
				slurmdb_wckey_rec_t *wckey = NULL;
				ListIterator wckey_itr = list_iterator_create(
					object->wckey_list);
				while ((wckey = list_next(wckey_itr))) {
					/* We need to mark all of the
					   wckeys with this account
					   since there could be multiple
					   clusters here.
					*/
					if (!strcmp(wckey->name,
						    object->default_wckey))
						wckey->is_def = 1;
				}
				list_iterator_destroy(wckey_itr);
			}
			list_transfer(wckey_list, object->wckey_list);
		}
	}
	list_iterator_destroy(itr);
	xfree(user_name);

	if (rc != SLURM_ERROR) {
		if (txn_query) {
			xstrcat(txn_query, ";");
			rc = mysql_db_query(mysql_conn,
					    txn_query);
			xfree(txn_query);
			if (rc != SLURM_SUCCESS) {
				error("Couldn't add txn");
				rc = SLURM_SUCCESS;
			}
		}
	} else
		xfree(txn_query);

	if (list_count(assoc_list)) {
		if (as_mysql_add_assocs(mysql_conn, uid, assoc_list)
		    == SLURM_ERROR) {
			error("Problem adding user associations");
			rc = SLURM_ERROR;
		}
	}
	list_destroy(assoc_list);

	if (list_count(wckey_list)) {
		if (as_mysql_add_wckeys(mysql_conn, uid, wckey_list)
		    == SLURM_ERROR) {
			error("Problem adding user wckeys");
			rc = SLURM_ERROR;
		}
	}
	list_destroy(wckey_list);
	return rc;
}
コード例 #22
0
ファイル: as_mysql_cluster.c プロジェクト: FredHutch/slurm
extern int as_mysql_node_down(mysql_conn_t *mysql_conn,
			      struct node_record *node_ptr,
			      time_t event_time, char *reason,
			      uint32_t reason_uid)
{
	int rc = SLURM_SUCCESS;
	char *query = NULL;
	char *my_reason;
	MYSQL_RES *result = NULL;
	MYSQL_ROW row;

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	if (!mysql_conn->cluster_name) {
		error("%s:%d no cluster name", THIS_FILE, __LINE__);
		return SLURM_ERROR;
	}

	if (!node_ptr) {
		error("No node_ptr given!");
		return SLURM_ERROR;
	}

	if (!node_ptr->tres_str) {
		error("node ptr has no tres_list!");
		return SLURM_ERROR;
	}

	query = xstrdup_printf("select state, reason from \"%s_%s\" where "
			       "time_end=0 and node_name='%s';",
			       mysql_conn->cluster_name, event_table,
			       node_ptr->name);
	/* info("%d(%s:%d) query\n%s", */
	/*        mysql_conn->conn, THIS_FILE, __LINE__, query); */
	result = mysql_db_query_ret(mysql_conn, query, 0);
	xfree(query);

	if (!result)
		return SLURM_ERROR;

	if (reason)
		my_reason = slurm_add_slash_to_quotes(reason);
	else
		my_reason = slurm_add_slash_to_quotes(node_ptr->reason);

	row = mysql_fetch_row(result);
	if (row && (node_ptr->node_state == slurm_atoul(row[0])) &&
	    my_reason && row[1] &&
	    !strcasecmp(my_reason, row[1])) {
		debug("as_mysql_node_down: no change needed %u == %s "
		      "and %s == %s",
		     node_ptr->node_state, row[0], my_reason, row[1]);
		xfree(my_reason);
		mysql_free_result(result);
		return SLURM_SUCCESS;
	}
	mysql_free_result(result);

	debug2("inserting %s(%s) with tres of '%s'",
	       node_ptr->name, mysql_conn->cluster_name, node_ptr->tres_str);

	query = xstrdup_printf(
		"update \"%s_%s\" set time_end=%ld where "
		"time_end=0 and node_name='%s';",
		mysql_conn->cluster_name, event_table,
		event_time, node_ptr->name);
	/* If you are clean-restarting the controller over and over again you
	 * could get records that are duplicates in the database.  If
	 * this is the case we will zero out the time_end we are
	 * just filled in.  This will cause the last time to be erased
	 * from the last restart, but if you are restarting things
	 * this often the pervious one didn't mean anything anyway.
	 * This way we only get one for the last time we let it run.
	 */
	xstrfmtcat(query,
		   "insert into \"%s_%s\" "
		   "(node_name, state, tres, time_start, "
		   "reason, reason_uid) "
		   "values ('%s', %u, '%s', %ld, '%s', %u) "
		   "on duplicate key update time_end=0;",
		   mysql_conn->cluster_name, event_table,
		   node_ptr->name, node_ptr->node_state,
		   node_ptr->tres_str, event_time, my_reason, reason_uid);
	debug2("%d(%s:%d) query\n%s",
	       mysql_conn->conn, THIS_FILE, __LINE__, query);
	rc = mysql_db_query(mysql_conn, query);
	xfree(query);
	xfree(my_reason);
	return rc;
}
コード例 #23
0
ファイル: as_mysql_txn.c プロジェクト: A1ve5/slurm
extern List as_mysql_get_txn(mysql_conn_t *mysql_conn, uid_t uid,
			     slurmdb_txn_cond_t *txn_cond)
{
	char *query = NULL;
	char *assoc_extra = NULL;
	char *name_extra = NULL;
	char *extra = NULL;
	char *tmp = NULL;
	List txn_list = NULL;
	ListIterator itr = NULL;
	char *object = NULL;
	int set = 0;
	int i=0;
	MYSQL_RES *result = NULL;
	MYSQL_ROW row;
	List use_cluster_list = as_mysql_cluster_list;
	bool locked = 0;

	/* if this changes you will need to edit the corresponding enum */
	char *txn_req_inx[] = {
		"id",
		"timestamp",
		"action",
		"name",
		"actor",
		"info",
		"cluster"
	};
	enum {
		TXN_REQ_ID,
		TXN_REQ_TS,
		TXN_REQ_ACTION,
		TXN_REQ_NAME,
		TXN_REQ_ACTOR,
		TXN_REQ_INFO,
		TXN_REQ_CLUSTER,
		TXN_REQ_COUNT
	};

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return NULL;

	if (!txn_cond)
		goto empty;

	/* handle query for associations first */
	if (txn_cond->acct_list && list_count(txn_cond->acct_list)) {
		set = 0;
		if (assoc_extra)
			xstrcat(assoc_extra, " && (");
		else
			xstrcat(assoc_extra, " where (");

		if (name_extra)
			xstrcat(name_extra, " && (");
		else
			xstrcat(name_extra, " (");
		itr = list_iterator_create(txn_cond->acct_list);
		while ((object = list_next(itr))) {
			if (set) {
				xstrcat(assoc_extra, " || ");
				xstrcat(name_extra, " || ");
			}

			xstrfmtcat(assoc_extra, "acct='%s'", object);

			xstrfmtcat(name_extra, "(name like '%%\\'%s\\'%%'"
				   " || name='%s')"
				   " || (info like '%%acct=\\'%s\\'%%')",
				   object, object, object);
			set = 1;
		}
		list_iterator_destroy(itr);
		xstrcat(assoc_extra, ")");
		xstrcat(name_extra, ")");
	}

	if (txn_cond->cluster_list && list_count(txn_cond->cluster_list)) {
		set = 0;
		if (name_extra)
			xstrcat(name_extra, " && (");
		else
			xstrcat(name_extra, "(");

		itr = list_iterator_create(txn_cond->cluster_list);
		while ((object = list_next(itr))) {
			if (set) {
				xstrcat(name_extra, " || ");
			}
			xstrfmtcat(name_extra, "(cluster='%s' || "
				   "name like '%%\\'%s\\'%%' || name='%s')"
				   " || (info like '%%cluster=\\'%s\\'%%')",
				   object, object, object, object);
			set = 1;
		}
		list_iterator_destroy(itr);
		xstrcat(name_extra, ")");
		use_cluster_list = txn_cond->cluster_list;
	}

	if (txn_cond->user_list && list_count(txn_cond->user_list)) {
		set = 0;
		if (assoc_extra)
			xstrcat(assoc_extra, " && (");
		else
			xstrcat(assoc_extra, " where (");

		if (name_extra)
			xstrcat(name_extra, " && (");
		else
			xstrcat(name_extra, "(");

		itr = list_iterator_create(txn_cond->user_list);
		while ((object = list_next(itr))) {
			if (set) {
				xstrcat(assoc_extra, " || ");
				xstrcat(name_extra, " || ");
			}
			xstrfmtcat(assoc_extra, "user='******'", object);

			xstrfmtcat(name_extra, "(name like '%%\\'%s\\'%%'"
				   " || name='%s')"
				   " || (info like '%%user=\\'%s\\'%%')",
				   object, object, object);

			set = 1;
		}
		list_iterator_destroy(itr);
		xstrcat(assoc_extra, ")");
		xstrcat(name_extra, ")");
	}

	if (assoc_extra) {
		if (!locked && (use_cluster_list == as_mysql_cluster_list)) {
			slurm_mutex_lock(&as_mysql_cluster_list_lock);
			locked = 1;
		}

		itr = list_iterator_create(use_cluster_list);
		while ((object = list_next(itr))) {
			xstrfmtcat(query, "select id_assoc from \"%s_%s\"%s",
				   object, assoc_table, assoc_extra);
			if (debug_flags & DEBUG_FLAG_DB_QUERY)
				DB_DEBUG(mysql_conn->conn, "query\n%s", query);
			if (!(result = mysql_db_query_ret(
				      mysql_conn, query, 0))) {
				xfree(query);
				break;
			}
			xfree(query);

			if (mysql_num_rows(result)) {
				if (extra)
					xstrfmtcat(extra,
						   " || (cluster='%s' && (",
						   object);
				else
					xstrfmtcat(extra,
						   " where (cluster='%s' && (",
						   object);

				set = 0;

				while ((row = mysql_fetch_row(result))) {
					if (set)
						xstrcat(extra, " || ");

					xstrfmtcat(extra,
						   "(name like "
						   "'%%id_assoc=%s %%' "
						   "|| name like "
						   "'%%id_assoc=%s)')",
						   row[0], row[0]);
					set = 1;
				}
				xstrcat(extra, "))");
			}
			mysql_free_result(result);
		}
		list_iterator_destroy(itr);

		xfree(assoc_extra);
	}

	if (name_extra) {
		if (extra)
			xstrfmtcat(extra, " && (%s)", name_extra);
		else
			xstrfmtcat(extra, " where (%s)", name_extra);
		xfree(name_extra);
	}
	/*******************************************/

	if (txn_cond->action_list && list_count(txn_cond->action_list)) {
		set = 0;
		if (extra)
			xstrcat(extra, " && (");
		else
			xstrcat(extra, " where (");
		itr = list_iterator_create(txn_cond->action_list);
		while ((object = list_next(itr))) {
			if (set)
				xstrcat(extra, " || ");
			xstrfmtcat(extra, "action='%s'", object);
			set = 1;
		}
		list_iterator_destroy(itr);
		xstrcat(extra, ")");
	}

	if (txn_cond->actor_list && list_count(txn_cond->actor_list)) {
		set = 0;
		if (extra)
			xstrcat(extra, " && (");
		else
			xstrcat(extra, " where (");
		itr = list_iterator_create(txn_cond->actor_list);
		while ((object = list_next(itr))) {
			if (set)
				xstrcat(extra, " || ");
			xstrfmtcat(extra, "actor='%s'", object);
			set = 1;
		}
		list_iterator_destroy(itr);
		xstrcat(extra, ")");
	}

	if (txn_cond->id_list && list_count(txn_cond->id_list)) {
		set = 0;
		if (extra)
			xstrcat(extra, " && (");
		else
			xstrcat(extra, " where (");
		itr = list_iterator_create(txn_cond->id_list);
		while ((object = list_next(itr))) {
			char *ptr = NULL;
			long num = strtol(object, &ptr, 10);
			if ((num == 0) && ptr && ptr[0]) {
				error("Invalid value for txn id (%s)",
				      object);
				xfree(extra);
				list_iterator_destroy(itr);
				goto end_it;
			}

			if (set)
				xstrcat(extra, " || ");
			xstrfmtcat(extra, "id=%s", object);
			set = 1;
		}
		list_iterator_destroy(itr);
		xstrcat(extra, ")");
	}

	if (txn_cond->info_list && list_count(txn_cond->info_list)) {
		set = 0;
		if (extra)
			xstrcat(extra, " && (");
		else
			xstrcat(extra, " where (");
		itr = list_iterator_create(txn_cond->info_list);
		while ((object = list_next(itr))) {
			if (set)
				xstrcat(extra, " || ");
			xstrfmtcat(extra, "info like '%%%s%%'", object);
			set = 1;
		}
		list_iterator_destroy(itr);
		xstrcat(extra, ")");
	}

	if (txn_cond->name_list && list_count(txn_cond->name_list)) {
		set = 0;
		if (extra)
			xstrcat(extra, " && (");
		else
			xstrcat(extra, " where (");
		itr = list_iterator_create(txn_cond->name_list);
		while ((object = list_next(itr))) {
			if (set)
				xstrcat(extra, " || ");
			xstrfmtcat(extra, "name like '%%%s%%'", object);
			set = 1;
		}
		list_iterator_destroy(itr);
		xstrcat(extra, ")");
	}

	if (txn_cond->time_start && txn_cond->time_end) {
		if (extra)
			xstrcat(extra, " && (");
		else
			xstrcat(extra, " where (");
		xstrfmtcat(extra, "timestamp < %ld && timestamp >= %ld)",
			   txn_cond->time_end, txn_cond->time_start);
	} else if (txn_cond->time_start) {
		if (extra)
			xstrcat(extra, " && (");
		else
			xstrcat(extra, " where (");
		xstrfmtcat(extra, "timestamp >= %ld)", txn_cond->time_start);

	} else if (txn_cond->time_end) {
		if (extra)
			xstrcat(extra, " && (");
		else
			xstrcat(extra, " where (");
		xstrfmtcat(extra, "timestamp < %ld)", txn_cond->time_end);
	}

	/* make sure we can get the max length out of the database
	 * when grouping the names
	 */
	if (txn_cond->with_assoc_info)
		mysql_db_query(mysql_conn,
			       "set session group_concat_max_len=65536;");

empty:
	if (!locked && (use_cluster_list == as_mysql_cluster_list)) {
		slurm_mutex_lock(&as_mysql_cluster_list_lock);
		locked = 1;
	}

	xfree(tmp);
	xstrfmtcat(tmp, "%s", txn_req_inx[i]);
	for(i=1; i<TXN_REQ_COUNT; i++) {
		xstrfmtcat(tmp, ", %s", txn_req_inx[i]);
	}

	query = xstrdup_printf("select %s from %s", tmp, txn_table);

	if (extra) {
		xstrfmtcat(query, "%s", extra);
		xfree(extra);
	}
	xstrcat(query, " order by timestamp;");

	xfree(tmp);

	if (debug_flags & DEBUG_FLAG_DB_QUERY)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);
	if (!(result = mysql_db_query_ret(
		      mysql_conn, query, 0))) {
		xfree(query);
		goto end_it;
	}
	xfree(query);

	txn_list = list_create(slurmdb_destroy_txn_rec);

	while ((row = mysql_fetch_row(result))) {
		slurmdb_txn_rec_t *txn = xmalloc(sizeof(slurmdb_txn_rec_t));

		list_append(txn_list, txn);

		txn->action = slurm_atoul(row[TXN_REQ_ACTION]);
		txn->actor_name = xstrdup(row[TXN_REQ_ACTOR]);
		txn->id = slurm_atoul(row[TXN_REQ_ID]);
		txn->set_info = xstrdup(row[TXN_REQ_INFO]);
		txn->timestamp = slurm_atoul(row[TXN_REQ_TS]);
		txn->where_query = xstrdup(row[TXN_REQ_NAME]);
		txn->clusters = xstrdup(row[TXN_REQ_CLUSTER]);

		if (txn_cond && txn_cond->with_assoc_info
		    && (txn->action == DBD_ADD_ASSOCS
			|| txn->action == DBD_MODIFY_ASSOCS
			|| txn->action == DBD_REMOVE_ASSOCS)) {
			MYSQL_RES *result2 = NULL;
			MYSQL_ROW row2;
			if (txn->clusters) {
				query = xstrdup_printf(
					"select "
					"group_concat(distinct user "
					"order by user), "
					"group_concat(distinct acct "
					"order by acct) "
					"from \"%s_%s\" where %s",
					txn->clusters, assoc_table,
					row[TXN_REQ_NAME]);
				debug4("%d(%s:%d) query\n%s", mysql_conn->conn,
				       THIS_FILE, __LINE__, query);
				if (!(result2 = mysql_db_query_ret(
					      mysql_conn, query, 0))) {
					xfree(query);
					continue;
				}
				xfree(query);

				if ((row2 = mysql_fetch_row(result2))) {
					if (row2[0] && row2[0][0])
						txn->users = xstrdup(row2[0]);
					if (row2[1] && row2[1][0])
						txn->accts = xstrdup(row2[1]);
				}
				mysql_free_result(result2);
			} else {
				error("We can't handle associations "
				      "from action %s yet.",
				      slurmdbd_msg_type_2_str(txn->action, 1));
			}
		}
	}
	mysql_free_result(result);

end_it:
	if (locked)
		slurm_mutex_unlock(&as_mysql_cluster_list_lock);

	return txn_list;
}
コード例 #24
0
ファイル: jobcomp_mysql.c プロジェクト: VURM/slurm
extern int slurm_jobcomp_log_record(struct job_record *job_ptr)
{
	int rc = SLURM_SUCCESS;
	char *usr_str = NULL, *grp_str = NULL, lim_str[32];
	char *connect_type = NULL, *reboot = NULL, *rotate = NULL,
		*geometry = NULL, *start = NULL,
		*blockid = NULL;
	enum job_states job_state;
	char *query = NULL;
	uint32_t time_limit, start_time, end_time;

	if(!jobcomp_mysql_conn || mysql_db_ping(jobcomp_mysql_conn) != 0) {
		char *loc = slurm_get_jobcomp_loc();
		if(slurm_jobcomp_set_location(loc) == SLURM_ERROR) {
			xfree(loc);
			return SLURM_ERROR;
		}
		xfree(loc);
	}

	usr_str = _get_user_name(job_ptr->user_id);
	grp_str = _get_group_name(job_ptr->group_id);

	if ((job_ptr->time_limit == NO_VAL) && job_ptr->part_ptr)
		time_limit = job_ptr->part_ptr->max_time;
	else
		time_limit = job_ptr->time_limit;
	if (time_limit == INFINITE)
		strcpy(lim_str, "UNLIMITED");
	else {
		snprintf(lim_str, sizeof(lim_str), "%lu",
			 (unsigned long) time_limit);
	}

	/* Job will typically be COMPLETING when this is called.
	 * We remove the flags to get the eventual completion state:
	 * JOB_FAILED, JOB_TIMEOUT, etc. */
	if (IS_JOB_RESIZING(job_ptr)) {
		job_state = JOB_RESIZING;
		if (job_ptr->resize_time)
			start_time = job_ptr->resize_time;
		else
			start_time = job_ptr->start_time;
		end_time = time(NULL);
	} else {
		job_state = job_ptr->job_state & JOB_STATE_BASE;
		if (job_ptr->resize_time)
			start_time = job_ptr->resize_time;
		else if (job_ptr->start_time > job_ptr->end_time) {
			/* Job cancelled while pending and
			 * expected start time is in the future. */
			start_time = 0;
		} else
			start_time = job_ptr->start_time;
		end_time = job_ptr->end_time;
	}

	connect_type = select_g_select_jobinfo_xstrdup(job_ptr->select_jobinfo,
						       SELECT_PRINT_CONNECTION);
	reboot = select_g_select_jobinfo_xstrdup(job_ptr->select_jobinfo,
						 SELECT_PRINT_REBOOT);
	rotate = select_g_select_jobinfo_xstrdup(job_ptr->select_jobinfo,
						 SELECT_PRINT_ROTATE);
	geometry = select_g_select_jobinfo_xstrdup(job_ptr->select_jobinfo,
						   SELECT_PRINT_GEOMETRY);
	start = select_g_select_jobinfo_xstrdup(job_ptr->select_jobinfo,
						SELECT_PRINT_START);
#ifdef HAVE_BG
	blockid = select_g_select_jobinfo_xstrdup(job_ptr->select_jobinfo,
						  SELECT_PRINT_BG_ID);
#else
	blockid = select_g_select_jobinfo_xstrdup(job_ptr->select_jobinfo,
						  SELECT_PRINT_RESV_ID);
#endif
	query = xstrdup_printf(
		"insert into %s (jobid, uid, user_name, gid, group_name, "
		"name, state, proc_cnt, partition, timelimit, "
		"starttime, endtime, nodecnt",
		jobcomp_table);

	if(job_ptr->nodes)
		xstrcat(query, ", nodelist");
	if(connect_type)
		xstrcat(query, ", connect_type");
	if(reboot)
		xstrcat(query, ", reboot");
	if(rotate)
		xstrcat(query, ", rotate");
	if(job_ptr->details && (job_ptr->details->max_cpus != NO_VAL))
		xstrcat(query, ", maxprocs");
	if(geometry)
		xstrcat(query, ", geometry");
	if(start)
		xstrcat(query, ", start");
	if(blockid)
		xstrcat(query, ", blockid");
	xstrfmtcat(query, ") values (%u, %u, '%s', %u, '%s', \"%s\", %d, %u, "
		   "'%s', \"%s\", %u, %u, %u",
		   job_ptr->job_id, job_ptr->user_id, usr_str,
		   job_ptr->group_id, grp_str, job_ptr->name,
		   job_state, job_ptr->total_cpus, job_ptr->partition, lim_str,
		   start_time, end_time, job_ptr->node_cnt);

	if(job_ptr->nodes)
		xstrfmtcat(query, ", '%s'", job_ptr->nodes);

	if(connect_type) {
		xstrfmtcat(query, ", '%s'", connect_type);
		xfree(connect_type);
	}
	if(reboot) {
		xstrfmtcat(query, ", '%s'", reboot);
		xfree(reboot);
	}
	if(rotate) {
		xstrfmtcat(query, ", '%s'", rotate);
		xfree(rotate);
	}
	if(job_ptr->details && (job_ptr->details->max_cpus != NO_VAL))
		xstrfmtcat(query, ", '%u'", job_ptr->details->max_cpus);

	if(geometry) {
		xstrfmtcat(query, ", '%s'", geometry);
		xfree(geometry);
	}
	if(start) {
		xstrfmtcat(query, ", '%s'", start);
		xfree(start);
	}
	if(blockid) {
		xstrfmtcat(query, ", '%s'", blockid);
		xfree(blockid);
	}
	xstrcat(query, ")");
	//info("query = %s", query);
	rc = mysql_db_query(jobcomp_mysql_conn, query);
	xfree(usr_str);
	xfree(grp_str);

	return rc;
}
コード例 #25
0
ファイル: as_mysql_user.c プロジェクト: BYUHPC/slurm
extern int as_mysql_add_coord(mysql_conn_t *mysql_conn, uint32_t uid,
			      List acct_list, slurmdb_user_cond_t *user_cond)
{
	char *query = NULL, *user = NULL, *acct = NULL;
	char *user_name = NULL, *txn_query = NULL;
	ListIterator itr, itr2;
	time_t now = time(NULL);
	int rc = SLURM_SUCCESS;
	slurmdb_user_rec_t *user_rec = NULL;

	if (!user_cond || !user_cond->assoc_cond
	    || !user_cond->assoc_cond->user_list
	    || !list_count(user_cond->assoc_cond->user_list)
	    || !acct_list || !list_count(acct_list)) {
		error("we need something to add");
		return SLURM_ERROR;
	}

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return ESLURM_DB_CONNECTION;

	user_name = uid_to_string((uid_t) uid);
	itr = list_iterator_create(user_cond->assoc_cond->user_list);
	itr2 = list_iterator_create(acct_list);
	while ((user = list_next(itr))) {
		if (!user[0])
			continue;
		while ((acct = list_next(itr2))) {
			if (!acct[0])
				continue;
			if (query)
				xstrfmtcat(query, ", (%ld, %ld, '%s', '%s')",
					   (long)now, (long)now, acct, user);
			else
				query = xstrdup_printf(
					"insert into %s (creation_time, "
					"mod_time, acct, user) values "
					"(%ld, %ld, '%s', '%s')",
					acct_coord_table,
					(long)now, (long)now, acct, user);

			if (txn_query)
				xstrfmtcat(txn_query,
					   ", (%ld, %u, '%s', '%s', '%s')",
					   (long)now, DBD_ADD_ACCOUNT_COORDS,
					   user, user_name, acct);
			else
				xstrfmtcat(txn_query,
					   "insert into %s "
					   "(timestamp, action, name, "
					   "actor, info) "
					   "values (%ld, %u, '%s', "
					   "'%s', '%s')",
					   txn_table,
					   (long)now, DBD_ADD_ACCOUNT_COORDS,
					   user,
					   user_name, acct);
		}
		list_iterator_reset(itr2);
	}
	xfree(user_name);
	list_iterator_destroy(itr);
	list_iterator_destroy(itr2);

	if (query) {
		xstrfmtcat(query,
			   " on duplicate key update mod_time=%ld, "
			   "deleted=0;%s",
			   (long)now, txn_query);
		debug3("%d(%s:%d) query\n%s",
		       mysql_conn->conn, THIS_FILE, __LINE__, query);
		rc = mysql_db_query(mysql_conn, query);
		xfree(query);
		xfree(txn_query);

		if (rc != SLURM_SUCCESS) {
			error("Couldn't add cluster hour rollup");
			return rc;
		}
		/* get the update list set */
		itr = list_iterator_create(user_cond->assoc_cond->user_list);
		while ((user = list_next(itr))) {
			user_rec = xmalloc(sizeof(slurmdb_user_rec_t));
			user_rec->name = xstrdup(user);
			_get_user_coords(mysql_conn, user_rec);
			if (addto_update_list(mysql_conn->update_list,
					      SLURMDB_ADD_COORD, user_rec)
			    != SLURM_SUCCESS)
				slurmdb_destroy_user_rec(user_rec);
		}
		list_iterator_destroy(itr);
	}

	return SLURM_SUCCESS;
}
コード例 #26
0
static int _process_cluster_usage(mysql_conn_t *mysql_conn,
				  char *cluster_name,
				  time_t curr_start, time_t curr_end,
				  time_t now, local_cluster_usage_t *c_usage)
{
	int rc = SLURM_SUCCESS;
	char *query = NULL;
	uint64_t total_used;
	char start_char[20], end_char[20];

	if (!c_usage)
		return rc;
	/* Now put the lists into the usage tables */

	/* sanity check to make sure we don't have more
	   allocated cpus than possible. */
	if (c_usage->total_time < c_usage->a_cpu) {
		slurm_make_time_str(&curr_start, start_char,
				    sizeof(start_char));
		slurm_make_time_str(&curr_end, end_char,
				    sizeof(end_char));
		error("We have more allocated time than is "
		      "possible (%"PRIu64" > %"PRIu64") for "
		      "cluster %s(%d) from %s - %s",
		      c_usage->a_cpu, c_usage->total_time,
		      cluster_name, c_usage->cpu_count,
		      start_char, end_char);
		c_usage->a_cpu = c_usage->total_time;
	}

	total_used = c_usage->a_cpu + c_usage->d_cpu + c_usage->pd_cpu;

	/* Make sure the total time we care about
	   doesn't go over the limit */
	if (c_usage->total_time < total_used) {
		int64_t overtime;

		slurm_make_time_str(&curr_start, start_char,
				    sizeof(start_char));
		slurm_make_time_str(&curr_end, end_char,
				    sizeof(end_char));
		error("We have more time than is "
		      "possible (%"PRIu64"+%"PRIu64"+%"
		      PRIu64")(%"PRIu64") > %"PRIu64" for "
		      "cluster %s(%d) from %s - %s",
		      c_usage->a_cpu, c_usage->d_cpu,
		      c_usage->pd_cpu, total_used,
		      c_usage->total_time,
		      cluster_name, c_usage->cpu_count,
		      start_char, end_char);

		/* First figure out how much actual down time
		   we have and then how much
		   planned down time we have. */
		overtime = (int64_t)(c_usage->total_time -
				     (c_usage->a_cpu + c_usage->d_cpu));
		if (overtime < 0) {
			c_usage->d_cpu += overtime;
			if ((int64_t)c_usage->d_cpu < 0)
				c_usage->d_cpu = 0;
		}

		overtime = (int64_t)(c_usage->total_time -
				     (c_usage->a_cpu + c_usage->d_cpu
				      + c_usage->pd_cpu));
		if (overtime < 0) {
			c_usage->pd_cpu += overtime;
			if ((int64_t)c_usage->pd_cpu < 0)
				c_usage->pd_cpu = 0;
		}

		total_used = c_usage->a_cpu +
			c_usage->d_cpu + c_usage->pd_cpu;
	}
	/* info("Cluster %s now has (%"PRIu64"+%"PRIu64"+" */
	/*      "%"PRIu64")(%"PRIu64") ?= %"PRIu64"", */
	/*      cluster_name, */
	/*      c_usage->a_cpu, c_usage->d_cpu, */
	/*      c_usage->pd_cpu, total_used, */
	/*      c_usage->total_time); */

	c_usage->i_cpu = c_usage->total_time - total_used - c_usage->r_cpu;
	/* sanity check just to make sure we have a
	 * legitimate time after we calulated
	 * idle/reserved time put extra in the over
	 * commit field
	 */
	/* info("%s got idle of %lld", c_usage->name, */
	/*      (int64_t)c_usage->i_cpu); */
	if ((int64_t)c_usage->i_cpu < 0) {
		/* info("got %d %d %d", c_usage->r_cpu, */
		/*      c_usage->i_cpu, c_usage->o_cpu); */
		c_usage->r_cpu += (int64_t)c_usage->i_cpu;
		c_usage->o_cpu -= (int64_t)c_usage->i_cpu;
		c_usage->i_cpu = 0;
		if ((int64_t)c_usage->r_cpu < 0)
			c_usage->r_cpu = 0;
	}

	/* info("cluster %s(%u) down %"PRIu64" alloc %"PRIu64" " */
	/*      "resv %"PRIu64" idle %"PRIu64" over %"PRIu64" " */
	/*      "total= %"PRIu64" ?= %"PRIu64" from %s", */
	/*      cluster_name, */
	/*      c_usage->cpu_count, c_usage->d_cpu, c_usage->a_cpu, */
	/*      c_usage->r_cpu, c_usage->i_cpu, c_usage->o_cpu, */
	/*      c_usage->d_cpu + c_usage->a_cpu + */
	/*      c_usage->r_cpu + c_usage->i_cpu, */
	/*      c_usage->total_time, */
	/*      slurm_ctime(&c_usage->start)); */
	/* info("to %s", slurm_ctime(&c_usage->end)); */
	query = xstrdup_printf("insert into \"%s_%s\" "
			       "(creation_time, "
			       "mod_time, time_start, "
			       "cpu_count, alloc_cpu_secs, "
			       "down_cpu_secs, pdown_cpu_secs, "
			       "idle_cpu_secs, over_cpu_secs, "
			       "resv_cpu_secs, consumed_energy) "
			       "values (%ld, %ld, %ld, %d, "
			       "%"PRIu64", %"PRIu64", %"PRIu64", "
			       "%"PRIu64", %"PRIu64", %"PRIu64", "
			       "%"PRIu64")",
			       cluster_name, cluster_hour_table,
			       now, now,
			       c_usage->start,
			       c_usage->cpu_count,
			       c_usage->a_cpu, c_usage->d_cpu,
			       c_usage->pd_cpu, c_usage->i_cpu,
			       c_usage->o_cpu, c_usage->r_cpu,
			       c_usage->energy);

	/* Spacing out the inserts here instead of doing them
	   all at once in the end proves to be faster.  Just FYI
	   so we don't go testing again and again.
	*/
	if (query) {
		xstrfmtcat(query,
			   " on duplicate key update "
			   "mod_time=%ld, cpu_count=VALUES(cpu_count), "
			   "alloc_cpu_secs=VALUES(alloc_cpu_secs), "
			   "down_cpu_secs=VALUES(down_cpu_secs), "
			   "pdown_cpu_secs=VALUES(pdown_cpu_secs), "
			   "idle_cpu_secs=VALUES(idle_cpu_secs), "
			   "over_cpu_secs=VALUES(over_cpu_secs), "
			   "resv_cpu_secs=VALUES(resv_cpu_secs), "
			   "consumed_energy=VALUES(consumed_energy)",
			   now);
		if (debug_flags & DEBUG_FLAG_DB_USAGE)
			DB_DEBUG(mysql_conn->conn, "query\n%s", query);
		rc = mysql_db_query(mysql_conn, query);
		xfree(query);
		if (rc != SLURM_SUCCESS)
			error("Couldn't add cluster hour rollup");
	}

	return rc;
}
コード例 #27
0
ファイル: as_mysql_rollup.c プロジェクト: jsollom/slurm
extern int as_mysql_daily_rollup(mysql_conn_t *mysql_conn,
				 char *cluster_name,
				 time_t start, time_t end,
				 uint16_t archive_data)
{
	/* can't just add 86400 since daylight savings starts and ends every
	 * once in a while
	 */
	int rc = SLURM_SUCCESS;
	struct tm start_tm;
	time_t curr_start = start;
	time_t curr_end;
	time_t now = time(NULL);
	char *query = NULL;
	uint16_t track_wckey = slurm_get_track_wckey();

	if (!localtime_r(&curr_start, &start_tm)) {
		error("Couldn't get localtime from day start %ld", curr_start);
		return SLURM_ERROR;
	}
	start_tm.tm_sec = 0;
	start_tm.tm_min = 0;
	start_tm.tm_hour = 0;
	start_tm.tm_mday++;
	start_tm.tm_isdst = -1;
	curr_end = mktime(&start_tm);

	while (curr_start < end) {
		debug3("curr day is now %ld-%ld", curr_start, curr_end);
/* 		info("start %s", ctime(&curr_start)); */
/* 		info("end %s", ctime(&curr_end)); */
		query = xstrdup_printf(
			"insert into \"%s_%s\" (creation_time, mod_time, "
			"id_assoc, "
			"time_start, alloc_cpu_secs) select %ld, %ld, "
			"id_assoc, "
			"%ld, @ASUM:=SUM(alloc_cpu_secs) from \"%s_%s\" where "
			"(time_start < %ld && time_start >= %ld) "
			"group by id_assoc on duplicate key update "
			"mod_time=%ld, alloc_cpu_secs=@ASUM;",
			cluster_name, assoc_day_table, now, now, curr_start,
			cluster_name, assoc_hour_table,
			curr_end, curr_start, now);
		/* We group on deleted here so if there are no entries
		   we don't get an error, just nothing is returned.
		   Else we get a bunch of NULL's
		*/
		xstrfmtcat(query,
			   "insert into \"%s_%s\" (creation_time, "
			   "mod_time, time_start, cpu_count, "
			   "alloc_cpu_secs, down_cpu_secs, pdown_cpu_secs, "
			   "idle_cpu_secs, over_cpu_secs, resv_cpu_secs) "
			   "select %ld, %ld, "
			   "%ld, @CPU:=MAX(cpu_count), "
			   "@ASUM:=SUM(alloc_cpu_secs), "
			   "@DSUM:=SUM(down_cpu_secs), "
			   "@PDSUM:=SUM(pdown_cpu_secs), "
			   "@ISUM:=SUM(idle_cpu_secs), "
			   "@OSUM:=SUM(over_cpu_secs), "
			   "@RSUM:=SUM(resv_cpu_secs) from \"%s_%s\" where "
			   "(time_start < %ld && time_start >= %ld) "
			   "group by deleted "
			   "on duplicate key update "
			   "mod_time=%ld, cpu_count=@CPU, "
			   "alloc_cpu_secs=@ASUM, down_cpu_secs=@DSUM, "
			   "pdown_cpu_secs=@PDSUM, idle_cpu_secs=@ISUM, "
			   "over_cpu_secs=@OSUM, resv_cpu_secs=@RSUM;",
			   cluster_name, cluster_day_table,
			   now, now, curr_start,
			   cluster_name, cluster_hour_table,
			   curr_end, curr_start, now);
		if (track_wckey) {
			xstrfmtcat(query,
				   "insert into \"%s_%s\" (creation_time, "
				   "mod_time, id_wckey, time_start, "
				   "alloc_cpu_secs) select %ld, %ld, "
				   "id_wckey, %ld, @ASUM:=SUM(alloc_cpu_secs) "
				   "from \"%s_%s\" where (time_start < %ld && "
				   "time_start >= %ld) "
				   "group by id_wckey on duplicate key update "
				   "mod_time=%ld, alloc_cpu_secs=@ASUM;",
				   cluster_name, wckey_day_table,
				   now, now, curr_start,
				   cluster_name, wckey_hour_table,
				   curr_end, curr_start, now);
		}
		debug3("%d(%s:%d) query\n%s",
		       mysql_conn->conn, THIS_FILE, __LINE__, query);
		rc = mysql_db_query(mysql_conn, query);
		xfree(query);
		if (rc != SLURM_SUCCESS) {
			error("Couldn't add day rollup");
			return SLURM_ERROR;
		}

		curr_start = curr_end;
		if (!localtime_r(&curr_start, &start_tm)) {
			error("Couldn't get localtime from day start %ld",
			      curr_start);
			return SLURM_ERROR;
		}
		start_tm.tm_sec = 0;
		start_tm.tm_min = 0;
		start_tm.tm_hour = 0;
		start_tm.tm_mday++;
		start_tm.tm_isdst = -1;
		curr_end = mktime(&start_tm);
	}

/* 	info("stop start %s", ctime(&curr_start)); */
/* 	info("stop end %s", ctime(&curr_end)); */

	/* go check to see if we archive and purge */
	rc = _process_purge(mysql_conn, cluster_name, archive_data,
			    SLURMDB_PURGE_DAYS);
	return rc;
}
コード例 #28
0
ファイル: as_mysql_user.c プロジェクト: BYUHPC/slurm
extern List as_mysql_remove_users(mysql_conn_t *mysql_conn, uint32_t uid,
				  slurmdb_user_cond_t *user_cond)
{
	ListIterator itr = NULL;
	List ret_list = NULL;
	List coord_list = NULL;
	int rc = SLURM_SUCCESS;
	char *object = NULL;
	char *extra = NULL, *query = NULL,
		*name_char = NULL, *assoc_char = NULL;
	time_t now = time(NULL);
	char *user_name = NULL;
	int set = 0;
	MYSQL_RES *result = NULL;
	MYSQL_ROW row;
	slurmdb_user_cond_t user_coord_cond;
	slurmdb_association_cond_t assoc_cond;
	slurmdb_wckey_cond_t wckey_cond;
	bool jobs_running = 0;

	if (!user_cond) {
		error("we need something to remove");
		return NULL;
	}

	if (check_connection(mysql_conn) != SLURM_SUCCESS)
		return NULL;

	if (user_cond->assoc_cond && user_cond->assoc_cond->user_list
	    && list_count(user_cond->assoc_cond->user_list)) {
		set = 0;
		xstrcat(extra, " && (");
		itr = list_iterator_create(user_cond->assoc_cond->user_list);
		while ((object = list_next(itr))) {
			if (!object[0])
				continue;
			if (set)
				xstrcat(extra, " || ");
			xstrfmtcat(extra, "name='%s'", object);
			set = 1;
		}
		list_iterator_destroy(itr);
		xstrcat(extra, ")");
	}

	ret_list = _get_other_user_names_to_mod(mysql_conn, uid, user_cond);

	if (user_cond->admin_level != SLURMDB_ADMIN_NOTSET) {
		xstrfmtcat(extra, " && admin_level=%u", user_cond->admin_level);
	}

	if (!extra && !ret_list) {
		error("Nothing to remove");
		return NULL;
	} else if (!extra) {
		/* means we got a ret_list and don't need to look at
		   the user_table. */
		goto no_user_table;
	}

	/* Only handle this if we need to actually query the
	   user_table.  If a request comes in stating they want to
	   remove all users with default account of whatever then that
	   doesn't deal with the user_table.
	*/
	query = xstrdup_printf("select name from %s where deleted=0 %s;",
			       user_table, extra);
	xfree(extra);
	if (!(result = mysql_db_query_ret(mysql_conn, query, 0))) {
		xfree(query);
		return NULL;
	}

	if (!ret_list)
		ret_list = list_create(slurm_destroy_char);
	while ((row = mysql_fetch_row(result)))
		slurm_addto_char_list(ret_list, row[0]);
	mysql_free_result(result);

no_user_table:

	if (!list_count(ret_list)) {
		errno = SLURM_NO_CHANGE_IN_DATA;
		debug3("didn't effect anything\n%s", query);
		xfree(query);
		return ret_list;
	}
	xfree(query);

	memset(&user_coord_cond, 0, sizeof(slurmdb_user_cond_t));
	memset(&assoc_cond, 0, sizeof(slurmdb_association_cond_t));
	/* we do not need to free the objects we put in here since
	   they are also placed in a list that will be freed
	*/
	assoc_cond.user_list = list_create(NULL);
	user_coord_cond.assoc_cond = &assoc_cond;

	itr = list_iterator_create(ret_list);
	while ((object = list_next(itr))) {
		slurmdb_user_rec_t *user_rec =
			xmalloc(sizeof(slurmdb_user_rec_t));
		list_append(assoc_cond.user_list, object);

		if (name_char) {
			xstrfmtcat(name_char, " || name='%s'", object);
			xstrfmtcat(assoc_char, " || t2.user='******'", object);
		} else {
			xstrfmtcat(name_char, "name='%s'", object);
			xstrfmtcat(assoc_char, "t2.user='******'", object);
		}

		user_rec->name = xstrdup(object);
		if (addto_update_list(mysql_conn->update_list,
				      SLURMDB_REMOVE_USER, user_rec)
		    != SLURM_SUCCESS)
			slurmdb_destroy_user_rec(user_rec);
	}
	list_iterator_destroy(itr);

	/* We need to remove these accounts from the coord's that have it */
	coord_list = as_mysql_remove_coord(
		mysql_conn, uid, NULL, &user_coord_cond);
	if (coord_list)
		list_destroy(coord_list);

	/* We need to remove these users from the wckey table */
	memset(&wckey_cond, 0, sizeof(slurmdb_wckey_cond_t));
	wckey_cond.user_list = assoc_cond.user_list;
	coord_list = as_mysql_remove_wckeys(mysql_conn, uid, &wckey_cond);
	if (coord_list)
		list_destroy(coord_list);

	list_destroy(assoc_cond.user_list);

	user_name = uid_to_string((uid_t) uid);
	slurm_mutex_lock(&as_mysql_cluster_list_lock);
	itr = list_iterator_create(as_mysql_cluster_list);
	while ((object = list_next(itr))) {
		if ((rc = remove_common(mysql_conn, DBD_REMOVE_USERS, now,
					user_name, user_table, name_char,
					assoc_char, object, ret_list,
					&jobs_running))
		    != SLURM_SUCCESS)
			break;
	}
	list_iterator_destroy(itr);
	slurm_mutex_unlock(&as_mysql_cluster_list_lock);

	xfree(user_name);
	xfree(name_char);
	if (rc == SLURM_ERROR) {
		list_destroy(ret_list);
		xfree(assoc_char);
		return NULL;
	}

	query = xstrdup_printf(
		"update %s as t2 set deleted=1, mod_time=%ld where %s",
		acct_coord_table, (long)now, assoc_char);
	xfree(assoc_char);

	rc = mysql_db_query(mysql_conn, query);
	xfree(query);
	if (rc != SLURM_SUCCESS) {
		error("Couldn't remove user coordinators");
		list_destroy(ret_list);
		return NULL;
	}

	if (jobs_running)
		errno = ESLURM_JOBS_RUNNING_ON_ASSOC;
	else
		errno = SLURM_SUCCESS;
	return ret_list;
}
コード例 #29
0
extern int as_mysql_hourly_rollup(mysql_conn_t *mysql_conn,
				  char *cluster_name,
				  time_t start, time_t end,
				  uint16_t archive_data)
{
	int rc = SLURM_SUCCESS;
	int add_sec = 3600;
	int i=0;
	time_t now = time(NULL);
	time_t curr_start = start;
	time_t curr_end = curr_start + add_sec;
	char *query = NULL;
	MYSQL_RES *result = NULL;
	MYSQL_ROW row;
	ListIterator a_itr = NULL;
	ListIterator c_itr = NULL;
	ListIterator w_itr = NULL;
	ListIterator r_itr = NULL;
	List assoc_usage_list = list_create(_destroy_local_id_usage);
	List cluster_down_list = list_create(_destroy_local_cluster_usage);
	List wckey_usage_list = list_create(_destroy_local_id_usage);
	List resv_usage_list = list_create(_destroy_local_resv_usage);
	uint16_t track_wckey = slurm_get_track_wckey();
	/* char start_char[20], end_char[20]; */

	char *job_req_inx[] = {
		"job.job_db_inx",
		"job.id_job",
		"job.id_assoc",
		"job.id_wckey",
		"job.array_task_pending",
		"job.time_eligible",
		"job.time_start",
		"job.time_end",
		"job.time_suspended",
		"job.cpus_alloc",
		"job.cpus_req",
		"job.id_resv",
		"SUM(step.consumed_energy)"
	};
	char *job_str = NULL;
	enum {
		JOB_REQ_DB_INX,
		JOB_REQ_JOBID,
		JOB_REQ_ASSOCID,
		JOB_REQ_WCKEYID,
		JOB_REQ_ARRAY_PENDING,
		JOB_REQ_ELG,
		JOB_REQ_START,
		JOB_REQ_END,
		JOB_REQ_SUSPENDED,
		JOB_REQ_ACPU,
		JOB_REQ_RCPU,
		JOB_REQ_RESVID,
		JOB_REQ_ENERGY,
		JOB_REQ_COUNT
	};

	char *suspend_req_inx[] = {
		"time_start",
		"time_end"
	};
	char *suspend_str = NULL;
	enum {
		SUSPEND_REQ_START,
		SUSPEND_REQ_END,
		SUSPEND_REQ_COUNT
	};

	char *resv_req_inx[] = {
		"id_resv",
		"assoclist",
		"cpus",
		"flags",
		"time_start",
		"time_end"
	};
	char *resv_str = NULL;
	enum {
		RESV_REQ_ID,
		RESV_REQ_ASSOCS,
		RESV_REQ_CPU,
		RESV_REQ_FLAGS,
		RESV_REQ_START,
		RESV_REQ_END,
		RESV_REQ_COUNT
	};

	i=0;
	xstrfmtcat(job_str, "%s", job_req_inx[i]);
	for(i=1; i<JOB_REQ_COUNT; i++) {
		xstrfmtcat(job_str, ", %s", job_req_inx[i]);
	}

	i=0;
	xstrfmtcat(suspend_str, "%s", suspend_req_inx[i]);
	for(i=1; i<SUSPEND_REQ_COUNT; i++) {
		xstrfmtcat(suspend_str, ", %s", suspend_req_inx[i]);
	}

	i=0;
	xstrfmtcat(resv_str, "%s", resv_req_inx[i]);
	for(i=1; i<RESV_REQ_COUNT; i++) {
		xstrfmtcat(resv_str, ", %s", resv_req_inx[i]);
	}

/* 	info("begin start %s", slurm_ctime(&curr_start)); */
/* 	info("begin end %s", slurm_ctime(&curr_end)); */
	a_itr = list_iterator_create(assoc_usage_list);
	c_itr = list_iterator_create(cluster_down_list);
	w_itr = list_iterator_create(wckey_usage_list);
	r_itr = list_iterator_create(resv_usage_list);
	while (curr_start < end) {
		int last_id = -1;
		int last_wckeyid = -1;
		int seconds = 0;
		int tot_time = 0;
		local_cluster_usage_t *loc_c_usage = NULL;
		local_cluster_usage_t *c_usage = NULL;
		local_resv_usage_t *r_usage = NULL;
		local_id_usage_t *a_usage = NULL;
		local_id_usage_t *w_usage = NULL;

		if (debug_flags & DEBUG_FLAG_DB_USAGE)
			DB_DEBUG(mysql_conn->conn,
				 "%s curr hour is now %ld-%ld",
				 cluster_name, curr_start, curr_end);
/* 		info("start %s", slurm_ctime(&curr_start)); */
/* 		info("end %s", slurm_ctime(&curr_end)); */

		c_usage = _setup_cluster_usage(mysql_conn, cluster_name,
					       curr_start, curr_end,
					       cluster_down_list);

		// now get the reservations during this time
		/* If a reservation has the IGNORE_JOBS flag we don't
		 * have an easy way to distinguish the cpus a job not
		 * running in the reservation, but on it's cpus.
		 * So we will just ignore these reservations for
		 * accounting purposes.
		 */
		query = xstrdup_printf("select %s from \"%s_%s\" where "
				       "(time_start < %ld && time_end >= %ld) "
				       "&& !(flags & %u)"
				       "order by time_start",
				       resv_str, cluster_name, resv_table,
				       curr_end, curr_start,
				       RESERVE_FLAG_IGN_JOBS);

		if (debug_flags & DEBUG_FLAG_DB_USAGE)
			DB_DEBUG(mysql_conn->conn, "query\n%s", query);
		if (!(result = mysql_db_query_ret(
			      mysql_conn, query, 0))) {
			xfree(query);
			_destroy_local_cluster_usage(c_usage);
			return SLURM_ERROR;
		}
		xfree(query);

		/* If a reservation overlaps another reservation we
		   total up everything here as if they didn't but when
		   calculating the total time for a cluster we will
		   remove the extra time received.  This may result in
		   unexpected results with association based reports
		   since the association is given the total amount of
		   time of each reservation, thus equaling more time
		   than is available.  Job/Cluster/Reservation reports
		   should be fine though since we really don't over
		   allocate resources.  The issue with us not being
		   able to handle overlapping reservations here is
		   unless the reservation completely overlaps the
		   other reservation we have no idea how many cpus
		   should be removed since this could be a
		   heterogeneous system.  This same problem exists
		   when a reservation is created with the ignore_jobs
		   option which will allow jobs to continue to run in the
		   reservation that aren't suppose to.
		*/
		while ((row = mysql_fetch_row(result))) {
			time_t row_start = slurm_atoul(row[RESV_REQ_START]);
			time_t row_end = slurm_atoul(row[RESV_REQ_END]);
			uint32_t row_cpu = slurm_atoul(row[RESV_REQ_CPU]);
			uint32_t row_flags = slurm_atoul(row[RESV_REQ_FLAGS]);

			if (row_start < curr_start)
				row_start = curr_start;

			if (!row_end || row_end > curr_end)
				row_end = curr_end;

			/* Don't worry about it if the time is less
			 * than 1 second.
			 */
			if ((row_end - row_start) < 1)
				continue;

			r_usage = xmalloc(sizeof(local_resv_usage_t));
			r_usage->id = slurm_atoul(row[RESV_REQ_ID]);

			r_usage->local_assocs = list_create(slurm_destroy_char);
			slurm_addto_char_list(r_usage->local_assocs,
					      row[RESV_REQ_ASSOCS]);

			r_usage->total_time = (row_end - row_start) * row_cpu;
			r_usage->start = row_start;
			r_usage->end = row_end;
			list_append(resv_usage_list, r_usage);

			/* Since this reservation was added to the
			   cluster and only certain people could run
			   there we will use this as allocated time on
			   the system.  If the reservation was a
			   maintenance then we add the time to planned
			   down time.
			*/


			/* only record time for the clusters that have
			   registered.  This continue should rarely if
			   ever happen.
			*/
			if (!c_usage)
				continue;
			else if (row_flags & RESERVE_FLAG_MAINT)
				c_usage->pd_cpu += r_usage->total_time;
			else
				c_usage->a_cpu += r_usage->total_time;
			/* slurm_make_time_str(&r_usage->start, start_char, */
			/* 		    sizeof(start_char)); */
			/* slurm_make_time_str(&r_usage->end, end_char, */
			/* 		    sizeof(end_char)); */
			/* info("adding this much %lld to cluster %s " */
			/*      "%d %d %s - %s", */
			/*      r_usage->total_time, c_usage->name, */
			/*      (row_flags & RESERVE_FLAG_MAINT),  */
			/*      r_usage->id, start_char, end_char); */
		}
		mysql_free_result(result);

		/* now get the jobs during this time only  */
		query = xstrdup_printf("select %s from \"%s_%s\" as job "
				       "left outer join \"%s_%s\" as step on "
				       "job.job_db_inx=step.job_db_inx "
				       "and (step.id_step>=0) "
				       "where (job.time_eligible < %ld && "
				       "(job.time_end >= %ld || "
				       "job.time_end = 0)) "
				       "group by job.job_db_inx "
				       "order by job.id_assoc, "
				       "job.time_eligible",
				       job_str, cluster_name, job_table,
				       cluster_name, step_table,
				       curr_end, curr_start);

		if (debug_flags & DEBUG_FLAG_DB_USAGE)
			DB_DEBUG(mysql_conn->conn, "query\n%s", query);
		if (!(result = mysql_db_query_ret(
			      mysql_conn, query, 0))) {
			xfree(query);
			_destroy_local_cluster_usage(c_usage);
			return SLURM_ERROR;
		}
		xfree(query);

		while ((row = mysql_fetch_row(result))) {
			uint32_t job_id = slurm_atoul(row[JOB_REQ_JOBID]);
			uint32_t assoc_id = slurm_atoul(row[JOB_REQ_ASSOCID]);
			uint32_t wckey_id = slurm_atoul(row[JOB_REQ_WCKEYID]);
			uint32_t array_pending =
				slurm_atoul(row[JOB_REQ_ARRAY_PENDING]);
			uint32_t resv_id = slurm_atoul(row[JOB_REQ_RESVID]);
			time_t row_eligible = slurm_atoul(row[JOB_REQ_ELG]);
			time_t row_start = slurm_atoul(row[JOB_REQ_START]);
			time_t row_end = slurm_atoul(row[JOB_REQ_END]);
			uint32_t row_acpu = slurm_atoul(row[JOB_REQ_ACPU]);
			uint32_t row_rcpu = slurm_atoul(row[JOB_REQ_RCPU]);
			uint64_t row_energy = 0;
			int loc_seconds = 0;
			seconds = 0;

			if (row[JOB_REQ_ENERGY])
				row_energy = slurm_atoull(row[JOB_REQ_ENERGY]);
			if (row_start && (row_start < curr_start))
				row_start = curr_start;

			if (!row_start && row_end)
				row_start = row_end;

			if (!row_end || row_end > curr_end)
				row_end = curr_end;

			if (!row_start || ((row_end - row_start) < 1))
				goto calc_cluster;

			seconds = (row_end - row_start);

			if (slurm_atoul(row[JOB_REQ_SUSPENDED])) {
				MYSQL_RES *result2 = NULL;
				MYSQL_ROW row2;
				/* get the suspended time for this job */
				query = xstrdup_printf(
					"select %s from \"%s_%s\" where "
					"(time_start < %ld && (time_end >= %ld "
					"|| time_end = 0)) && job_db_inx=%s "
					"order by time_start",
					suspend_str, cluster_name,
					suspend_table,
					curr_end, curr_start,
					row[JOB_REQ_DB_INX]);

				debug4("%d(%s:%d) query\n%s",
				       mysql_conn->conn, THIS_FILE,
				       __LINE__, query);
				if (!(result2 = mysql_db_query_ret(
					      mysql_conn,
					      query, 0))) {
					xfree(query);
					_destroy_local_cluster_usage(c_usage);
					return SLURM_ERROR;
				}
				xfree(query);
				while ((row2 = mysql_fetch_row(result2))) {
					time_t local_start = slurm_atoul(
						row2[SUSPEND_REQ_START]);
					time_t local_end = slurm_atoul(
						row2[SUSPEND_REQ_END]);

					if (!local_start)
						continue;

					if (row_start > local_start)
						local_start = row_start;
					if (row_end < local_end)
						local_end = row_end;
					tot_time = (local_end - local_start);
					if (tot_time < 1)
						continue;

					seconds -= tot_time;
				}
				mysql_free_result(result2);
			}
			if (seconds < 1) {
				debug4("This job (%u) was suspended "
				       "the entire hour", job_id);
				continue;
			}

			if (last_id != assoc_id) {
				a_usage = xmalloc(sizeof(local_id_usage_t));
				a_usage->id = assoc_id;
				list_append(assoc_usage_list, a_usage);
				last_id = assoc_id;
			}

			a_usage->a_cpu += seconds * row_acpu;
			a_usage->energy += row_energy;

			if (!track_wckey)
				goto calc_cluster;

			/* do the wckey calculation */
			if (last_wckeyid != wckey_id) {
				list_iterator_reset(w_itr);
				while ((w_usage = list_next(w_itr)))
					if (w_usage->id == wckey_id)
						break;

				if (!w_usage) {
					w_usage = xmalloc(
						sizeof(local_id_usage_t));
					w_usage->id = wckey_id;
					list_append(wckey_usage_list,
						    w_usage);
				}

				last_wckeyid = wckey_id;
			}
			w_usage->a_cpu += seconds * row_acpu;
			w_usage->energy += row_energy;
			/* do the cluster allocated calculation */
		calc_cluster:

			/* Now figure out there was a disconnected
			   slurmctld durning this job.
			*/
			list_iterator_reset(c_itr);
			while ((loc_c_usage = list_next(c_itr))) {
				int temp_end = row_end;
				int temp_start = row_start;
				if (loc_c_usage->start > temp_start)
					temp_start = loc_c_usage->start;
				if (loc_c_usage->end < temp_end)
					temp_end = loc_c_usage->end;
				loc_seconds = (temp_end - temp_start);
				if (loc_seconds < 1)
					continue;

				loc_seconds *= row_acpu;
				/* info(" Job %u was running for " */
				/*      "%d seconds while " */
				/*      "cluster %s's slurmctld " */
				/*      "wasn't responding", */
				/*      job_id, loc_seconds, cluster_name); */
				if (loc_seconds >= loc_c_usage->total_time)
					loc_c_usage->total_time = 0;
				else {
					loc_c_usage->total_time -=
						loc_seconds * row_acpu;
				}
			}

			/* first figure out the reservation */
			if (resv_id) {
				if (seconds <= 0)
					continue;
				/* Since we have already added the
				   entire reservation as used time on
				   the cluster we only need to
				   calculate the used time for the
				   reservation and then divy up the
				   unused time over the associations
				   able to run in the reservation.
				   Since the job was to run, or ran a
				   reservation we don't care about
				   eligible time since that could
				   totally skew the clusters reserved time
				   since the job may be able to run
				   outside of the reservation. */
				list_iterator_reset(r_itr);
				while ((r_usage = list_next(r_itr))) {
					/* since the reservation could
					   have changed in some way,
					   thus making a new
					   reservation record in the
					   database, we have to make
					   sure all the reservations
					   are checked to see if such
					   a thing has happened */
					if (r_usage->id == resv_id) {
						int temp_end = row_end;
						int temp_start = row_start;
						if (r_usage->start > temp_start)
							temp_start =
								r_usage->start;
						if (r_usage->end < temp_end)
							temp_end = r_usage->end;

						if ((temp_end - temp_start)
						    > 0) {
							r_usage->a_cpu +=
								(temp_end
								 - temp_start)
								* row_acpu;
						}
					}
				}
				continue;
			}

			/* only record time for the clusters that have
			   registered.  This continue should rarely if
			   ever happen.
			*/
			if (!c_usage)
				continue;

			if (row_start && (seconds > 0)) {
				/* info("%d assoc %d adds " */
				/*      "(%d)(%d-%d) * %d = %d " */
				/*      "to %d", */
				/*      job_id, */
				/*      a_usage->id, */
				/*      seconds, */
				/*      row_end, row_start, */
				/*      row_acpu, */
				/*      seconds * row_acpu, */
				/*      row_acpu); */

				c_usage->a_cpu += seconds * row_acpu;
				c_usage->energy += row_energy;
			}

			/* now reserved time */
			if (!row_start || (row_start >= c_usage->start)) {
				int temp_end = row_start;
				int temp_start = row_eligible;
				if (c_usage->start > temp_start)
					temp_start = c_usage->start;
				if (c_usage->end < temp_end)
					temp_end = c_usage->end;
				loc_seconds = (temp_end - temp_start);
				if (loc_seconds > 0) {
					/* If we have pending jobs in
					   an array they haven't been
					   inserted into the database
					   yet as proper job records,
					   so handle them here.
					*/
					if (array_pending)
						loc_seconds *= array_pending;

					/* info("%d assoc %d reserved " */
					/*      "(%d)(%d-%d) * %d * %d = %d " */
					/*      "to %d", */
					/*      job_id, */
					/*      assoc_id, */
					/*      temp_end - temp_start, */
					/*      temp_end, temp_start, */
					/*      row_rcpu, */
					/*      array_pending, */
					/*      loc_seconds, */
					/*      row_rcpu); */

					c_usage->r_cpu +=
						loc_seconds * row_rcpu;
				}
			}
		}
		mysql_free_result(result);

		/* now figure out how much more to add to the
		   associations that could had run in the reservation
		*/
		list_iterator_reset(r_itr);
		while ((r_usage = list_next(r_itr))) {
			int64_t idle = r_usage->total_time - r_usage->a_cpu;
			char *assoc = NULL;
			ListIterator tmp_itr = NULL;

			if (idle <= 0)
				continue;

			/* now divide that time by the number of
			   associations in the reservation and add
			   them to each association */
			seconds = idle / list_count(r_usage->local_assocs);
/* 			info("resv %d got %d for seconds for %d assocs", */
/* 			     r_usage->id, seconds, */
/* 			     list_count(r_usage->local_assocs)); */
			tmp_itr = list_iterator_create(r_usage->local_assocs);
			while ((assoc = list_next(tmp_itr))) {
				uint32_t associd = slurm_atoul(assoc);
				if (last_id != associd) {
					list_iterator_reset(a_itr);
					while ((a_usage = list_next(a_itr))) {
						if (a_usage->id == associd) {
							last_id = a_usage->id;
							break;
						}
					}
				}

				if (!a_usage) {
					a_usage = xmalloc(
						sizeof(local_id_usage_t));
					a_usage->id = associd;
					list_append(assoc_usage_list, a_usage);
					last_id = associd;
				}

				a_usage->a_cpu += seconds;
			}
			list_iterator_destroy(tmp_itr);
		}

		/* now apply the down time from the slurmctld disconnects */
		if (c_usage) {
			list_iterator_reset(c_itr);
			while ((loc_c_usage = list_next(c_itr)))
				c_usage->d_cpu += loc_c_usage->total_time;

			if ((rc = _process_cluster_usage(
				     mysql_conn, cluster_name, curr_start,
				     curr_end, now, c_usage))
			    != SLURM_SUCCESS) {
				_destroy_local_cluster_usage(c_usage);
				goto end_it;
			}
		}

		list_iterator_reset(a_itr);
		while ((a_usage = list_next(a_itr))) {
/* 			info("association (%d) %d alloc %d", */
/* 			     a_usage->id, last_id, */
/* 			     a_usage->a_cpu); */
			if (query) {
				xstrfmtcat(query,
					   ", (%ld, %ld, %d, %ld, %"PRIu64", "
					   "%"PRIu64")",
					   now, now,
					   a_usage->id, curr_start,
					   a_usage->a_cpu, a_usage->energy);
			} else {
				xstrfmtcat(query,
					   "insert into \"%s_%s\" "
					   "(creation_time, "
					   "mod_time, id_assoc, time_start, "
					   "alloc_cpu_secs, consumed_energy) "
					   "values "
					   "(%ld, %ld, %d, %ld, %"PRIu64", "
					   "%"PRIu64")",
					   cluster_name, assoc_hour_table,
					   now, now,
					   a_usage->id, curr_start,
					   a_usage->a_cpu, a_usage->energy);
			}
		}
		if (query) {
			xstrfmtcat(query,
				   " on duplicate key update "
				   "mod_time=%ld, "
				   "alloc_cpu_secs=VALUES(alloc_cpu_secs), "
				   "consumed_energy=VALUES(consumed_energy);",
				   now);

			if (debug_flags & DEBUG_FLAG_DB_USAGE)
				DB_DEBUG(mysql_conn->conn, "query\n%s", query);
			rc = mysql_db_query(mysql_conn, query);
			xfree(query);
			if (rc != SLURM_SUCCESS) {
				error("Couldn't add assoc hour rollup");
				_destroy_local_cluster_usage(c_usage);
				goto end_it;
			}
		}

		if (!track_wckey)
			goto end_loop;

		list_iterator_reset(w_itr);
		while ((w_usage = list_next(w_itr))) {
/* 			info("association (%d) %d alloc %d", */
/* 			     w_usage->id, last_id, */
/* 			     w_usage->a_cpu); */
			if (query) {
				xstrfmtcat(query,
					   ", (%ld, %ld, %d, %ld, "
					   "%"PRIu64", %"PRIu64")",
					   now, now,
					   w_usage->id, curr_start,
					   w_usage->a_cpu, w_usage->energy);
			} else {
				xstrfmtcat(query,
					   "insert into \"%s_%s\" "
					   "(creation_time, "
					   "mod_time, id_wckey, time_start, "
					   "alloc_cpu_secs, consumed_energy) "
					   "values "
					   "(%ld, %ld, %d, %ld, "
					   "%"PRIu64", %"PRIu64")",
					   cluster_name, wckey_hour_table,
					   now, now,
					   w_usage->id, curr_start,
					   w_usage->a_cpu, w_usage->energy);
			}
		}
		if (query) {
			xstrfmtcat(query,
				   " on duplicate key update "
				   "mod_time=%ld, "
				   "alloc_cpu_secs=VALUES(alloc_cpu_secs), "
				   "consumed_energy=VALUES(consumed_energy);",
				   now);

			if (debug_flags & DEBUG_FLAG_DB_USAGE)
				DB_DEBUG(mysql_conn->conn, "query\n%s", query);
			rc = mysql_db_query(mysql_conn, query);
			xfree(query);
			if (rc != SLURM_SUCCESS) {
				error("Couldn't add wckey hour rollup");
				_destroy_local_cluster_usage(c_usage);
				goto end_it;
			}
		}

	end_loop:
		_destroy_local_cluster_usage(c_usage);
		list_flush(assoc_usage_list);
		list_flush(cluster_down_list);
		list_flush(wckey_usage_list);
		list_flush(resv_usage_list);
		curr_start = curr_end;
		curr_end = curr_start + add_sec;
	}
end_it:
	xfree(suspend_str);
	xfree(job_str);
	xfree(resv_str);
	list_iterator_destroy(a_itr);
	list_iterator_destroy(c_itr);
	list_iterator_destroy(w_itr);
	list_iterator_destroy(r_itr);

	list_destroy(assoc_usage_list);
	list_destroy(cluster_down_list);
	list_destroy(wckey_usage_list);
	list_destroy(resv_usage_list);

/* 	info("stop start %s", slurm_ctime(&curr_start)); */
/* 	info("stop end %s", slurm_ctime(&curr_end)); */

	/* go check to see if we archive and purge */

	if (rc == SLURM_SUCCESS)
		rc = _process_purge(mysql_conn, cluster_name, archive_data,
				    SLURMDB_PURGE_HOURS);

	return rc;
}
コード例 #30
0
ファイル: as_mysql_resv.c プロジェクト: RSE-Cambridge/slurm
extern int as_mysql_modify_resv(mysql_conn_t *mysql_conn,
				slurmdb_reservation_rec_t *resv)
{
	MYSQL_RES *result = NULL;
	MYSQL_ROW row;
	int rc = SLURM_SUCCESS;
	char *cols = NULL, *vals = NULL, *extra = NULL,
		*query = NULL;
	time_t start = 0, now = time(NULL);
	int i;
	int set = 0;

	char *resv_req_inx[] = {
		"assoclist",
		"time_start",
		"time_end",
		"resv_name",
		"nodelist",
		"node_inx",
		"flags",
		"tres"
	};
	enum {
		RESV_ASSOCS,
		RESV_START,
		RESV_END,
		RESV_NAME,
		RESV_NODES,
		RESV_NODE_INX,
		RESV_FLAGS,
		RESV_TRES,
		RESV_COUNT
	};

	if (!resv) {
		error("No reservation was given to edit");
		return SLURM_ERROR;
	}

	if (!resv->id) {
		error("We need an id to edit a reservation.");
		return SLURM_ERROR;
	}
	if (!resv->time_start) {
		error("We need a start time to edit a reservation.");
		return SLURM_ERROR;
	}
	if (!resv->cluster || !resv->cluster[0]) {
		error("We need a cluster name to edit a reservation.");
		return SLURM_ERROR;
	}

	if (!resv->time_start_prev) {
		error("We need a time to check for last "
		      "start of reservation.");
		return SLURM_ERROR;
	}

	xstrfmtcat(cols, "%s", resv_req_inx[0]);
	for (i=1; i<RESV_COUNT; i++) {
		xstrfmtcat(cols, ", %s", resv_req_inx[i]);
	}

	/* check for both the last start and the start because most
	   likely the start time hasn't changed, but something else
	   may have since the last time we did an update to the
	   reservation. */
	query = xstrdup_printf("select %s from \"%s_%s\" where id_resv=%u "
			       "and (time_start=%ld || time_start=%ld) "
			       "and deleted=0 order by time_start desc "
			       "limit 1 FOR UPDATE;",
			       cols, resv->cluster, resv_table, resv->id,
			       resv->time_start, resv->time_start_prev);
try_again:
	debug4("%d(%s:%d) query\n%s",
	       mysql_conn->conn, THIS_FILE, __LINE__, query);
	if (!(result = mysql_db_query_ret(
		      mysql_conn, query, 0))) {
		rc = SLURM_ERROR;
		goto end_it;
	}
	if (!(row = mysql_fetch_row(result))) {
		rc = SLURM_ERROR;
		mysql_free_result(result);
		error("There is no reservation by id %u, "
		      "time_start %ld, and cluster '%s'", resv->id,
		      resv->time_start_prev, resv->cluster);
		if (!set && resv->time_end) {
			/* This should never really happen,
			   but just incase the controller and the
			   database get out of sync we check
			   to see if there is a reservation
			   not deleted that hasn't ended yet. */
			xfree(query);
			query = xstrdup_printf(
				"select %s from \"%s_%s\" where id_resv=%u "
				"and time_start <= %ld and deleted=0 "
				"order by time_start desc "
				"limit 1;",
				cols, resv->cluster, resv_table, resv->id,
				resv->time_end);
			set = 1;
			goto try_again;
		}
		goto end_it;
	}

	start = slurm_atoul(row[RESV_START]);

	xfree(query);
	xfree(cols);

	set = 0;

	/* check differences here */

	if (!resv->name
	    && row[RESV_NAME] && row[RESV_NAME][0])
		// if this changes we just update the
		// record, no need to create a new one since
		// this doesn't really effect the
		// reservation accounting wise
		resv->name = xstrdup(row[RESV_NAME]);

	if (resv->assocs)
		set = 1;
	else if (row[RESV_ASSOCS] && row[RESV_ASSOCS][0])
		resv->assocs = xstrdup(row[RESV_ASSOCS]);

	if (resv->flags != NO_VAL)
		set = 1;
	else
		resv->flags = slurm_atoul(row[RESV_FLAGS]);

	if (resv->nodes)
		set = 1;
	else if (row[RESV_NODES] && row[RESV_NODES][0]) {
		resv->nodes = xstrdup(row[RESV_NODES]);
		resv->node_inx = xstrdup(row[RESV_NODE_INX]);
	}

	if (!resv->time_end)
		resv->time_end = slurm_atoul(row[RESV_END]);

	if (resv->tres_str)
		set = 1;
	else if (row[RESV_TRES] && row[RESV_TRES][0])
		resv->tres_str = xstrdup(row[RESV_TRES]);

	mysql_free_result(result);

	_setup_resv_limits(resv, &cols, &vals, &extra);
	/* use start below instead of resv->time_start_prev
	 * just incase we have a different one from being out
	 * of sync
	 */
	if ((start > now) || !set) {
		/* we haven't started the reservation yet, or
		   we are changing the associations or end
		   time which we can just update it */
		query = xstrdup_printf("update \"%s_%s\" set deleted=0%s "
				       "where deleted=0 and id_resv=%u "
				       "and time_start=%ld;",
				       resv->cluster, resv_table,
				       extra, resv->id, start);
	} else {
		/* time_start is already done above and we
		 * changed something that is in need on a new
		 * entry. */
		query = xstrdup_printf("update \"%s_%s\" set time_end=%ld "
				       "where deleted=0 && id_resv=%u "
				       "and time_start=%ld;",
				       resv->cluster, resv_table,
				       resv->time_start-1,
				       resv->id, start);
		xstrfmtcat(query,
			   "insert into \"%s_%s\" (id_resv%s) "
			   "values (%u%s) "
			   "on duplicate key update deleted=0%s;",
			   resv->cluster, resv_table, cols, resv->id,
			   vals, extra);
	}

	if (debug_flags & DEBUG_FLAG_DB_RESV)
		DB_DEBUG(mysql_conn->conn, "query\n%s", query);

	rc = mysql_db_query(mysql_conn, query);

end_it:

	xfree(query);
	xfree(cols);
	xfree(vals);
	xfree(extra);

	return rc;
}