示例#1
0
/* Check if the logical name is not already registered */
static int check_logical_name(DC_Workunit *wu, const char *logicalFileName)
{
	GList *l;

	if (strchr(logicalFileName, '/') || strchr(logicalFileName, '\\'))
	{
		DC_log(LOG_ERR, "Illegal characters in logical file name %s",
			logicalFileName);
		return DC_ERR_BADPARAM;
	}
	for (l = wu->input_files; l; l = l->next)
	{
		DC_PhysicalFile *file = (DC_PhysicalFile *)l->data;

		if (!strcmp(file->label, logicalFileName))
		{
			DC_log(LOG_ERR, "File %s is already registered as an "
				"input file", logicalFileName);
			return DC_ERR_BADPARAM;
		}
	}
	for (l = wu->output_files; l; l = l->next)
	{
		if (!strcmp((char *)l->data, logicalFileName))
		{
			DC_log(LOG_ERR, "File %s is already registered as an "
				"output file", logicalFileName);
			return DC_ERR_BADPARAM;
		}
	}
	return 0;
}
示例#2
0
static DC_ClientEvent *handle_special_msg(const char *message)
{
	if (!strncmp(message, DC_MSG_CANCEL, strlen(DC_MSG_CANCEL)) &&
			message[strlen(DC_MSG_CANCEL)] == ':')
	{
		if (strcmp(message + strlen(DC_MSG_CANCEL) + 1, wu_name))
		{
			DC_log(LOG_WARNING, "Received CANCEL message for "
				"unknown WU %s",
				message + strlen(DC_MSG_CANCEL) + 1);
			return NULL;
		}
		DC_log(LOG_NOTICE, "Received cancel request from the master");
		client_state = STATE_FINISH;
		return new_event(DC_CLIENT_FINISH);
	}
	if (!strcmp(message, DC_MSG_SUSPEND))
	{
		DC_log(LOG_NOTICE, "Received suspend request from the master");
		client_state = STATE_SUSPEND;
		return new_event(DC_CLIENT_CHECKPOINT);
	}

	DC_log(LOG_WARNING, "Received unknown control message %s", message);

	return NULL;
}
示例#3
0
static int
_DC_rmsubdir(char *name)
{
	DIR *d;
	struct dirent *de;
	int i= 0;

	if ((d= opendir(name)) == NULL)
	{
		DC_log(LOG_DEBUG, "Open %s: %s", name, strerror(errno));
		return(0);
	}
	while ((de= readdir(d)))
	{
		if (strcmp(de->d_name, ".") != 0 &&
		    strcmp(de->d_name, "..") != 0)
		{
			char *s= malloc(strlen(name)+strlen(de->d_name) + 10);
			strcpy(s, name);
			strcat(s, "/");
			strcat(s, de->d_name);
			i+= _DC_rm(s);
			free(s);
		}
	}
	closedir(d);
	if (rmdir(name))
	{
		DC_log(LOG_ERR, "Failed to rmdir %s: %s",
		       name, strerror(errno));
	}
	return(i);
}
示例#4
0
char *DC_resolveFileName(DC_FileType type, const char *logicalFileName)
{
	char buf[PATH_MAX];
	int ret;

	if (!logicalFileName)
	{
		DC_log(LOG_ERR, "%s: Missing logical file name", __func__);
		return NULL;
	}

	if (!strcmp(logicalFileName, DC_CHECKPOINT_FILE))
	{
		if (type == DC_FILE_IN)
		{
			if (last_complete_ckpt)
				return strdup(last_complete_ckpt);
			return NULL;
		}
		else if (type == DC_FILE_OUT)
		{
			/* Remove the previous checkpoint if it was not
			 * finished */
			if (strlen(active_ckpt))
				unlink(active_ckpt);

			snprintf(active_ckpt, sizeof(active_ckpt), "dc_ckpt_%d",
				++ckpt_generation);
			DC_log(LOG_DEBUG, "Opened new checkpoint file %s",
				active_ckpt);
			return strdup(active_ckpt);
		}
		else
			return NULL;
	}

	/* Temporary files can be created in the current directory */
	if (type == DC_FILE_TMP)
		return strdup(logicalFileName);

	ret = boinc_resolve_filename(logicalFileName, buf, sizeof(buf));
	if (!ret) {
        if (type == DC_FILE_IN) {
    	    if (FILE * file = fopen(buf, "r")) 
    	    {
                fclose(file);
        		return strdup(buf);	    
    	    }
            return NULL;
    	}
		return strdup(buf);	    
	}

	/* Do not fail for missing output files in stand-alone mode */
	if (!wu_name[0] && type == DC_FILE_OUT)
		return strdup(logicalFileName);
	return NULL;
}
示例#5
0
int DC_initMaster(const char *config_file)
{
	char *cfgval;
	int ret;

	_DC_init_common();

	if (!config_file)
		config_file = DC_CONFIG_FILE;

	ret = _DC_parseCfg(config_file);
	if (ret)
	{
		DC_log(LOG_ERR, "The DC-API cannot be initialized without a "
			"config file");
		return ret;
	}

	/* Check the working directory */
	cfgval = DC_getCfgStr(CFG_WORKDIR);
	if (!cfgval)
	{
		DC_log(LOG_ERR, "%s is not specified in the config file",
			CFG_WORKDIR);
		return DC_ERR_CONFIG;
	}
	free(cfgval);

	/* Check sleep interval */
	sleep_interval = DC_getCfgInt(CFG_SLEEPINTERVAL, DEFAULT_SLEEP_INTERVAL);
	if (sleep_interval < 1)
		sleep_interval = 1;

	/* Check the project UUID */
	cfgval = DC_getCfgStr(CFG_INSTANCEUUID);
	if (!cfgval)
	{
		DC_log(LOG_ERR, "%s is not set in the config file",
			CFG_INSTANCEUUID);
		return DC_ERR_CONFIG;
	}

	ret = uuid_parse((char *)cfgval, project_uuid);
	if (ret)
	{
		DC_log(LOG_ERR, "Invalid project UUID");
		free(cfgval);
		return DC_ERR_CONFIG;
	}
	free(cfgval);

	/* Enforce a canonical string representation of the UUID */
	uuid_unparse_lower(project_uuid, project_uuid_str);

	return DC_OK;
}
示例#6
0
void DC_checkpointMade(const char *filename)
{
	FILE *f;

	if (!filename)
	{
		/* No file name - reset the checkpoint logic */
		if (active_ckpt[0])
			unlink(active_ckpt);
		active_ckpt[0] = '\0';

		if (last_complete_ckpt)
		{
			unlink(last_complete_ckpt);
			free(last_complete_ckpt);
			last_complete_ckpt = NULL;
		}

		boinc_checkpoint_completed();
		return;
	}

	if (strcmp(filename, active_ckpt))
	{
		DC_log(LOG_ERR, "DC_checkpointMade: bad checkpoint file %s "
			"(expected %s)", filename, active_ckpt);
		boinc_checkpoint_completed();
		return;
	}

	DC_log(LOG_INFO, "Completed checkpoint %s", filename);

	/* Remember which was the last completed checkpoint */
	f = boinc_fopen(LAST_CKPT_FILE, "w");
	if (f)
	{
		fprintf(f, "%s", filename);
		fclose(f);
	}

	if (last_complete_ckpt)
	{
		unlink(last_complete_ckpt);
		free(last_complete_ckpt);
	}
	last_complete_ckpt = strdup(filename);

	/* Reset the active checkpoint */
	active_ckpt[0] = '\0';

	boinc_checkpoint_completed();
	
	if (client_state == STATE_SUSPEND)
		client_state = STATE_FINISH;
}
示例#7
0
int
_DC_create_message(char *box,
		   char *name,
		   const char *message,
		   char *msgfile)
{
	char *fn, *fn2;
	FILE *f;
	int ret= DC_OK;

	/*DC_log(LOG_DEBUG, "DC_sendMessage(%s)", message);*/
	if (!box ||
	    !name)
		return(DC_ERR_BADPARAM);
	mkdir(box, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
	_DC_message_id++;
	fn= malloc(strlen(box)+strlen(name)+100);
	sprintf(fn, "%s/%s_creating.%d", box, name, _DC_message_id);
	if ((f= fopen(fn, "w")) != NULL)
	{
		if (message)
			fprintf(f, "%s", message);
		else if (msgfile)
		{
			if (_DC_copyFile(msgfile, fn))
				DC_log(LOG_ERR, "copyFile(%s,%s) error",
				       msgfile, fn);
		}
		else
		{
			DC_log(LOG_WARNING, "No message specified for "
			       "creation");
		}
		if (fsync(fileno(f)) != 0)
			DC_log(LOG_ERR, "Sync of %s: %d %s", fn,
			       errno, strerror(errno));
		fclose(f);
		/*DC_log(LOG_DEBUG, "Message %d created", _DC_message_id);*/
	}
	else
	{
		DC_log(LOG_ERR, "Error creating message file (%s)",
		       fn);
		ret= DC_ERR_SYSTEM;
	}
	fn2= malloc(strlen(box)+strlen(name)+100);
	sprintf(fn2, "%s/%s.%d", box, name, _DC_message_id);
	rename(fn, fn2);
	DC_log(LOG_DEBUG, "Message created: %s", fn2);
	free(fn2);
	free(fn);
	return(ret);
}
示例#8
0
void DC_finishClient(int exitcode)
{
	char path[PATH_MAX];
	int ret;

	/* Rename/copy the checkpoint file to the label CKPT_LABEL_OUT
	 * so it will be uploaded together with the result(s) */
	if (last_complete_ckpt &&
		!boinc_resolve_filename(CKPT_LABEL_OUT, path, sizeof(path)))
	{
#ifndef _WIN32
		ret = link(last_complete_ckpt, path);
		if (ret)
#endif
		ret = _DC_copyFile(last_complete_ckpt, path);

		DC_log(LOG_DEBUG, "Uploading last complete checkpoint %s",
			last_complete_ckpt);
	}

	/* Delete files that we have created */
	if (last_complete_ckpt)
		unlink(last_complete_ckpt);
	if (strlen(active_ckpt))
		unlink(active_ckpt);
	unlink(LAST_CKPT_FILE);

	/* Make sure the output is on disk */
	DC_log(LOG_DEBUG, "Flushing stdout/stderr");
	fflush(stdout);
	fflush(stderr);

	if (!boinc_resolve_filename(DC_LABEL_STDOUT, path, sizeof(path)))
	{
		DC_log(LOG_DEBUG, "Uploading stdout.txt");
		_DC_copyFile("stdout.txt", path);
	}

	if (!boinc_resolve_filename(DC_LABEL_STDERR, path, sizeof(path)))
	{
		DC_log(LOG_DEBUG, "Uploading stderr.txt");
		_DC_copyFile("stderr.txt", path);
	}

	DC_log(LOG_INFO, "DC-API: Application finished with exit code %d",
		exitcode);
	boinc_finish(exitcode);
	/* We should never get here, but boinc_finish() is not marked
	 * with "noreturn" so this avoids a GCC warning */
	exit(exitcode);
}
示例#9
0
DC_Workunit *_DC_getWUByName(const char *name)
{
	DC_Workunit *wu;
	char *uuid_str;
	uuid_t uuid;
	int ret;

	if (_DC_wu_table)
	{
		wu = (DC_Workunit *)g_hash_table_lookup(_DC_wu_table, name);
		if (wu)
			return wu;
	}

	/* Check if the WU belongs to this application */
	uuid_str = g_strndup(name, 36);
	ret = uuid_parse(uuid_str, uuid);
	g_free(uuid_str);
	if (ret)
	{
		DC_log(LOG_ERR, "WU name contains illegal UUID");
		return NULL;
	}

	if (uuid_compare(uuid, project_uuid))
	{
		DC_log(LOG_WARNING, "WU does not belong to this application");
		return NULL;
	}

	if (name[36] != '_')
	{
		DC_log(LOG_ERR, "Illegal WU name syntax");
		return NULL;
	}

	/* Check the WU's UUID */
	uuid_str = g_strndup(name + 37, 36);
	ret = uuid_parse(uuid_str, uuid);
	g_free(uuid_str);
	if (ret)
	{
		DC_log(LOG_ERR, "WU name contains illegal UUID");
		return NULL;
	}

	DC_log(LOG_ERR, "WU %s not found!", name);
	return NULL;
}
示例#10
0
int
_DC_rm(char *name)
{
	struct stat s;
	int i;

	if (!name ||
	    !*name)
		return(0);
	i= lstat(name, &s);
	if (i != 0)
	{
		return(0);
	}
	if (S_ISDIR(s.st_mode) &&
	    strcmp(name, ".") != 0 &&
	    strcmp(name, "..") != 0)
	{
		return(_DC_rmsubdir(name));
	}
	else
		{
			if (remove(name))
				DC_log(LOG_ERR, "Failed to remove %s: %s",
				       name, strerror(errno));
		}
	return(1);
}
示例#11
0
int DC_sendMessage(const char *message)
{
	char *xml, *msg;
	int ret, len;

	if (!message)
	{
		DC_log(LOG_ERR, "%s: Missing message", __func__);
		return DC_ERR_BADPARAM;
	}

	if (!wu_name[0])
	{
		DC_log(LOG_ERR, "Messaging is not available in stand-alone mode");
		return DC_ERR_NOTIMPL;
	}

	int buflen = 6 * strlen(message) + 1;
	xml = (char *)malloc(buflen);
	if (!xml)
	{
		DC_log(LOG_ERR, "Sending message: Out of memory");
		return DC_ERR_INTERNAL;
	}

	xml_escape(message, xml, buflen);
	len = strlen(xml) + 24;
	msg = (char *)malloc(len);
	if (!msg)
	{
		DC_log(LOG_ERR, "Sending message: Out of memory");
		free(xml);
		return DC_ERR_INTERNAL;
	}
	snprintf(msg, len, "<message>%s</message>", xml);

	/* We use the WU's name as the variety */
	ret = boinc_send_trickle_up(wu_name, msg);
	free(msg);
	free(xml);
	if (ret)
	{
		DC_log(LOG_ERR, "Failed to send trickle-up message");
		return DC_ERR_INTERNAL;
	}
	return 0;
}
示例#12
0
static char *get_workdir(const uuid_t uuid, int create)
{
	char *tmp, uuid_str[37], *cfgval;
	GString *str;
	int ret;

	uuid_unparse_lower(uuid, uuid_str);

	cfgval = DC_getCfgStr(CFG_WORKDIR);
	if (!cfgval)
		return NULL;
	str = g_string_new(cfgval);
	free(cfgval);

	if (create)
	{
		ret = mkdir(str->str, 0755);
		if (ret && errno != EEXIST)
			goto error;
	}

	g_string_append_c(str, G_DIR_SEPARATOR);
	g_string_append(str, ".dcapi-");
	g_string_append(str, project_uuid_str);
	if (create)
	{
		ret = mkdir(str->str, 0755);
		if (ret && errno != EEXIST)
			goto error;
	}

	g_string_append_c(str, G_DIR_SEPARATOR);
	g_string_append_printf(str, "%02x", uuid[0]);
	if (create)
	{
		ret = mkdir(str->str, 0755);
		if (ret && errno != EEXIST)
			goto error;
	}

	g_string_append_c(str, G_DIR_SEPARATOR);
	g_string_append(str, uuid_str);
	if (create)
	{
		ret = mkdir(str->str, 0755);
		if (ret && errno != EEXIST)
			goto error;
	}

	tmp = str->str;
	g_string_free(str, FALSE);
	return tmp;

error:
	DC_log(LOG_ERR, "Failed to create WU working directory %s: %s",
		str->str, strerror(errno));
	g_string_free(str, TRUE);
	return NULL;
}
示例#13
0
static void count_subresults(void)
{
	struct dirent *d;
	DIR *dir;

	dir = opendir(".");
	if (!dir)
		return;

	DC_log(LOG_DEBUG, "Workdir contents:");
	while ((d = readdir(dir)))
	{
		DC_log(LOG_DEBUG, "\t%s", d->d_name);
		if (!strncmp(d->d_name, SUBRESULT_PFX, strlen(SUBRESULT_PFX)))
			max_subresults++;
	}
	closedir(dir);
}
示例#14
0
/* Resumes computation of a previously suspended work unit. */
int
DC_resumeWU(DC_Workunit *wu)
{
    int ret;
    char *id;
    GString *dn;

    if (!_DC_wu_check(wu))
        return(DC_ERR_UNKNOWN_WU);

    DC_log(LOG_DEBUG, "DC_resumeWU(%p-\"%s\")", wu, wu->data.name);

    if (wu->data.state != DC_WU_SUSPENDED)
    {
        DC_log(LOG_NOTICE, "Can not resume a non-suspended wu");
        return(DC_ERR_INTERNAL);
    }
    dn= g_string_new(wu->data.workdir);
    g_string_append(dn, "/");
    g_string_append(dn, _DC_wu_cfg(wu, cfg_management_box));
    _DC_create_message(dn->str, _DCAPI_MSG_COMMAND, _DCAPI_CMD_RESUME,
                       NULL);
    g_string_free(dn, TRUE);
    ret= _DC_start_condor_job(wu);
    if (ret == 0)
    {
        _DC_wu_update_condor_events(wu);
        while (wu->condor_events->len == 0)
        {
            sleep(1);
            _DC_wu_update_condor_events(wu);
        }
        DC_log(LOG_DEBUG, "DC_ResumeWU...");
        _DC_wu_set_state(wu, DC_WU_RUNNING);
        id= DC_getWUId(wu);
        DC_log(LOG_INFO, "Condor id of wu's job: %s", id);
        g_free(id);
    }
    return(ret);
}
示例#15
0
/* Cancels all computations for a given work unit. */
int
DC_cancelWU(DC_Workunit *wu)
{
    int ret;

    if (!_DC_wu_check(wu))
        return(DC_ERR_UNKNOWN_WU);

    DC_log(LOG_DEBUG, "DC_cancelWU(%p-\"%s\")", wu, wu->data.name);

    if (wu->data.state != DC_WU_RUNNING &&
            wu->data.state != DC_WU_SUSPENDED)
    {
        DC_log(LOG_NOTICE, "Can not cancel a non-running/non-suspended wu");
        return(DC_ERR_INTERNAL);
    }
    ret= _DC_stop_condor_job(wu);
    if (wu->data.state == DC_WU_SUSPENDED)
        ret= 0;
    _DC_wu_set_state(wu, DC_WU_ABORTED);
    return((ret==0)?DC_OK:DC_ERR_BADPARAM);
}
示例#16
0
static int
_DC_stop_condor_job(DC_Workunit *wu)
{
    char *id;
    GString *cmd;
    int ret;

    if (!_DC_wu_check(wu))
        return(DC_ERR_UNKNOWN_WU);

    id= DC_getWUId(wu);
    if (!id)
        return(DC_ERR_UNKNOWN_WU);
    cmd= g_string_new("condor_rm ");
    cmd= g_string_append(cmd, id);
    DC_log(LOG_DEBUG, "Calling \"%s\"...", cmd->str);
    ret= system(cmd->str);
    DC_log(LOG_DEBUG, "Returned %d", ret);
    g_string_free(cmd, TRUE);
    g_free(id);
    return((ret==0)?DC_OK:DC_ERR_BADPARAM);
}
示例#17
0
int DC_submitWU(DC_Workunit *wu)
{
	pid_t pid;
	char *old_path, *new_path;

	if (wu->state != DC_WU_READY)
	{
		DC_log(LOG_ERR, "Only WUs in READY state can be submitted");
		return DC_ERR_BADPARAM;
	}

	/* copy the exec into the workdir */
	old_path = g_strdup_printf(/*"%s%c%s", wu->client_path, G_DIR_SEPARATOR, wu->client_name*/
		"%s", _DC_wu_cfg(wu, cfg_executable));
	new_path = g_strdup_printf("%s%c%s", wu->workdir, G_DIR_SEPARATOR, wu->client_name);
	if (link(old_path, new_path))
	{
		DC_log(LOG_ERR, "Failed to link %s to %s: %s",
			old_path, new_path, strerror(errno));
		return DC_ERR_BADPARAM;
	}
	g_free(old_path);
	g_free(new_path);

	if((pid=fork())<0) {
		DC_log(LOG_ERR,"Cannot fork!\nerrno=%d  %s\n",
			errno, strerror(errno));
		return DC_ERR_BADPARAM;
	}

	if(pid==0) /* client process */
	{
		/* change into working directory of the WU */
		if (chdir(wu->workdir))
		{
			DC_log(LOG_ERR,"Cannot cd into %s\nerrno=%d  %s\n",
			wu->workdir, errno, strerror(errno));
			return DC_ERR_BADPARAM;
		}

		/* hook up stdout and stderr to specially-named files */
		freopen(STDOUT_LABEL, "a", stdout);
		freopen(STDERR_LABEL, "a", stderr);

		/* execute the client */
		DC_log(LOG_INFO, "Work unit : %s executes: %s", wu->name, wu->client_name);
		execv(wu->client_name, wu->argv);
		DC_log(LOG_ERR, "Cannot execute. Errno=%d  %s\n",
			errno, strerror(errno));
		exit(1);
	}

	wu->pid = pid;
	wu->state = DC_WU_RUNNING;

	return DC_OK;
}
示例#18
0
/* Temporarily suspends the execution of a work unit. */
int
DC_suspendWU(DC_Workunit *wu)
{
    GString *dn;

    if (!_DC_wu_check(wu))
        return(DC_ERR_UNKNOWN_WU);

    DC_log(LOG_DEBUG, "DC_suspendWU(%p-\"%s\")", wu, wu->data.name);

    if (wu->data.state != DC_WU_RUNNING)
    {
        DC_log(LOG_NOTICE, "Can not suspend a non-running wu");
        return(DC_ERR_INTERNAL);
    }
    dn= g_string_new(wu->data.workdir);
    g_string_append(dn, "/");
    g_string_append(dn, _DC_wu_cfg(wu, cfg_management_box));
    _DC_create_message(dn->str, _DCAPI_MSG_COMMAND, _DCAPI_CMD_SUSPEND,
                       NULL);
    g_string_free(dn, TRUE);
    /*wu->asked_to_suspend= TRUE;*/
    return(DC_OK);
}
示例#19
0
static int
_DC_start_condor_job(DC_Workunit *wu)
{
    int ret;
    GString *cmd;
    gchar *act, *act2;

    cmd= g_string_new("condor_submit");
    cmd= g_string_append(cmd, " ");
    cmd= g_string_append(cmd, _DC_wu_cfg(wu, cfg_submit_file));
    act= getcwd(NULL, 0);
    chdir(wu->data.workdir);
    act2= getcwd(NULL, 0);
    DC_log(LOG_DEBUG, "Calling \"%s\" in %s...",
           cmd->str, act2);
    ret= system(cmd->str);
    DC_log(LOG_DEBUG, "Returned %d", ret);
    chdir(act);
    g_free(act);
    g_free(act2);
    g_string_free(cmd, TRUE);

    return ret;
}
示例#20
0
static void count_subresults(void)
{
	WIN32_FIND_DATA fdata;
	HANDLE hfind;

	hfind = FindFirstFile("*", &fdata);
	if (hfind == INVALID_HANDLE_VALUE)
		return;
	do {
		DC_log(LOG_DEBUG, "\t%s", fdata.cFileName);
		if (!strncmp(fdata.cFileName, SUBRESULT_PFX,
				strlen(SUBRESULT_PFX)))
			max_subresults++;
	} while (FindNextFile(hfind, &fdata));
	FindClose(hfind);
}
示例#21
0
/* Sends a message to a running work unit. */
int
DC_sendWUMessage(DC_Workunit *wu, const char *message)
{
	GString *dn;
	int ret;

	/*if (!_DC_wu_check(wu))
	  return(DC_ERR_UNKNOWN_WU);*/
	DC_log(LOG_DEBUG, "DC_sendWUMessage(%p-\"%s\", %s)",
	       wu, wu->name, message);
	dn= g_string_new(wu->workdir);
	g_string_append(dn, "/");
	g_string_append(dn, _DC_wu_cfg(wu, cfg_master_message_box));
	ret= _DC_create_message(dn->str, (char*)_DCAPI_MSG_MESSAGE, message, NULL);
	g_string_free(dn, TRUE);
	return(ret);
}
示例#22
0
int DC_sendResult(const char *logicalFileName, const char *path,
	DC_FileMode mode)
{
	char label[32], new_path[PATH_MAX], msg[PATH_MAX], *p;
	int ret;

	if (!logicalFileName)
	{
		DC_log(LOG_ERR, "%s: Missing logical file name", __func__);
		return DC_ERR_BADPARAM;
	}
	if (!path)
	{
		DC_log(LOG_ERR, "%s: Missing path", __func__);
		return DC_ERR_BADPARAM;
	}

	if (!DC_getMaxSubresults())
	{
		DC_log(LOG_ERR, "No more subresults are allowed to be sent");
		return DC_ERR_NOTIMPL;
	}

	/* We have to use the subresult labels that were defined by the
	 * master for doing the upload */
	snprintf(label, sizeof(label), "%s%d", SUBRESULT_PFX, ++subresult_cnt);
	if (boinc_resolve_filename(label, new_path, sizeof(new_path)))
		return DC_ERR_INTERNAL;

	/* We need the file name that will appear on the server */
	p = strrchr(new_path, PATHSEP);
	if (!p)
	{
		DC_log(LOG_ERR, "Failed to determine the on-server file name "
			"of the subresult");
		return DC_ERR_INTERNAL;
	}
	p++;

	switch (mode)
	{
		case DC_FILE_REGULAR:
			ret = _DC_copyFile(path, new_path);
			if (ret)
				return DC_ERR_SYSTEM;
			break;
		case DC_FILE_PERSISTENT:
#ifndef _WIN32
			ret = link(path, new_path);
			if (!ret)
				break;
#endif
			/* The client system may not support hard links so
			 * fall back to copying silently */
			ret = _DC_copyFile(path, new_path);
			if (ret)
				return DC_ERR_SYSTEM;
			break;
		case DC_FILE_VOLATILE:
			ret = rename(path, new_path);
			if (!ret)
				break;
			/* If renaming fails, fall back to copying, but in this
			 * case we are also responsible for deleting the
			 * original */
			ret = _DC_copyFile(path, new_path);
			if (ret)
				return DC_ERR_SYSTEM;
			break;
		case DC_FILE_REMOTE:
			/* Ignore this case, entirely handled by BOINC */
			break;
	}

	/* Stupid C++ */
	std::string str = label;
	ret = boinc_upload_file(str);
	if (ret)
	{
		unlink(new_path);
		return DC_ERR_INTERNAL;
	}

	DC_log(LOG_INFO, "File %s (%s) has been scheduled for upload",
		logicalFileName, label);

	snprintf(msg, sizeof(msg), "%s:%s:%s:%s", DCAPI_MSG_PFX, DC_MSG_UPLOAD,
		p, logicalFileName);
	DC_sendMessage(msg);

	/* If we had to copy volatile files, delete the original only when
	 * we are sure the upload will happen */
	if (mode == DC_FILE_VOLATILE)
		unlink(path);
	return 0;
}
示例#23
0
DC_ClientEvent *DC_checkClientEvent(void)
{
	DC_ClientEvent *event;
	char *buf, *msg;
	int ret;

	/* Check for checkpoint requests */
	if (boinc_time_to_checkpoint())
	{
		DC_log(LOG_DEBUG, "Core client requested checkpoint");
		return new_event(DC_CLIENT_CHECKPOINT);
	}

	/* Check for messages */
	buf = (char *)malloc(MAX_MESSAGE_SIZE);
	if (!buf)
		/* Let's hope the error is transient and we can deliver the
		 * message when DC_checkClientEvent() is called for the next time */
		return NULL;

	/* Check for trickle-down messages and also handle internal
	 * communication */
	ret = boinc_receive_trickle_down(buf, MAX_MESSAGE_SIZE);
	if (ret)
	{
		msg = (char *)malloc(MAX_MESSAGE_SIZE);
		if (!msg)
		{
			free(buf);
			return NULL;
		}
		ret = parse_str(buf, "<message>", msg, MAX_MESSAGE_SIZE);
		if (!ret)
		{
			DC_log(LOG_WARNING, "Failed to parse message %s", buf);
			free(buf);
			free(msg);
			return NULL;
		}

		if (!strncmp(msg, DCAPI_MSG_PFX, strlen(DCAPI_MSG_PFX)) &&
				msg[strlen(DCAPI_MSG_PFX)] == ':')
		{
			event = handle_special_msg(msg +
				strlen(DCAPI_MSG_PFX) + 1);
			free(msg);
			return event;
		}

		DC_log(LOG_DEBUG, "Received trickle message");

		event = new_event(DC_CLIENT_MESSAGE);
		event->message = buf;
		return event;
	}
	free(buf);

	if (client_state == STATE_FINISH)
		return new_event(DC_CLIENT_FINISH);

	return NULL;
}
示例#24
0
int DC_addWUInput(DC_Workunit *wu, const char *logicalFileName, const char *URL,
	DC_FileMode fileMode, ...)
{
	DC_PhysicalFile *file;
	char *workpath;
	int ret;

	/* Sanity checks */
	ret = check_logical_name(wu, logicalFileName);
	if (ret)
		return ret;

	if (fileMode & DC_FILE_PERSISTENT_CLIENT)
    {
		DC_log(LOG_WARNING, "File mode DC_FILE_PERSISTENT_CLIENT for input file %s is not supported",
			logicalFileName);
        fileMode ^= DC_FILE_PERSISTENT_CLIENT;
    }

	/* Remote files aren't supported */
	if (DC_FILE_REMOTE == fileMode)
	{
		DC_log(LOG_ERR, "Unsupported file mode for input file %s",
			logicalFileName);
		return DC_ERR_BADPARAM;
	}

	workpath = get_workdir_path(wu, logicalFileName, FILE_IN);
	file = _DC_createPhysicalFile(logicalFileName, workpath);
	g_free(workpath);
	if (!file)
		return DC_ERR_INTERNAL;

	switch (fileMode)
	{
		case DC_FILE_REGULAR:
			ret = copy_file(URL, file->path);
			if (ret)
			{
				_DC_destroyPhysicalFile(file);
				return DC_ERR_BADPARAM; /* XXX */
			}
			break;
		case DC_FILE_PERSISTENT:
			ret = link(URL, file->path);
			if (ret)
			{
				DC_log(LOG_ERR, "Failed to link %s to %s: %s",
					URL, file->path, strerror(errno));
				_DC_destroyPhysicalFile(file);
				return DC_ERR_BADPARAM; /* XXX */
			}
			/* Remember the file mode */
			file->mode = DC_FILE_PERSISTENT;
			break;
		case DC_FILE_VOLATILE:
			ret = rename(URL, file->path);
			if (ret)
			{
				DC_log(LOG_ERR, "Failed to rename %s to %s: %s",
					URL, file->path, strerror(errno));
				_DC_destroyPhysicalFile(file);
				return DC_ERR_BADPARAM; /* XXX */
			}
		default:
    		DC_log(LOG_ERR, "Unsupported file mode for input file %s",
    			logicalFileName);
		    _DC_destroyPhysicalFile(file);
    		return DC_ERR_BADPARAM;
	}

	wu->input_files = g_list_append(wu->input_files, file);
	wu->num_inputs++;
	return 0;
}
示例#25
0
static int copy_file(const char *src, const char *dst)
{
	int sfd, dfd;
	ssize_t ret;
	char *buf;

	buf = (char *)g_malloc(COPY_BUFSIZE);
	sfd = open(src, O_RDONLY);
	if (sfd == -1)
	{
		DC_log(LOG_ERR, "Failed to open %s for copying: %s", src,
			strerror(errno));
		g_free(buf);
		return -1;
	}
	dfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 00664);
	if (dfd == -1)
	{
		DC_log(LOG_ERR, "Failed to create %s: %s", dst, strerror(errno));
		g_free(buf);
		close(sfd);
		return -1;
	}

	while ((ret = read(sfd, buf, COPY_BUFSIZE)) > 0)
	{
		char *ptr = buf;
		while (ret)
		{
			ssize_t ret2 = write(dfd, ptr, ret);
			if (ret2 < 0)
			{
				DC_log(LOG_ERR, "Error writing to %s: %s", dst,
					strerror(errno));
				close(sfd);
				close(dfd);
				unlink(dst);
				g_free(buf);
				return -1;
			}
			ret -= ret2;
			ptr += ret2;
		}
	}

	if (ret < 0)
	{
		DC_log(LOG_ERR, "Error reading from %s: %s", src, strerror(errno));
		close(sfd);
		close(dfd);
		g_free(buf);
		unlink(dst);
		return -1;
	}

	g_free(buf);
	close(sfd);
	if (close(dfd))
	{
		DC_log(LOG_ERR, "Error writing to %s: %s", dst, strerror(errno));
		unlink(dst);
		return -1;
	}
	return 0;
}
示例#26
0
void DC_destroyWU(DC_Workunit *wu)
{
	char *path;
	int leave= strtol(_DC_wu_cfg(wu, cfg_leave_files), 0, 0);
	if (!wu)
		return;

	if (_DC_wu_table)
		g_hash_table_remove(_DC_wu_table, wu->name);

	switch (wu->state)
	{
		case DC_WU_RUNNING:
			/* XXX Abort the work unit */
			break;
		default:
			break;
	}

	while (wu->input_files &&
	       !leave)
	{
		DC_PhysicalFile *file = (DC_PhysicalFile *)wu->input_files->data;

		unlink(file->path);
		wu->input_files = g_list_delete_link(wu->input_files,
			wu->input_files);
		_DC_destroyPhysicalFile(file);
	}

	while (wu->output_files &&
	       !leave)
	{
		char *name = (char *)wu->output_files->data;
		char *file = g_strdup_printf("%s%c%s", wu->workdir, G_DIR_SEPARATOR, name);
		unlink(file);
		g_free(file);

		g_free(wu->output_files->data);
		wu->output_files = g_list_delete_link(wu->output_files,
			wu->output_files);
	}

	/* checkpoint file */
	path = g_strdup_printf("%s%c%s", wu->workdir, G_DIR_SEPARATOR, CKPT_LABEL);
	if (!leave)
		unlink(path);
	g_free(path);

	/* standard output file */
	path = g_strdup_printf("%s%c%s", wu->workdir, G_DIR_SEPARATOR, STDOUT_LABEL);
	if (!leave)
		unlink(path);
	g_free(path);

	/* standard error file */
	path = g_strdup_printf("%s%c%s", wu->workdir, G_DIR_SEPARATOR, STDERR_LABEL);
	if (!leave)
		unlink(path);
	g_free(path);

	if (wu->client_name &&
	    !leave)
	{
		char *path = g_strdup_printf("%s%c%s", wu->workdir, G_DIR_SEPARATOR, wu->client_name);
		unlink(path);
		g_free(path);
		g_free(wu->client_name);
		/*g_free(wu->client_path);*/
	}

	if (wu->workdir &&
	    !leave)
	{
		const char *name;
		GDir *dir;
		int ret;

		dir = g_dir_open(wu->workdir, 0, NULL);
		/* The work directory should not contain any extra files, but
		 * just in case */
		while (dir && (name = g_dir_read_name(dir)))
		{
			GString *str = g_string_new(wu->workdir);
			g_string_append_c(str, G_DIR_SEPARATOR);
			g_string_append(str, name);
			DC_log(LOG_INFO, "Removing unknown file %s",
				str->str);
			unlink(str->str);
			g_string_free(str, TRUE);
		}
		if (dir)
			g_dir_close(dir);

		ret = rmdir(wu->workdir);
		if (ret)
			DC_log(LOG_WARNING, "Failed to remove WU working "
				"directory %s: %s", wu->workdir,
				strerror(errno));
		g_free(wu->workdir);
	}

	g_free(wu->uuid_str);
	g_strfreev(wu->argv);
	g_free(wu->tag);
	g_free(wu->name);

	g_free(wu);
}
示例#27
0
int DC_initClient(void)
{
	char path[PATH_MAX], *buf, label[32];
	int i, ret;
	FILE *f;

	/* We leave the redirection to BOINC and only copy stdout.txt/stderr.txt
	 * to the final output location in DC_finishClient(). This means BOINC
	 * can rotate the files so they won't grow too big. */
	if (boinc_init_diagnostics(BOINC_DIAG_REDIRECTSTDERR |
			BOINC_DIAG_REDIRECTSTDOUT))
		return DC_ERR_INTERNAL;

	if (boinc_init())
		return DC_ERR_INTERNAL;

	/* Parse the config file if the master sent one */
	buf = DC_resolveFileName(DC_FILE_IN, DC_CONFIG_FILE);
	if (buf)
	{
		ret = _DC_parseCfg(buf);
		if (ret && ret != DC_ERR_SYSTEM)
			return ret;
	}
	free(buf);

	/* Check if we are starting from a checkpoint file */
	if ((f = boinc_fopen(LAST_CKPT_FILE, "r")))
	{
		fgets(path, sizeof(path), f);
		fclose(f);
		if (strlen(path))
			last_complete_ckpt = strdup(path);
	}
	/* If the application did not generate a checkpoint file before, check
	 * if the master sent one */
	else
		last_complete_ckpt = DC_resolveFileName(DC_FILE_IN, CKPT_LABEL_IN);

	if (last_complete_ckpt)
		DC_log(LOG_INFO, "Found initial checkpoint file %s",
			last_complete_ckpt);

	/* Extract the WU name from init_data.xml */
	if (boinc_is_standalone())
	{
		DC_log(LOG_NOTICE, "Running in stand-alone mode, some "
			"functions are not available");
		wu_name[0] = '\0';
	}
	else
	{
		APP_INIT_DATA init_data;

		boinc_get_init_data(init_data);
		strncpy(wu_name, init_data.wu_name, sizeof(wu_name));
	}

	/* Initialize all optional output files as empty to prevent
	 * <file_xfer_error>s */
	for (i = 0; i < DC_getMaxSubresults(); i++)
	{
		snprintf(label, sizeof(label), "%s%d", SUBRESULT_PFX, i);
		if (boinc_resolve_filename(label, path, sizeof(path)))
			continue;
		f = boinc_fopen(path, "w");
		if (f)
			fclose(f);
	}
	ret = boinc_resolve_filename(CKPT_LABEL_OUT, path, sizeof(path));
	if (!ret)
	{
		f = boinc_fopen(path, "w");
		if (f)
			fclose(f);
	}

	DC_log(LOG_INFO, "DC-API initialized for work unit %s", wu_name);

	return 0;
}
示例#28
0
/* Submits a work unit. */
int
DC_submitWU(DC_Workunit *wu)
{
    int ret;
    /*GString *fn;*/
    char *id;
    int tries;
    int sleeptime;
    int maxtries;

    if (!_DC_wu_check(wu))
        return(DC_ERR_UNKNOWN_WU);

    DC_log(LOG_DEBUG, "DC_submitWU(%p-\"%s\")", wu, wu->data.name);

    if (wu->data.state != DC_WU_READY)
    {
        DC_log(LOG_INFO, "Re-submission of %s", wu->data.name);
        return(DC_ERR_BADPARAM);
    }

    ret= _DC_wu_gen_condor_submit(wu);
    if (ret)
    {
        DC_log(LOG_ERR, "Submit file generation failed");
        return(ret);
    }

    /*fn= g_string_new(wu->workdir);*/
    /*fn= g_string_append(fn, "/condor_submit.txt");*/
    tries=0;
    sleeptime= DC_getCfgInt("SubmitRetrySleepTime", 2);
    maxtries = DC_getCfgInt("SubmitRetry", 5);
    do
    {
        ret= _DC_start_condor_job(wu);
        tries++;
        if (ret != 0)
        {
            if (tries > maxtries)
                break;
            DC_log(LOG_INFO, "Failed to submit WU to Condor. Sleeping for %d seconds and retrying (%d of %d)",
                   sleeptime, tries, maxtries);
            sleep(sleeptime);
            sleeptime*=2;
        }
    } while (ret != 0);
    if (ret == 0)
    {
        /* Fix #1105 */
        _DC_wu_set_state(wu, DC_WU_RUNNING);
        _DC_wu_update_condor_events(wu);
        while (wu->condor_events->len == 0)
        {
            sleep(1);
            _DC_wu_update_condor_events(wu);
        }
        /*_DC_wu_set_state(wu, DC_WU_RUNNING);*/
        id= DC_getWUId(wu);
        DC_log(LOG_INFO, "Condor id of wu's job: %s", id);
        g_free(id);
    }
    return(ret);
}
示例#29
0
DC_Workunit *DC_createWU(const char *clientName, const char *arguments[],
	int subresults, const char *tag)
{
	char uuid_str[37];
	DC_Workunit *wu;

	if (subresults > MAX_SUBRESULTS){
		DC_log(LOG_ERR, "DC_createWU: The given subresult number: %d is too high. (max:%d)",
			subresults, MAX_SUBRESULTS);
		return NULL;
	}

	if (!clientName)
	{
		DC_log(LOG_ERR, "DC_createWU: clientName is not supplied");
		return NULL;
	}

	wu = g_new0(DC_Workunit, 1);

	wu->argv = g_strdupv((char **)arguments);

	for (wu->argc = 0; arguments && arguments[wu->argc]; wu->argc++)
		/* Nothing */;

	wu->subresults = subresults;
	wu->tag = g_strdup(tag);

	uuid_generate(wu->uuid);
	uuid_unparse_lower(wu->uuid, uuid_str);
	wu->uuid_str = g_strdup(uuid_str);

	if (tag)
		wu->name = g_strdup_printf("%s_%s_%s", project_uuid_str,
			uuid_str, tag);
	else
		wu->name = g_strdup_printf("%s_%s", project_uuid_str, uuid_str);

	/* Calculate & create the working directory. The working directory
	 * has the form:
	 * <project work dir>/.dcapi-<project uuid>/<hash>/<wu uuid>
	 * Where <hash> is the first 2 hex digits of the uuid
	 */
	wu->workdir = get_workdir(wu->uuid, TRUE);
	if (!wu->workdir)
	{
		DC_destroyWU(wu);
		return NULL;
	}

	wu->client_name = /*DC_getClientCfgStr(clientName, "name", FALSE);*/
		strdup(clientName);
	/*wu->client_path = DC_getClientCfgStr(clientName, "path", FALSE);*/

	if (!wu->client_name/* || !wu->client_path*/)
	{
		DC_log(LOG_ERR, "Failed to create WU. Cannot find client name\n"
			"Define client application in the config file:\n"
			"[Client-%s]\nname = <client name>\npath = <client path>", clientName);
		DC_destroyWU(wu);
		return NULL;
	}

	DC_log(LOG_DEBUG, "client path: %%s,     client name: %s    from client: %s",
	       /*wu->client_path,*/ wu->client_name, clientName);

	if (!_DC_wu_table)
		_DC_wu_table = g_hash_table_new_full(g_str_hash, g_str_equal,
			NULL, NULL);
	g_hash_table_insert(_DC_wu_table, wu->name, wu);

	return wu;
}