Beispiel #1
0
unsigned int LoadSaveProblems(Client *client,
                              unsigned int load_problem_count,int mode)
{
  /* Some platforms need to stop asynchronously, for example, Win16 which
     gets an ENDSESSION message and has to exit then and there. So also
     win9x when running as a service where windows suspends all threads
     except the window thread. For these (and perhaps other platforms)
     we save our last state so calling with (0,0,0) will save the
     problem states (without hanging). see 'abortive_action' below.
  */
  static Client *previous_client = 0;
  static unsigned int previous_load_problem_count = 0, reentrant_count = 0;
  static int abortive_action = 0;

  unsigned int retval = 0;
  int changed_flag, first_time;

  int allclosed, prob_step,bufupd_pending;
  unsigned int cont_i, prob_for, prob_first, prob_last;
  unsigned int loaded_problems_count[CONTEST_COUNT];
  unsigned int saved_problems_count[CONTEST_COUNT];
  unsigned long totalBlocksDone; /* all contests */

  unsigned int total_problems_loaded, total_problems_saved;
  unsigned int norandom_count, getbuff_errs, empty_problems;

  allclosed = 0;
  norandom_count = getbuff_errs = empty_problems = 0;
  changed_flag = (previous_load_problem_count == 0);
  total_problems_loaded = 0;
  total_problems_saved = 0;
  bufupd_pending = 0;
  totalBlocksDone = 0;

  /* ============================================================= */

  if (abortive_action) /* already aborted once */
  {                    /* no probfill action can happen again */
    return 0;
  }
  if (!client)             /* abnormal end */
  {
    client = previous_client;
    if (!client)
      return 0;
    abortive_action = 1;
    mode = PROBFILL_UNLOADALL;
  }
  previous_client = client;
  if ((++reentrant_count) > 1)
  {
    --reentrant_count;
    return 0;
  }

  /* ============================================================= */

  prob_first = 0;
  prob_step  = 0;
  prob_last  = 0;
  first_time = 0;

  if (load_problem_count == 0) /* only permitted if unloading all */
  {
    if (mode != PROBFILL_UNLOADALL || previous_load_problem_count == 0)
    {
      --reentrant_count;
      return 0;
    }
    load_problem_count = previous_load_problem_count;
  }
  if (previous_load_problem_count == 0) /* must be initial load */
  {            /* [0 ... (load_problem_count - 1)] */
    prob_first = 0;
    prob_last  = (load_problem_count - 1);
    prob_step  = 1;
    first_time = 1;
  }
  else if (mode == PROBFILL_RESIZETABLE)
  {            /* [(previousload_problem_count-1) ... load_problem_count] */
    prob_first = load_problem_count;
    prob_last  = (previous_load_problem_count - 1);
    prob_step  = -1;
  }
  else /* PROBFILL_UNLOADALL, PROBFILL_REFRESH */
  {            /* [(load_problem_count - 1) ... 0] */
    prob_first = 0;
    prob_last  = (load_problem_count - 1);
    prob_step  = -1;
  }

  TRACE_BUFFUPD((+1, "LoadSaveProblems(%d)\n", mode));

  /* ============================================================= */

  for (cont_i = 0; cont_i < CONTEST_COUNT; cont_i++)
  {
    unsigned int blocksdone;
    if (CliGetContestInfoSummaryData( cont_i, &blocksdone, NULL, NULL, NULL, NULL )==0)
      totalBlocksDone += blocksdone;
    loaded_problems_count[cont_i] = 0;
    saved_problems_count[cont_i] = 0;
  }

  /* ============================================================= */

  ClientEventSyncPost(CLIEVENT_PROBLEM_TFILLSTARTED, &load_problem_count,
                                                sizeof(load_problem_count));

  for (prob_for = 0; prob_for <= (prob_last - prob_first); prob_for++)
  {
    Problem *thisprob;
    int load_needed;
    unsigned int prob_i = prob_for + prob_first;
    if ( prob_step < 0 )
      prob_i = prob_last - prob_for;

    thisprob = GetProblemPointerFromIndex( prob_i );
    if (thisprob == 0)
    {
      if (prob_step < 0)
        continue;
      break;
    }

    // -----------------------------------

    load_needed = 0;
    if (__IndividualProblemSave( thisprob, prob_i, client,
        &load_needed, load_problem_count, &cont_i, &bufupd_pending,
        (mode == PROBFILL_UNLOADALL || mode == PROBFILL_RESIZETABLE ),
        abortive_action ))
    {
      changed_flag = 1;
      total_problems_saved++;
      saved_problems_count[cont_i]++;
      totalBlocksDone++;
    }
    if (load_needed)
      empty_problems++;

    TRACE_BUFFUPD((0, "__IndividualProblemSave ==> bufupd_pending = %d\n", bufupd_pending));

    //---------------------------------------

    if (load_needed && mode!=PROBFILL_UNLOADALL && mode!=PROBFILL_RESIZETABLE)
    {
      // Bug #3672 (all clients running at least 2 cores).
      // Take the number of still active crunchers into account to determine
      // whether we can load another problem.

      // Bug #4018: It will not work for initial load: this 'if' will load
      // packet to LAST cruncher while main loop will start FIRST cruncher.
      // So here is a second 'if' for inital load (when mode==0), it will
      // load cruncher from start up to block count. (I wonder can old 'if'
      // be completely replaced with new one.)

      if (client->blockcount > 0)
      {
          if (mode == 0)
          {
              /* Load from beginning to up max. count, skip last crunchers */
              if (totalBlocksDone+total_problems_loaded >= (unsigned long)client->blockcount)
                  load_needed = 0;
          }
          else
          {
              /* Skip first crunchers, load from middle to last */
              if (totalBlocksDone+load_problem_count-empty_problems>=((unsigned long)(client->blockcount)))
                  load_needed = 0;
          }
      }
      if (load_needed)
      {
        load_needed = 0;
        if (__IndividualProblemLoad( thisprob, prob_i, client,
            &load_needed, load_problem_count, &cont_i, &bufupd_pending ))
        {
          empty_problems--;
          total_problems_loaded++;
          loaded_problems_count[cont_i]++;
          changed_flag = 1;
        }
        TRACE_BUFFUPD((0, "__IndividualProblemLoad ==> bufupd_pending = %d\n", bufupd_pending));
        if (load_needed)
        {
          getbuff_errs++;
          if (load_needed == NOLOAD_ALLCONTESTSCLOSED)
          {
            allclosed = 1;
            break; /* the for ... prob_i ... loop */
          }
          else if (load_needed == NOLOAD_NORANDOM)
            norandom_count++;
        }
      }
    } //if (load_needed)
  } //for (prob_i = 0; prob_i < load_problem_count; prob_i++ )

  ClientEventSyncPost(CLIEVENT_PROBLEM_TFILLFINISHED,
     ((previous_load_problem_count==0)?(&total_problems_loaded):(&total_problems_saved)),
     sizeof(total_problems_loaded));

  /* ============================================================= */

  if (mode == PROBFILL_UNLOADALL)
  {
    previous_load_problem_count = 0;
    if (client->nodiskbuffers == 0)
    {
      // close checkpoint file immediately after saving the problems to disk
      CheckpointAction( client, CHECKPOINT_CLOSE, 0 );
    }
    else if (!CheckRestartRequestTrigger()) /* no disk buffers */
    {
      TRACE_BUFFUPD((0, "BufferUpdate: reason = LoadSaveProblem && unload all && membuffers\n"));
      BufferUpdate(client,BUFFERUPDATE_FLUSH,0);
      /* in case the flush fails, empty the membuf table manually */
      for (cont_i = 0; cont_i < CONTEST_COUNT; cont_i++)
      {
        WorkRecord data;
        while (GetBufferCount(client, cont_i, 0, 0)>0)
          GetBufferRecord( client, &data, cont_i, 0 );
        while (GetBufferCount(client, cont_i, 0, 0)>0)
          GetBufferRecord( client, &data, cont_i, 1);
      }
    }
    retval = total_problems_saved;
  }
  else /* if (mode != PROBFILL_UNLOADALL) */
  {
    /*
    =============================================================
    // save the number of active problems, so that we can bail out
    // in an "emergency". Some platforms call us asynchronously when they
    // need to abort [win16/win32 for example]
    -------------------------------------------------------------
    */

    previous_load_problem_count = load_problem_count;

    if (bufupd_pending && client->blockcount >= 0)
    {
      int req = MODEREQ_FLUSH; // always flush while fetching
      if (!CheckExitRequestTriggerNoIO()) //((bufupd_pending & BUFFERUPDATE_FETCH)!=0)
        req |= MODEREQ_FETCH;
      TRACE_BUFFUPD((0, "ModeReqSet(flush=%d, fetch=%d, fquiet=1)\n",
                        (req & MODEREQ_FLUSH) != 0, (req & MODEREQ_FETCH) != 0));
      ModeReqSet( req|MODEREQ_FQUIET ); /* delegate to the client.run loop */
    }

    if (!allclosed && mode != PROBFILL_RESIZETABLE)
    {
      /*
       =============================================================
       if we are running a limited number of blocks then check if we have
       exceeded that number. If we have, but one or more crunchers are
       still at work, bump the limit.
       -------------------------------------------------------------
      */
      if (client->blockcount < 0 || (client->blockcount > 0
                  && totalBlocksDone >= (unsigned long)(client->blockcount)))
      {
        if (empty_problems >= load_problem_count)
        {
          Log( "Shutdown - packet limit exceeded.\n" );
          RaiseExitRequestTrigger();
        }
        // Bug #3672 (all clients running at least 2 cores).
        // The following two lines prevent the client from stopping as
        // instructed by option "-n" when running at least two crunchers
        // simultaneously.
        //else
        //  client->blockcount = ((u32)(totalBlocksDone))+1;
      }
    }

    if (mode == PROBFILL_RESIZETABLE)
      retval = total_problems_saved;
    else if (mode == PROBFILL_GETBUFFERRS)
      retval = getbuff_errs;
    else if (mode == PROBFILL_ANYCHANGED)
      retval = changed_flag;
    else
      retval = total_problems_loaded;
  }

  /* ============================================================= */

  for ( cont_i = 0; cont_i < CONTEST_COUNT; cont_i++) //once for each contest
  {
    int show_totals = 0;
    if (loaded_problems_count[cont_i] || saved_problems_count[cont_i])
      show_totals = 1;

    if (first_time || show_totals)
    {
      unsigned int inout;
      const char *cont_name = CliGetContestNameFromID(cont_i);

      if (loaded_problems_count[cont_i] && load_problem_count > COMBINEMSG_THRESHOLD )
      {
        Log( "%s: Loaded %u packet%s from %s\n",
              cont_name, loaded_problems_count[cont_i],
              ((loaded_problems_count[cont_i]==1)?(""):("s")),
              (client->nodiskbuffers ? "(memory-in)" :
              BufferGetDefaultFilename( cont_i, 0,
                                        client->in_buffer_basename )) );
      }

      if (saved_problems_count[cont_i] && load_problem_count > COMBINEMSG_THRESHOLD
       && (client->nodiskbuffers == 0 || (mode != PROBFILL_UNLOADALL)))
      {
        Log( "%s: Saved %u packet%s to %s\n",
              cont_name, saved_problems_count[cont_i],
              ((saved_problems_count[cont_i]==1)?(""):("s")),
              (mode == PROBFILL_UNLOADALL)?
                (client->nodiskbuffers ? "(memory-in)" :
                BufferGetDefaultFilename( cont_i, 0,
                                          client->in_buffer_basename ) ) :
                (client->nodiskbuffers ? "(memory-out)" :
                BufferGetDefaultFilename( cont_i, 1,
                                          client->out_buffer_basename )) );
      }

      if (show_totals && totalBlocksDone > 0)
      {
        // To suppress "odd" problem completion count summaries (and not be
        // quite so verbose) we only display summaries if the number of
        // completed problems is even divisible by the number of processors.
        // Requires a working GetNumberOfDetectedProcessors() [cpucheck.cpp]
        #if 0
        int cpustmp; unsigned int cpus = 1;
        if ((cpustmp = GetNumberOfDetectedProcessors()) > 1)
          cpus = (unsigned int)cpustmp;
        if (load_problem_count > cpus)
          cpus = load_problem_count;
        if ((totalBlocksDone%cpus) == 0 )
        #endif
        {
          __post_summary_for_contest(cont_i);
        }
      }

      /* -------------------------------------------------------------- */

      for (inout=0;inout<=1;inout++)
      {
        unsigned long stats_count;
        long block_count = GetBufferCount( client, cont_i, inout, &stats_count );

        if (show_totals && block_count >= 0) /* no error */
        {
          char buffer[(3*80)+sizeof(client->in_buffer_basename)];
          int len;

          len = sprintf(buffer, "%s: %ld packet%s ",
                cont_name, block_count, ((block_count == 1)?(""):("s")) );
          if (stats_count)
            len += sprintf( &buffer[len], "(%lu.%02lu stats units) ",
                            stats_count/100,stats_count%100);
          len += sprintf( &buffer[len], "%s in\n%s",
              ((inout!= 0 || mode == PROBFILL_UNLOADALL)?
                 ((block_count==1)?("is"):("are")):
                 ((block_count==1)?("remains"):("remain"))),
              ((inout== 0)?
                  (client->nodiskbuffers ? "(memory-in)" :
                   BufferGetDefaultFilename( cont_i, 0,
                   client->in_buffer_basename ) ) :
                   (client->nodiskbuffers ? "(memory-out)":
                   BufferGetDefaultFilename( cont_i, 1,
                   client->out_buffer_basename ) ))
             );
          if (len < 55) /* fits on a single line, so unwrap */
          {
            char *nl = strrchr( buffer, '\n' );
            if (nl) *nl = ' ';
          }
          if (inout != 0) /* out-buffer */
          {
            /* adjust bufupd_pending if outthresh has been crossed */
            /* we don't check in-buffer here since we need cumulative count */
            if (__check_outbufthresh_limit( client, cont_i, block_count,
                                            stats_count, &bufupd_pending ))
            {
              //Log("5. bufupd_pending |= BUFFERUPDATE_FLUSH;\n");
            }
          }
          else /*in*/ if (stats_count && (mode!=PROBFILL_UNLOADALL))
          {
            timeval tv;
            tv.tv_sec = __get_thresh_secs(client, cont_i, 0, stats_count, 0 );
            if (tv.tv_sec > 0)
            {
              tv.tv_usec = 0;
              len += sprintf(&buffer[len],
                       "\nProjected ideal time to completion: %s",
                       CliGetTimeString( &tv, 2));
            }
          }
          Log( "%s\n", buffer );
        } //if (block_count >= 0)

      } //  for (inout=0;inout<=1;inout++)
    } //if (loaded_problems_count[cont_i] || saved_problems_count[cont_i])
  } //for ( cont_i = 0; cont_i < CONTEST_COUNT; cont_i++)

  /* ============================================================ */

  if (mode == PROBFILL_UNLOADALL)
  {
    previous_load_problem_count = 0;
    previous_client = (Client *)0;
    if (!CheckRestartRequestTrigger())
      Log("Shutdown complete.\n");
  }
  --reentrant_count;

  TRACE_BUFFUPD((-1, "LoadSaveProblems => %d\n", retval));

  return retval;
}
Beispiel #2
0
int ModeReqRun(Client *client)
{
  int retval = 0;

  /* This exits if we don't see a CPU we want,
     Also saves us from floating point exceptions on GPU clients 
  */
  if ((modereq.reqbits & MODEREQ_NEEDS_CPU_MASK) != 0)
  {
    if (GetNumberOfDetectedProcessors() == 0)  // -1 is OK when OS doesn't support detection
      return 0;
  }

  if (++modereq.isrunning == 1)
  {
    int restart = ((modereq.reqbits & MODEREQ_RESTART) != 0);
    modereq.reqbits &= ~MODEREQ_RESTART;

    while ((modereq.reqbits & MODEREQ_ALL)!=0)
    {
      unsigned int bits = modereq.reqbits;
      if ((bits & (MODEREQ_BENCHMARK |
                   MODEREQ_BENCHMARK_QUICK |
                   MODEREQ_BENCHMARK_ALLCORE )) != 0)
      {
        do
        {
          unsigned int contest, benchsecs = 16;
          unsigned long sel_contests = modereq.bench_projbits;
          modereq.bench_projbits = 0;

          if ((bits & (MODEREQ_BENCHMARK_QUICK))!=0)
            benchsecs = 8;
          for (contest = 0; contest < CONTEST_COUNT; contest++)
          {
            if (CheckExitRequestTriggerNoIO())
              break;
            if (sel_contests == 0 /*none set==all set*/
                || (sel_contests & (1L<<contest)) != 0)
            {
              if ((bits & (MODEREQ_BENCHMARK_ALLCORE))!=0)
                if(client->corenumtotestbench < 0)
                  selcoreBenchmark( client, contest, benchsecs, -1 );
                else
                  selcoreBenchmark( client, contest, benchsecs, client->corenumtotestbench);
              else
                TBenchmark( client, contest, benchsecs, 0, NULL, NULL );
            }
          }
          Log("Compare and share your rates in the speeds database at\n"
              "http://www.distributed.net/speed/\n"
              "(benchmark rates are for a single processor core)\n");
        } while (!CheckExitRequestTriggerNoIO() && modereq.bench_projbits);
        retval |= (bits & (MODEREQ_BENCHMARK_QUICK | MODEREQ_BENCHMARK |
                           MODEREQ_BENCHMARK_ALLCORE));
        modereq.reqbits &= ~(MODEREQ_BENCHMARK_QUICK | MODEREQ_BENCHMARK |
                             MODEREQ_BENCHMARK_ALLCORE);
      }
      if ((bits & MODEREQ_CMDLINE_HELP) != 0)
      {
        DisplayHelp(modereq.helpoption);
        modereq.helpoption = (const char *)0;
        modereq.reqbits &= ~(MODEREQ_CMDLINE_HELP);
        retval |= (MODEREQ_CMDLINE_HELP);
      }
      if ((bits & (MODEREQ_CONFIG | MODEREQ_CONFRESTART)) != 0)
      {
        /* cmdline_config is set if there is an explicit --config on the cmdline */
        /* Configure() returns <0=error,0=exit+nosave,>0=exit+save */
        Configure(client,(!(!modereq.cmdline_config)) /* nottycheck */);
        /* it used to be such that restart would only be posted on an exit+save */
        /* but now we restart for other retvals too, otherwise the GUI windows */
        /* end up with half-assed content */
        if ((bits & MODEREQ_CONFRESTART) != 0)
          restart = 1;
        modereq.cmdline_config = 0;
        modereq.reqbits &= ~(MODEREQ_CONFIG | MODEREQ_CONFRESTART);
        retval |= (bits & (MODEREQ_CONFIG | MODEREQ_CONFRESTART));
      }
      if ((bits & (MODEREQ_FETCH | MODEREQ_FLUSH)) != 0)
      {
        if (client)
        {
          int domode = 0;
          int interactive = ((bits & MODEREQ_FQUIET) == 0);
          domode  = ((bits & MODEREQ_FETCH) ? BUFFERUPDATE_FETCH : 0);
          domode |= ((bits & MODEREQ_FLUSH) ? BUFFERUPDATE_FLUSH : 0);
          TRACE_BUFFUPD((0, "BufferUpdate: reason = ModeReqRun\n"));
          domode = BufferUpdate( client, domode, interactive );
          if (domode & BUFFERUPDATE_FETCH)
            retval |= MODEREQ_FETCH;
          if (domode & BUFFERUPDATE_FLUSH)
            retval |= MODEREQ_FLUSH;
          if (domode!=0 && (bits & MODEREQ_FQUIET) != 0)
            retval |= MODEREQ_FQUIET;
        }
        modereq.reqbits &= ~(MODEREQ_FETCH | MODEREQ_FLUSH | MODEREQ_FQUIET);
      }
      if ((bits & MODEREQ_IDENT) != 0)
      {
        CliIdentifyModules();
        modereq.reqbits &= ~(MODEREQ_IDENT);
        retval |= (MODEREQ_IDENT);
      }
      if ((bits & MODEREQ_UNLOCK) != 0)
      {
        if (modereq.filetounlock)
        {
          UnlockBuffer(modereq.filetounlock);
          modereq.filetounlock = (const char *)0;
        }
        modereq.reqbits &= ~(MODEREQ_UNLOCK);
        retval |= (MODEREQ_UNLOCK);
      }
      if ((bits & MODEREQ_IMPORT) != 0)
      {
        if (modereq.filetoimport && client)
        {
          BufferImportFileRecords(client, modereq.filetoimport, 1 /* interactive */);
          modereq.filetoimport = (const char *)0;
          retval |= (MODEREQ_IMPORT);
        }
        modereq.reqbits &= ~(MODEREQ_IMPORT);
      }
      if ((bits & MODEREQ_CPUINFO) != 0)
      {
        DisplayProcessorInformation();
        modereq.reqbits &= ~(MODEREQ_CPUINFO);
        retval |= (MODEREQ_CPUINFO);
      }
      if ((bits & (MODEREQ_TEST | MODEREQ_TEST_ALLCORE)) != 0)
      {

        int testfailed = 0;
        do
        {
          unsigned int contest;
          unsigned long sel_contests = modereq.test_projbits;
          modereq.test_projbits = 0;

          for (contest = 0; !testfailed && contest < CONTEST_COUNT; contest++)
          {
            if (CheckExitRequestTriggerNoIO())
            {
              testfailed = 1;
              break;
            }
            if (sel_contests == 0 /*none set==all set*/
                || (sel_contests & (1L<<contest)) != 0)
            {
              if ((bits & (MODEREQ_TEST_ALLCORE)) != 0)
              {
                if (client->corenumtotestbench < 0)
                {
                  if (selcoreSelfTest( client, contest, -1 ) < 0)
                    testfailed = 1;
                }
                else
                {
                  if (selcoreSelfTest( client, contest, client->corenumtotestbench ) < 0)
                    testfailed = 1;
                }
              }
              else if ( SelfTest( client, contest ) < 0 )
                testfailed = 1;
            }
          }
        } while (!testfailed && modereq.test_projbits);
        retval |= (MODEREQ_TEST|MODEREQ_TEST_ALLCORE);
        modereq.reqbits &= ~(MODEREQ_TEST|MODEREQ_TEST_ALLCORE);
      }
      if ((bits & (MODEREQ_STRESS | MODEREQ_STRESS_ALLCORE)) != 0)
      {

        int testfailed = 0;
        do
        {
          unsigned int contest;
          unsigned long sel_contests = modereq.stress_projbits;
          modereq.stress_projbits = 0;

          for (contest = 0; !testfailed && contest < CONTEST_COUNT; contest++)
          {
            if (CheckExitRequestTriggerNoIO())
            {
              testfailed = 1;
              break;
            }
            if (sel_contests == 0 /*none set==all set*/
                || (sel_contests & (1L<<contest)) != 0)
            {
              if ((bits & (MODEREQ_STRESS_ALLCORE)) != 0)
              {
                if (client->corenumtotestbench < 0)
                {
                  if (selcoreStressTest( client, contest, -1 ) < 0)
                    testfailed = 1;
                }
                else
                {
                  if (selcoreStressTest( client, contest, client->corenumtotestbench ) < 0)
                    testfailed = 1;
                }
              }
              else if ( StressTest( client, contest ) < 0 )
                testfailed = 1;
            }
          }
        } while (!testfailed && modereq.stress_projbits);
        retval |= (MODEREQ_STRESS|MODEREQ_STRESS_ALLCORE);
        modereq.reqbits &= ~(MODEREQ_STRESS|MODEREQ_STRESS_ALLCORE);
      }
      if ((bits & MODEREQ_VERSION) != 0)
      {
        /* the requested information already has been printed */
        modereq.reqbits &= ~(MODEREQ_VERSION);
        retval |= (MODEREQ_VERSION);
      }
      if (CheckExitRequestTriggerNoIO())
      {
        restart = 0;
        break;
      }
    } //end while

    if (restart)
      RaiseRestartRequestTrigger();
  } //if (++isrunning == 1)

  modereq.isrunning--;
  return retval;
}
Beispiel #3
0
static unsigned int __IndividualProblemLoad( Problem *thisprob,
                    unsigned int prob_i, Client *client, int *load_needed,
                    unsigned load_problem_count,
                    unsigned int *loaded_for_contest,
                    int *bufupd_pending )
{
  unsigned int did_load = 0;
  int retry_due_to_failed_loadstate = 0;

  TRACE_OUT((+1, "__IndivProbLoad()\n"));

  do /* while (retry_due_to_failed_loadstate) */
  {
    TRACE_OUT((0, "do /* while (retry_due_to_failed_loadstate) */\n"));
    WorkRecord wrdata;
    int update_on_current_contest_exhaust_flag = (client->connectoften & 4);
    long bufcount;
    int may_do_random_blocks, random_project = -1, proj_i;
    struct timeval tv;

    may_do_random_blocks = 0;
    for (proj_i = 0; proj_i < PROJECT_COUNT; ++proj_i)
    {
      int projectid = client->project_order_map[proj_i];
      if ((ProjectGetFlags(projectid) & PROJECTFLAG_RANDOM_BLOCKS) &&
          ((client->project_state[projectid] &
              (PROJECTSTATE_USER_DISABLED | PROJECTSTATE_CLOSED)) == 0))
      {
        may_do_random_blocks = 1;
        random_project = projectid;
        break;
      }
    }

    if (!may_do_random_blocks && client->last_buffupd_failed_time != 0
                              && CliClock(&tv) == 0)
    {
      // If no random work is allowed and if buffer updates are temporarily
      // disabled (retry delay not elapsed), then exit early to prevent the
      // client from doing unecessary file I/O operations until updates are
      // enabled.
      if (!tv.tv_sec)
        tv.tv_sec++;
      if (client->last_buffupd_failed_time + client->buffupd_retry_delay > tv.tv_sec) {
        *load_needed = NOLOAD_NORANDOM;
        return 0;   /* Retry delay not elapsed : did nothing */
      }
    }  

    retry_due_to_failed_loadstate = 0;
    bufcount = __loadapacket( client, &wrdata, 1, prob_i,
                              update_on_current_contest_exhaust_flag );

    if (bufcount < 0 && client->nonewblocks == 0)
    {
      if (CheckExitRequestTriggerNoIO())
        break;
      //Log("3. BufferUpdate(client,(BUFFERUPDATE_FETCH|BUFFERUPDATE_FLUSH),0)\n");
      TRACE_BUFFUPD((0, "BufferUpdate: reason = __IndividualProblemLoad && no more blocks\n"));
      int didupdate =
         BufferUpdate(client,(BUFFERUPDATE_FETCH|BUFFERUPDATE_FLUSH),0);
      if (CheckExitRequestTriggerNoIO())
        break;
      if (!(didupdate < 0))
      {
        if (didupdate!=0)
          *bufupd_pending&=~(didupdate&(BUFFERUPDATE_FLUSH|BUFFERUPDATE_FETCH));
        if ((didupdate & BUFFERUPDATE_FETCH) != 0) /* fetched successfully */
          bufcount = __loadapacket( client, &wrdata, 0, prob_i,
                                    update_on_current_contest_exhaust_flag );
      }
    }

    *load_needed = 0;
    if (bufcount >= 0) /* load from file suceeded */
      *load_needed = 0;
    else if (!may_do_random_blocks || client->blockcount < 0)
      *load_needed = NOLOAD_NORANDOM; /* -1 */
    else if (client->nonewblocks)
      *load_needed = NOLOAD_NONEWBLOCKS;
    else  /* using randoms is permitted */
      *load_needed = 0;

    TRACE_OUT((0, "bufcount = %ld, load_needed = %d, may_do_randoms = %d\n", bufcount, *load_needed, may_do_random_blocks));
    TRACE_BUFFUPD((0, "__Indiv...Load: bufcount = %ld, load_needed = %d\n", bufcount, *load_needed));
    if (*load_needed == 0)
    {
      u32 timeslice = 0x10000;
      int expected_cpu = 0, expected_core = 0;
      int expected_os  = 0, expected_build = 0;
      const ContestWork *work = &wrdata.work;
      int res = -1;

      #if (defined(INIT_TIMESLICE) && (INIT_TIMESLICE >= 64))
      timeslice = INIT_TIMESLICE;
      #endif

      if (bufcount < 0) /* normal load from buffer failed */
      {                 /* so generate random */
        work = CONTESTWORK_MAGIC_RANDOM;
        *loaded_for_contest = random_project;
      }
      else
      {
        *loaded_for_contest = (unsigned int)(wrdata.contest);
        // If a user gets a packet already started by another user,
        // force a restart to occur (may happen when the input buffer
        // is shared).
        if (strcmp(wrdata.id, "*****@*****.**") == 0
            || strncmp(wrdata.id, client->id, sizeof(wrdata.id)-1) == 0)
        {
          expected_cpu   = wrdata.cpu;
          expected_core  = wrdata.core;
          expected_os    = wrdata.os;
          expected_build = wrdata.build;
        }
        work = &wrdata.work;

        /* if the total number of packets in buffers is less than the number
           of crunchers running then post a fetch request. This means that the
           effective minimum threshold is always >= num crunchers
        */
        if (((unsigned long)(bufcount)) < (load_problem_count - prob_i))
        {
          *bufupd_pending |= BUFFERUPDATE_FETCH;
        }
      }

      /* loadstate can fail if it selcore fails or the previous problem */
      /* hadn't been purged, or the contest isn't available or ... */

      res = ProblemLoadState( thisprob, work, *loaded_for_contest, timeslice,
                    expected_cpu, expected_core, expected_os, expected_build, client );

      if (res != 0)
      {
        /* The problem with LoadState() failing is that it implicitely
        ** causes the block to be discarded, which means, that the
        ** keyserver network will reissue it - a senseless undertaking
        ** if the data itself is invalid.
        */
        if (res != -2)
        {
          retry_due_to_failed_loadstate = 1;
        }
        else
        {
          // should never happen
          Log("Serious ProblemLoadState() error! Aborting!\n");
          RaiseExitRequestTrigger();
        }
      }
      else
      {
        *load_needed = 0;
        did_load = 1;

        ClientEventSyncPost( CLIEVENT_PROBLEM_STARTED, &prob_i, sizeof(prob_i) );

        if (load_problem_count <= COMBINEMSG_THRESHOLD)
        {
          ProblemInfo info;
          if (ProblemGetInfo( thisprob, &info, P_INFO_S_PERMIL | P_INFO_SIGBUF   |
                                               P_INFO_DCOUNT   | P_INFO_EXACT_PE ) != -1)
          {
            const char *extramsg = "";
            char ddonebuf[15];
            char perdone[32];

            *loaded_for_contest = thisprob->pub_data.contest;
            if (thisprob->pub_data.was_reset)
              extramsg="\nPacket was from a different user/core/client cpu/os/build.";
            else if (info.s_permille > 0 && info.s_permille < 1000)
            {
              sprintf(perdone, " (%u.%u0%% done)", (info.s_permille/10), (info.s_permille%10));
              extramsg = perdone;
            }
            else if (info.dcounthi || info.dcountlo)
            {
              strcat( strcat( strcpy(perdone, " ("), U64stringify(ddonebuf, sizeof(ddonebuf),
                                                                  info.dcounthi, info.dcountlo,
                                                                  2, info.unit)),
                                                     " done)");
              extramsg = perdone;
            }

            if (load_problem_count > 1) {
              Log("%s #%c: Loaded %s%s%s\n", info.name, ProblemLetterId(prob_i),
                      ((thisprob->pub_data.is_random)?("random "):("")),
                      info.sigbuf, extramsg );
            }
            else {
              Log("%s: Loaded %s%s%s\n", info.name,
                      ((thisprob->pub_data.is_random)?("random "):("")),
                      info.sigbuf, extramsg );
            }
          } /* if (thisprob->GetProblemInfo(...) != -1) */
        } /* if (load_problem_count <= COMBINEMSG_THRESHOLD) */
      } /* if (LoadState(...) != -1) */
    } /* if (*load_needed == 0) */
  } while (retry_due_to_failed_loadstate);

  TRACE_OUT((-1, "__IndivProbLoad() => %d\n", did_load));
  return did_load;
}