From 8063219c416fc410a191c67a2db1aafa937d5feb Mon Sep 17 00:00:00 2001 From: David Anderson Date: Wed, 1 Feb 2006 07:04:24 +0000 Subject: [PATCH] state file read logic svn path=/trunk/boinc/; revision=9376 --- checkin_notes | 23 ++++++++++++++++++ client/cs_statefile.C | 56 +++++++++++++++++++++---------------------- 2 files changed, 50 insertions(+), 29 deletions(-) diff --git a/checkin_notes b/checkin_notes index 07dbccc982..1f4074b733 100755 --- a/checkin_notes +++ b/checkin_notes @@ -1252,3 +1252,26 @@ Bruce 31 Jan 2006 inc/ user.inc +David 31 Jan 2005 + - core client: finish logic for recovering from state file write failures. + For some reason I'd done the write part but not the read part. + write: + 1) write "next" + 2) rename "current" to "prev" + 3) rename "next" to "current" + read: + if "next" is valid, use it + (in case failure between 1 and 2) + In principle we should rename "next" to "current" here, + but I didn't bother doing this. + else if "current" is valid use it + (normal case) + else if "prev" is valid use it + (in case 3) failed and file got deleted) + + "is valid" means that the file has a tag, + followed later by a tag + + client/ + cs_statefile.C + diff --git a/client/cs_statefile.C b/client/cs_statefile.C index 4e762b56fe..b31331dd55 100644 --- a/client/cs_statefile.C +++ b/client/cs_statefile.C @@ -36,11 +36,30 @@ void CLIENT_STATE::set_client_state_dirty(const char* source) { client_state_dirty = true; } +static bool valid_state_file(char* fname) { + char buf[256]; + FILE* f = boinc_fopen(fname, "r"); + if (!f) return false; + fgets(buf, 256, f); + if (!match_tag(buf, "")) { + fclose(f); + return false; + } + while (fgets(buf, 256, f)) { + if (match_tag(buf, "")) { + fclose(f); + return true; + } + } + fclose(f); + return false; +} + // Parse the client_state.xml file // int CLIENT_STATE::parse_state_file() { - char buf[256]; PROJECT *project=NULL; + char buf[256]; int retval=0; int failnum; const char *fname; @@ -50,10 +69,12 @@ int CLIENT_STATE::parse_state_file() { // Look for a valid state file: // First the regular one, then the "next" one. // - if (boinc_file_exists(STATE_FILE_NAME)) { - fname = STATE_FILE_NAME; - } else if (boinc_file_exists(STATE_FILE_NEXT)) { + if (valid_state_file(STATE_FILE_NEXT)) { fname = STATE_FILE_NEXT; + } else if (valid_state_file(STATE_FILE_NAME)) { + fname = STATE_FILE_NAME; + } else if (boinc_file_exists(STATE_FILE_PREV)) { + fname = STATE_FILE_PREV; } else { scope_messages.printf("CLIENT_STATE::parse_state_file(): No state file; will create one\n"); @@ -68,25 +89,9 @@ int CLIENT_STATE::parse_state_file() { FILE* f = fopen(fname, "r"); MIOFILE mf; mf.init_file(f); - fgets(buf, 256, f); - if (!match_tag(buf, "")) { - - // if file is invalid (probably empty), try the previous statefile - // - fclose(f); - f = fopen(STATE_FILE_PREV, "r"); - mf.init_file(f); - fgets(buf, 256, f); - if (!match_tag(buf, "")) { - msg_printf(NULL, MSG_ERROR, "Missing open tag in state file.\n"); - retval = ERR_XML_PARSE; - goto done; - } - } while (fgets(buf, 256, f)) { if (match_tag(buf, "")) { - retval = 0; - goto done; + break; } else if (match_tag(buf, "")) { PROJECT temp_project; retval = temp_project.parse_state(mf); @@ -331,15 +336,8 @@ int CLIENT_STATE::parse_state_file() { } else if (parse_str(buf, "", newer_version)) { } else scope_messages.printf("CLIENT_STATE::parse_state_file: unrecognized: %s\n", buf); } - - // if get here, we must have reached end of state file - // without finding tag. - // - retval = ERR_XML_PARSE; -done: fclose(f); - - return retval; + return 0; }