diff --git a/checkin_notes b/checkin_notes index 9b04882259..a8beea462d 100755 --- a/checkin_notes +++ b/checkin_notes @@ -8840,3 +8840,15 @@ David 31 Dec 2003 validate.C test/ testbase.py + +David 31 Dec 2003 + - Added Python assimilator, courtesy of Stephen Pellicer + All the back-end programs could be implemented in Python; + CPU usage is a non-factor. + Some people might prefer this to C++. + No reason not to have both, as long as the logic stays in synch. + + py/Boinc/ + sched_messages.py + sched/ + assimilator.py diff --git a/doc/anonymous_platform.php b/doc/anonymous_platform.php new file mode 100644 index 0000000000..8c97b3ca0b --- /dev/null +++ b/doc/anonymous_platform.php @@ -0,0 +1,73 @@ +The project-compiles-it-for-you model +

+In this approach, the BOINC-based project +compiles program versions for common platforms +(Windows/Intel, Linux/Intel, Mac OS/X. etc.), +and places them on its servers. +A participant downloads the core client for his platform +(assuming that it's supported by the project). +When the core client requests work from the project's scheduling server, +it tells the server its platform, +and the scheduling server instructs it to download +the appropriate application executables. +

+Although this addresses the needs of most BOINC participants, +there are two groups for whom it is inadequate: +

+ +

The compile-it-yourself model

+

+In this model participants compile programs themselves +rather than downloading them from the project. +Here's how it works: + +

+ +This model is possible only with projects that make their application +source code available. +

+ +Note: the compile-it-yourself model is under development, +and is not currently available. +Participants with uncommon platforms can prepare by porting +the current core client and applications to their platforms. + +"; +page_tail(); +?> diff --git a/doc/client.php b/doc/client.php index c9cd432878..b6000d5bb1 100644 --- a/doc/client.php +++ b/doc/client.php @@ -114,12 +114,9 @@ The work manager's menu items are as follows:

-Menu names and other text in the work manager are stored in -a file called language.ini. -The release uses American English. -Other languages are available -here -(thanks to Robi Buechler and other volunteers for this). +The text displayed by the work manager (menu names, etc.) +can be translated to languages other than English; +information about this is here.

The BOINC screensaver can be selected using the Display Properties dialog. diff --git a/doc/contact.php b/doc/contact.php index 2bed3a5510..5350831528 100644 --- a/doc/contact.php +++ b/doc/contact.php @@ -29,6 +29,8 @@ Janus Kristensen
Tim Lan
+Stephen Pellicer +
Rom Walton
Oliver Wang diff --git a/doc/db_dump.php b/doc/db_dump.php index bfd1ebab53..53939c3990 100644 --- a/doc/db_dump.php +++ b/doc/db_dump.php @@ -6,6 +6,13 @@ echo "

BOINC projects may export data describing teams, users and hosts. This data is exported in XML files that can be downloaded via HTTP. +

+This data can be summarized and represented as Web pages. +An example (implemented using PHP) is at +http://www.boinc.dk. +If you are interested in using or contributing to this code, +please contact the developer, +Janus Kristensen.

The data is presented in several different 'views': diff --git a/doc/participate.php b/doc/participate.php index bdec622839..fbfa2ac5be 100644 --- a/doc/participate.php +++ b/doc/participate.php @@ -13,6 +13,8 @@ echo "

  • Computation credit
  • Teams
  • Downloading statistics data +
  • Language customization +
  • Compile-it-yourself BOINC "; page_tail(); diff --git a/doc/translations.php b/doc/translations.php index 28a6ad42dc..b07cd17d0c 100644 --- a/doc/translations.php +++ b/doc/translations.php @@ -5,45 +5,27 @@ echo " Information about BOINC is available in the following languages: If you'd like to add a web site to this list, please contact us. diff --git a/py/Boinc/sched_messages.py b/py/Boinc/sched_messages.py new file mode 100644 index 0000000000..0931660ea8 --- /dev/null +++ b/py/Boinc/sched_messages.py @@ -0,0 +1,25 @@ +import sys, time + +CRITICAL=0 +NORMAL=1 +DEBUG=2 + +class SchedMessages: + def __init__(self): + self.debug_level = 0 + + def set_debug_level(self, level): + self.debug_level = int(level) + + def printf(self, kind, format, *args): + if kind <= self.debug_level: + if kind==CRITICAL: + kind = "CRITICAL" + elif kind==NORMAL: + kind = "normal " + elif kind==DEBUG: + kind = "debug " + else: + kind = "*** internal error: invalid MessageKind ***"; + sys.stderr.write("%s [%s] " % (time.strftime("%Y/%m/%d %H:%M:%S", time.localtime()), kind)) + sys.stderr.write(format % args) diff --git a/sched/assimilator.py b/sched/assimilator.py new file mode 100644 index 0000000000..685dcf4f08 --- /dev/null +++ b/sched/assimilator.py @@ -0,0 +1,135 @@ +#!/usr/bin/python +''' +Python implementation of an assimilator +Contributed by Stephen Pellicer +''' + +import os, re, boinc_path_config, signal, sys, time +from Boinc import database, boinc_db, configxml, sched_messages + +STOP_TRIGGER_FILENAME = os.path.join('..', 'stop_servers') +caught_sig_int = False +log_messages=sched_messages.SchedMessages() + +def check_stop_trigger(): + global caught_sig_int, log_messages + try: + junk = open(STOP_TRIGGER_FILENAME, 'r') + except IOError: + if caught_sig_int: + log_messages.printf(sched_messages.CRITICAL, "Caught SIGINT\n") + sys.exit(1) + else: + log_messages.printf(sched_messages.CRITICAL, "Found stop trigger\n") + sys.exit(1) + +def sigint_handler(sig, stack): + global caught_sig_int + log_messages.printf(sched_messages.DEBUG, "Handled SIGINT\n") + caught_sig_int = True + +def get_file_path(result): + return os.path.join(config.upload_dir, re.search('(.*)', result.xml_doc_out).group(1)) + +def assimilate_handler(wu, results, canonical_result): + # check for valid wu.canonical_resultid + if wu.canonical_result: + # do application specific processing + log_messages.printf(sched_messages.NORMAL, "[%s] Found canonical result\n", wu.name) + question = open(os.path.join('..', 'question'), 'r').read()[:32] + log_messages.printf(sched_messages.DEBUG, "Comparing to %s\n", question) + if len(question) != 32: + log_messages.printf(sched_messages.CRITICAL, "Question %s is wrong length\n", question) + else: + result = get_file_path(canonical_result) + for line in open(result, 'r').readlines(): + line = line.strip() + log_messages.printf(sched_messages.DEBUG, " [%s] Answer found %s %s\n", canonical_result.name, line[-32:], line[:-33]) + if line[-32:] == question: + log_messages.printf(sched_messages.CRITICAL, "[RESULT#%d %s] Found Answer %s\n", canonical_result.id, canonical_result.name, line[:-33]) + else: + log_messages.printf(sched_messages.NORMAL, "[%s] No canonical result\n", wu.name) + + if wu.error_mask&boinc_db.WU_ERROR_COULDNT_SEND_RESULT: + log_messages.printf(sched_messages.CRITICAL, "[%s] Error: couldn't send a result\n", wu.name) + if wu.error_mask&boinc_db.WU_ERROR_TOO_MANY_ERROR_RESULTS: + log_messages.printf(sched_messages.CRITICAL, "[%s] Error: too many error results\n", wu.name) + if wu.error_mask&boinc_db.WU_ERROR_TOO_MANY_TOTAL_RESULTS: + log_messages.printf(sched_messages.CRITICAL, "[%s] Error: too many total results\n", wu.name) + if wu.error_mask&boinc_db.WU_ERROR_TOO_MANY_SUCCESS_RESULTS: + log_messages.printf(sched_messages.CRITICAL, "[%s] Error: too many success results\n", wu.name) + # check for error conditions + +def do_pass(app): + did_something=False + # check for stop trigger + check_stop_trigger() + + # look for workunits with correct appid and assimilate_state==ASSIMILATE_READY + for wu in database.Workunits.find(app=app, assimilate_state=boinc_db.ASSIMILATE_READY): + did_something=True + canonical_result=None + results=None + log_messages.printf(sched_messages.DEBUG, "[%s] assimilating: state=%d\n", wu.name, wu.assimilate_state) + results = database.Results.find(workunit=wu) + # look for canonical result for workunit in results + for result in results: + if result == wu.canonical_result: + canonical_result=result + + # assimilate handler + assimilate_handler(wu, results, canonical_result) + + # tag wu as ASSIMILATE_DONE + wu.assimilate_state = boinc_db.ASSIMILATE_DONE + wu.transition_time = int(time.time()) + wu.commit() + + # set wu transition_time + + # return did something result + return did_something + +# main function +asynch = False +one_pass = False +appname = '' + +# check for asynch one_pass, debug, app +args = sys.argv[1:] +args.reverse() +while(len(args)): + arg = args.pop() + if arg == '-asynch': + asynch = True + elif arg == '-one_pass': + one_pass = True + elif arg == '-d': + arg = args.pop() + log_messages.set_debug_level(arg) + elif arg == '-app': + arg = args.pop() + appname = arg + else: + log_messages.printf(sched_messages.CRITICAL, "Unrecognized arg: %s\n", arg) + +config = configxml.default_config().config +database.connect() + +# fork if asynch +if(asynch): + # add fork code + pass + +# retrieve app where name = app.name +app=database.Apps.find1(name=appname) +signal.signal(signal.SIGINT, sigint_handler) + +# do one pass or execute main loop +if one_pass: + do_pass(app) +else: + # main loop + while(1): + if not do_pass(app): + time.sleep(10)