- client (Unix): use symbolic links instead of XML link files.

This will allow applications to access shared libraries
    by their logical names,
    which simplifies things when you have multiple platforms,
    and the apps (or libraries) refer to shared libraries
    by names that don't include the platform.
    This shouldn't impact the API - boinc_resolve_filename()
    will open the file, see that it's not an XML link file,
    and the symbolic link will be used directly.
    At some point we can change boinc_resolve_filename() on Unix
    to be a no-op if the client is 6.2+
- client (Unix):
    Append the slot dir to LD_LIBRARY_PATH.

svn path=/trunk/boinc/; revision=14944
This commit is contained in:
David Anderson 2008-03-19 16:54:36 +00:00
parent 0592fa868b
commit 6ba8928537
8 changed files with 108 additions and 83 deletions

View File

@ -2504,3 +2504,29 @@ Charlie Mar 19 2008
mac_installer/ mac_installer/
release_boinc.sh release_boinc.sh
release_GridRepublic.sh release_GridRepublic.sh
David Mar 19 2008
- client (Unix): use symbolic links instead of XML link files.
This will allow applications to access shared libraries
by their logical names,
which simplifies things when you have multiple platforms,
and the apps (or libraries) refer to shared libraries
by names that don't include the platform.
This shouldn't impact the API - boinc_resolve_filename()
will open the file, see that it's not an XML link file,
and the symbolic link will be used directly.
At some point we can change boinc_resolve_filename() on Unix
to be a no-op if the client is 6.2+
- client (Unix):
Append the slot dir to LD_LIBRARY_PATH.
client/
app_start.C
client_types.C,h
lib/
boinc_cmd.C
error_numbers.h
py/Boinc/
tools.py
tools/
update_versions

View File

@ -81,10 +81,8 @@ using std::vector;
// //
#ifndef _WIN32 #ifndef _WIN32
static void debug_print_argv(char** argv) { static void debug_print_argv(char** argv) {
int i;
msg_printf(0, MSG_INFO, "[task_debug] Arguments:"); msg_printf(0, MSG_INFO, "[task_debug] Arguments:");
for (i=0; argv[i]; i++) { for (int i=0; argv[i]; i++) {
msg_printf(0, MSG_INFO, msg_printf(0, MSG_INFO,
"[task_debug] argv[%d]: %s\n", i, argv[i] "[task_debug] argv[%d]: %s\n", i, argv[i]
); );
@ -92,43 +90,6 @@ static void debug_print_argv(char** argv) {
} }
#endif #endif
// create a file (new_link) which contains an XML
// reference to existing file.
//
static int make_link(const char *existing, const char *new_link) {
FILE *fp;
fp = boinc_fopen(new_link, "w");
if (!fp) return ERR_FOPEN;
fprintf(fp, "<soft_link>%s</soft_link>\n", existing);
fclose(fp);
#ifdef SANDBOX
return set_to_project_group(new_link);
#endif
return 0;
}
int ACTIVE_TASK::link_user_files() {
PROJECT* project = wup->project;
unsigned int i;
FILE_REF fref;
FILE_INFO* fip;
char link_path[1024], buf[256], file_path[1024];
int retval;
for (i=0; i<project->user_files.size(); i++) {
fref = project->user_files[i];
fip = fref.file_info;
if (fip->status != FILE_PRESENT) continue;
get_pathname(fip, file_path, sizeof(file_path));
sprintf(link_path, "%s/%s", slot_dir, strlen(fref.open_name)?fref.open_name:fip->name);
sprintf(buf, "../../%s", file_path);
retval = make_link(buf, link_path);
if (retval) return retval;
}
return 0;
}
// make a unique key for core/app shared memory segment // make a unique key for core/app shared memory segment
// //
int ACTIVE_TASK::get_shmem_seg_name() { int ACTIVE_TASK::get_shmem_seg_name() {
@ -250,11 +211,14 @@ int ACTIVE_TASK::write_app_init_file() {
return retval; return retval;
} }
// set up a 'symbolic link' in the slot dir to the given file // set up a file reference, given a slot dir and project dir.
// (or copy the file to slot dir) // This means:
// 1) copy the file to slot dir, if reference is by copy
// 2) (Unix) make a symbolic link
// 3) (Windows) make a
// //
static int setup_file( static int setup_file(
WORKUNIT* wup, FILE_INFO* fip, FILE_REF& fref, PROJECT* project, FILE_INFO* fip, FILE_REF& fref,
char* file_path, char* slot_dir, bool input char* file_path, char* slot_dir, bool input
) { ) {
char link_path[256], buf[256]; char link_path[256], buf[256];
@ -266,11 +230,18 @@ static int setup_file(
); );
sprintf(buf, "../../%s", file_path ); sprintf(buf, "../../%s", file_path );
// if anonymous platform, this is called even if not first time,
// so link may already be there
//
if (input && project->anonymous_platform && boinc_file_exists(link_path)) {
return 0;
}
if (fref.copy_file) { if (fref.copy_file) {
if (input) { if (input) {
retval = boinc_copy(file_path, link_path); retval = boinc_copy(file_path, link_path);
if (retval) { if (retval) {
msg_printf(wup->project, MSG_INTERNAL_ERROR, msg_printf(project, MSG_INTERNAL_ERROR,
"Can't copy %s to %s", file_path, link_path "Can't copy %s to %s", file_path, link_path
); );
return retval; return retval;
@ -279,18 +250,46 @@ static int setup_file(
return 0; return 0;
} }
// if anonymous platform, link may already be there #ifdef _WIN32
// FILE *fp = boinc_fopen(link_path, "w");
if (input && wup->project->anonymous_platform && boinc_file_exists(link_path)) { if (!fp) {
return 0; msg_printf(project, MSG_INTERNAL_ERROR,
} "Can't open link file %s", link_path
retval = make_link(buf, link_path);
if (retval) {
msg_printf(wup->project, MSG_INTERNAL_ERROR,
"Can't link %s to %s", file_path, link_path
); );
return retval; return ERR_FOPEN;
}
fprintf(fp, "<soft_link>%s</soft_link>\n", file_path);
fclose(fp);
#else
retval = symlink(file_path, link_path);
if (retval) {
msg_printf(project, MSG_INTERNAL_ERROR,
"Can't symlink %s to %s", file_path, link_path
);
return ERR_SYMLINK;
}
#endif
#ifdef SANDBOX
return set_to_project_group(link_path);
#endif
return 0;
}
int ACTIVE_TASK::link_user_files() {
PROJECT* project = wup->project;
unsigned int i;
FILE_REF fref;
FILE_INFO* fip;
char file_path[1024];
int retval;
for (i=0; i<project->user_files.size(); i++) {
fref = project->user_files[i];
fip = fref.file_info;
if (fip->status != FILE_PRESENT) continue;
get_pathname(fip, file_path, sizeof(file_path));
setup_file(project, fip, fref, file_path, slot_dir, true);
if (retval) return retval;
} }
return 0; return 0;
} }
@ -415,10 +414,10 @@ int ACTIVE_TASK::start(bool first_time) {
safe_strcpy(exec_path, file_path); safe_strcpy(exec_path, file_path);
} }
// anonymous platform may use different files than // anonymous platform may use different files than
// when the result was started // when the result was started, so link files even if not first time
// //
if (first_time || wup->project->anonymous_platform) { if (first_time || wup->project->anonymous_platform) {
retval = setup_file(wup, fip, fref, file_path, slot_dir, true); retval = setup_file(result->project, fip, fref, file_path, slot_dir, true);
if (retval) { if (retval) {
strcpy(buf, "Can't link input file"); strcpy(buf, "Can't link input file");
goto error; goto error;
@ -438,7 +437,7 @@ int ACTIVE_TASK::start(bool first_time) {
fref = wup->input_files[i]; fref = wup->input_files[i];
fip = fref.file_info; fip = fref.file_info;
get_pathname(fref.file_info, file_path, sizeof(file_path)); get_pathname(fref.file_info, file_path, sizeof(file_path));
retval = setup_file(wup, fip, fref, file_path, slot_dir, true); retval = setup_file(result->project, fip, fref, file_path, slot_dir, true);
if (retval) { if (retval) {
strcpy(buf, "Can't link input file"); strcpy(buf, "Can't link input file");
goto error; goto error;
@ -449,7 +448,7 @@ int ACTIVE_TASK::start(bool first_time) {
if (fref.copy_file) continue; if (fref.copy_file) continue;
fip = fref.file_info; fip = fref.file_info;
get_pathname(fref.file_info, file_path, sizeof(file_path)); get_pathname(fref.file_info, file_path, sizeof(file_path));
retval = setup_file(wup, fip, fref, file_path, slot_dir, false); retval = setup_file(result->project, fip, fref, file_path, slot_dir, false);
if (retval) { if (retval) {
strcpy(buf, "Can't link output file"); strcpy(buf, "Can't link output file");
goto error; goto error;
@ -710,7 +709,7 @@ int ACTIVE_TASK::start(bool first_time) {
// //
char libpath[8192]; char libpath[8192];
get_project_dir(wup->project, buf, sizeof(buf)); get_project_dir(wup->project, buf, sizeof(buf));
sprintf(libpath, "%s:%s", getenv("LD_LIBRARY_PATH"), buf); sprintf(libpath, "%s:%s:%s", getenv("LD_LIBRARY_PATH"), buf, slot_dir);
setenv("LD_LIBRARY_PATH", libpath, 1); setenv("LD_LIBRARY_PATH", libpath, 1);
retval = chdir(slot_dir); retval = chdir(slot_dir);

View File

@ -1177,7 +1177,6 @@ int FILE_REF::parse(MIOFILE& in) {
strcpy(file_name, ""); strcpy(file_name, "");
strcpy(open_name, ""); strcpy(open_name, "");
fd = -1;
main_program = false; main_program = false;
copy_file = false; copy_file = false;
optional = false; optional = false;
@ -1185,7 +1184,6 @@ int FILE_REF::parse(MIOFILE& in) {
if (match_tag(buf, "</file_ref>")) return 0; if (match_tag(buf, "</file_ref>")) return 0;
if (parse_str(buf, "<file_name>", file_name, sizeof(file_name))) continue; if (parse_str(buf, "<file_name>", file_name, sizeof(file_name))) continue;
if (parse_str(buf, "<open_name>", open_name, sizeof(open_name))) continue; if (parse_str(buf, "<open_name>", open_name, sizeof(open_name))) continue;
if (parse_int(buf, "<fd>", fd)) continue;
if (parse_bool(buf, "main_program", main_program)) continue; if (parse_bool(buf, "main_program", main_program)) continue;
if (parse_bool(buf, "copy_file", copy_file)) continue; if (parse_bool(buf, "copy_file", copy_file)) continue;
if (parse_bool(buf, "optional", optional)) continue; if (parse_bool(buf, "optional", optional)) continue;
@ -1208,9 +1206,6 @@ int FILE_REF::write(MIOFILE& out) {
if (strlen(open_name)) { if (strlen(open_name)) {
out.printf(" <open_name>%s</open_name>\n", open_name); out.printf(" <open_name>%s</open_name>\n", open_name);
} }
if (fd >= 0) {
out.printf(" <fd>%d</fd>\n", fd);
}
if (main_program) { if (main_program) {
out.printf(" <main_program/>\n"); out.printf(" <main_program/>\n");
} }

View File

@ -122,9 +122,8 @@ public:
// or the app will be connected by the given fd (in which case fd is nonzero) // or the app will be connected by the given fd (in which case fd is nonzero)
// //
struct FILE_REF { struct FILE_REF {
char file_name[256]; char file_name[256]; // physical name
char open_name[256]; char open_name[256]; // logical name
int fd;
bool main_program; bool main_program;
FILE_INFO* file_info; FILE_INFO* file_info;
bool copy_file; bool copy_file;

View File

@ -59,7 +59,6 @@ Commands:\n\
--project_attach URL auth attach to project\n\ --project_attach URL auth attach to project\n\
--join_acct_mgr URL name passwd attach account manager\n\ --join_acct_mgr URL name passwd attach account manager\n\
--quit_acct_mgr quit current account manager\n\ --quit_acct_mgr quit current account manager\n\
\n\
--get_state show entire state\n\ --get_state show entire state\n\
--get_results show results\n\ --get_results show results\n\
--get_simple_gui_info show status of projects and active results\n\ --get_simple_gui_info show status of projects and active results\n\
@ -70,7 +69,6 @@ Commands:\n\
--get_messages seqno show messages > seqno\n\ --get_messages seqno show messages > seqno\n\
--get_host_info\n\ --get_host_info\n\
--version, -V show core client version\n\ --version, -V show core client version\n\
\n\
--result url result_name op job operation\n\ --result url result_name op job operation\n\
op = suspend | resume | abort | graphics_window | graphics_fullscreen\n\ op = suspend | resume | abort | graphics_window | graphics_fullscreen\n\
--project URL op project operation\n\ --project URL op project operation\n\

View File

@ -185,6 +185,7 @@
#define ERR_TOO_MANY_EXITS -226 #define ERR_TOO_MANY_EXITS -226
#define ERR_RMDIR -227 #define ERR_RMDIR -227
#define ERR_CHILD_FAILED -228 #define ERR_CHILD_FAILED -228
#define ERR_SYMLINK -229
// PLEASE: add a text description of your error to // PLEASE: add a text description of your error to
// the text description function boincerror() in str_util.C. // the text description function boincerror() in str_util.C.

View File

@ -132,6 +132,7 @@ def process_app_version(
signature_files={}, signature_files={},
file_ref_infos={}, file_ref_infos={},
api_version='', api_version='',
extra_xml='',
quiet=False quiet=False
): ):
"""Return xml for application version """Return xml for application version
@ -157,10 +158,11 @@ def process_app_version(
file_ref_infos is a dictionary mapping exec_file -> extra XML strings to file_ref_infos is a dictionary mapping exec_file -> extra XML strings to
include in <file_info>, e.g. '<copy_file/>' include in <file_info>, e.g. '<copy_file/>'
exec_files[1:] and non_exec_files should be named like 'open_name=url_filename'. exec_files[1:] and non_exec_files should be named like
(url_filename is the basename of file as copied to 'open_name=url_filename'.
download/) If there is no '=', then the entire filename is (url_filename is the basename of file as copied to download/)
used as both the open_name and the filename. If there is no '=', then the entire filename is used as
both the open_name and the filename.
""" """
assert(exec_files) assert(exec_files)
@ -191,7 +193,9 @@ def process_app_version(
app.name, version_num) app.name, version_num)
if (len(api_version)): if (len(api_version)):
xml_doc += ' <api_version>'+api_version+'</api_version>\n'; xml_doc += ' <api_version>'+api_version+'</api_version>\n'
if (len(extra_xml)):
xml_doc += extra_xml
first = True first = True
for exec_file in exec_files + non_exec_files: for exec_file in exec_files + non_exec_files:

View File

@ -59,7 +59,8 @@ def add_files(
exec_files, # executable files; entry 0 is the main program exec_files, # executable files; entry 0 is the main program
non_exec_files=[], # non-executable files non_exec_files=[], # non-executable files
signature_files={}, signature_files={},
file_ref_infos = {} file_ref_infos = {},
extra_xml = ''
): ):
''' add files to app. ''' add files to app.
''' '''
@ -98,7 +99,8 @@ def add_files(
non_exec_files = non_exec_files, non_exec_files = non_exec_files,
signature_files = signature_files, signature_files = signature_files,
file_ref_infos = file_ref_infos, file_ref_infos = file_ref_infos,
api_version = api_version api_version = api_version,
extra_xml = extra_xml
) )
object = database.AppVersion( object = database.AppVersion(
@ -120,12 +122,8 @@ def re_match_exec_filename(filepath):
def find_versions(app, dir): def find_versions(app, dir):
"""Find application versions in DIR. """Find application versions in DIR.
If directory contains sub-directories,
If directory contains sub-directories, those are scanned (non-recursively) those are scanned (non-recursively) for files.
for files. If an executable is found, the first one found
(alphabetically) is the main program and other files bundled as
non-executables.
""" """
for filepath in xlistdir(dir): for filepath in xlistdir(dir):
@ -184,6 +182,7 @@ def find_versions__process_bundle(app, match, dir):
non_exec_files = [] non_exec_files = []
signature_files = {} signature_files = {}
file_ref_infos = {} file_ref_infos = {}
extra_xml = ''
dirname = os.path.basename(dir) dirname = os.path.basename(dir)
found_main = False found_main = False
for filepath in xlistdir(dir): for filepath in xlistdir(dir):
@ -200,6 +199,9 @@ def find_versions__process_bundle(app, match, dir):
s = filepath[:-4] s = filepath[:-4]
signature_files[s] = filepath signature_files[s] = filepath
continue continue
if os.path.basename(filepath) == 'extra_xml':
extra_xml = open(filepath).read()
continue
if filepath.endswith('.file_ref_info'): if filepath.endswith('.file_ref_info'):
s = filepath[:-len('.file_ref_info')] s = filepath[:-len('.file_ref_info')]
file_ref_infos[s] = open(filepath).read() file_ref_infos[s] = open(filepath).read()
@ -228,6 +230,7 @@ def find_versions__process_bundle(app, match, dir):
non_exec_files = non_exec_files, non_exec_files = non_exec_files,
signature_files = signature_files, signature_files = signature_files,
file_ref_infos = file_ref_infos, file_ref_infos = file_ref_infos,
extra_xml = extra_xml,
) )
#################### ####################