| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275 |
- --- a/FPGA-README
- +++ b/FPGA-README
- @@ -16,7 +16,25 @@
-
- Icarus
-
- -There is a hidden option in cgminer when Icarus support is compiled in:
- +There are two hidden options in cgminer when Icarus support is compiled in:
- +
- +--icarus-options <arg> Set specific FPGA board configurations - one set of values for all or comma separated
- + baud:work_division:fpga_count
- +
- + baud The Serial/USB baud rate - 115200 or 57600 only - default 115200
- + work_division The fraction of work divided up for each FPGA chip - 1, 2, 4 or 8
- + e.g. 2 means each FPGA does half the nonce range - default 2
- + fpga_count The actual number of FPGA working - this would normally be the same
- + as work_division - range is from 1 up to 'work_division'
- + It defaults to the value of work_division - or 2 if you don't specify
- + work_division
- +
- +If you define fewer comma seperated values than Icarus devices, the last values will be used
- +for all extra devices
- +
- +An example would be: --icarus-options 57600:2:1
- +This would mean: use 57600 baud, the FPGA board divides the work in half however
- +only 1 FPGA actually runs on the board (e.g. like an early CM1 Icarus copy bitstream)
-
- --icarus-timing <arg> Set how the Icarus timing is calculated - one setting/value for all or comma separated
- default[=N] Use the default Icarus hash time (2.6316ns)
- @@ -24,6 +42,9 @@
- long Re-calculate the hash time continuously
- value[=N] Specify the hash time in nanoseconds (e.g. 2.6316) and abort time (e.g. 2.6316=80)
-
- +If you define fewer comma seperated values than Icarus devices, the last values will be used
- +for all extra devices
- +
- Icarus timing is required for devices that do not exactly match a default Icarus Rev3 in
- processing speed
- If you have an Icarus Rev3 you should not normally need to use --icarus-timing since the
- @@ -55,9 +76,9 @@
- 'short' mode and take note of the final hash time value (Hs) calculated
- You can also use the RPC API 'stats' command to see the current hash time (Hs) at any time
-
- -The Icarus code currently only works with a dual FPGA device that supports the same commands as
- +The Icarus code currently only works with an FPGA device that supports the same commands as
- Icarus Rev3 requires and also is less than ~840MH/s and greater than 2MH/s
- -If a dual FPGA device does hash faster than ~840MH/s it should work correctly if you supply the
- +If an FPGA device does hash faster than ~840MH/s it should work correctly if you supply the
- correct hash time nanoseconds value
-
- The timing code itself will affect the Icarus performance since it increases the delay after
- --- a/NEWS
- +++ b/NEWS
- @@ -1,7 +1,42 @@
- +Version 2.6.2 - August 3, 2012
- +
- +- Scrypt mining does not support block testing yet so don't try to print it.
- +- Clear the bitforce buffer whenever we get an unexpected result as it has
- +likely throttled and we are getting cached responses out of order, and use the
- +temperature monitoring as a kind of watchdog to flush unexpected results.
- +- It is not critical getting the temperature response in bitforce so don't
- +mandatorily wait on the mutex lock.
- +- Check there is a cutoff temp actually set in bitforce before using it as a cut
- +off value otherwise it may think it's set to zero degrees.
- +- We dropped the temporary stopping of curl recruiting on submit_fail by
- +mistake, reinstate it.
- +- Make threads report in either side of the scanhash function in case we miss
- +reporting in when restarting work.
- +- Don't make mandatory work and its clones last forever.
- +- Make test work for pool_active mandatory work items to smooth out staged work
- +counts when in failover-only mode.
- +- Add debugging output when work is found stale as to why.
- +- Print the 3 parameters that are passed to applog for a debug line in
- +bitforce.c
- +- Clear bitforce buffer on init as previously.
- +- Add some headroom to the number of curls available per pool to allow for
- +longpoll and sendwork curls.
- +- Revert "Revert "Change BFL driver thread initialising to a constant 100ms
- +delay between devices instead of a random arrangement.""
- +- Revert "Remove bitforce_thread_init"
- +- Show the correct base units on GPU summary.
- +- Differentiate between the send return value being a bool and the get return
- +value when managing them in bitforce scanhash.
- +- 23a8c60 Revert "bitforce: Skip out of sending work if work restart requested"
- +
- +
- Version 2.6.1 - July 30, 2012
-
- +- Display scrypt as being built in as well.
- +- Fix build warning about KL_SCRYPT when built without scrypt support.
- - Remove the low hash count determinant of hardware being sick. A low hash rate
- -can be for poor network connectivity or scrypt mining, neither of which a
- +can be for poor network connectivity or scrypt mining, neither of which are due
- +to a sick device.
- - api.c poolpriority changes
-
-
- --- a/cgminer.c
- +++ b/cgminer.c
- @@ -142,6 +142,7 @@
- bool opt_api_network;
- bool opt_delaynet;
- bool opt_disable_pool = true;
- +char *opt_icarus_options = NULL;
- char *opt_icarus_timing = NULL;
-
- char *opt_kernel_path;
- @@ -710,6 +711,13 @@
- }
-
- #ifdef USE_ICARUS
- +static char *set_icarus_options(const char *arg)
- +{
- + opt_set_charp(arg, &opt_icarus_options);
- +
- + return NULL;
- +}
- +
- static char *set_icarus_timing(const char *arg)
- {
- opt_set_charp(arg, &opt_icarus_timing);
- @@ -873,6 +881,9 @@
- "Override sha256 kernel to use (diablo, poclbm, phatk or diakgcn) - one value or comma separated"),
- #endif
- #ifdef USE_ICARUS
- + OPT_WITH_ARG("--icarus-options",
- + set_icarus_options, NULL, NULL,
- + opt_hidden),
- OPT_WITH_ARG("--icarus-timing",
- set_icarus_timing, NULL, NULL,
- opt_hidden),
- @@ -1770,10 +1781,9 @@
-
- if (!QUIET) {
- hash32 = (uint32_t *)(work->hash);
- - if (opt_scrypt) {
- - sprintf(hashshow, "%08lx.%08lx%s", (unsigned long)(hash32[7]), (unsigned long)(hash32[6]),
- - work->block? " BLOCK!" : "");
- - } else {
- + if (opt_scrypt)
- + sprintf(hashshow, "%08lx.%08lx", (unsigned long)(hash32[7]), (unsigned long)(hash32[6]));
- + else {
- sprintf(hashshow, "%08lx.%08lx%s", (unsigned long)(hash32[6]), (unsigned long)(hash32[5]),
- work->block? " BLOCK!" : "");
- }
- @@ -2169,14 +2179,14 @@
- * network delays/outages. */
- static struct curl_ent *pop_curl_entry(struct pool *pool)
- {
- - int curl_limit = opt_delaynet ? 5 : mining_threads;
- + int curl_limit = opt_delaynet ? 5 : mining_threads * 4 / 3;
- struct curl_ent *ce;
-
- mutex_lock(&pool->pool_lock);
- if (!pool->curls)
- recruit_curl(pool);
- else if (list_empty(&pool->curlring)) {
- - if (pool->curls >= curl_limit)
- + if (pool->submit_fail || pool->curls >= curl_limit)
- pthread_cond_wait(&pool->cr_cond, &pool->pool_lock);
- else
- recruit_curl(pool);
- @@ -2278,9 +2288,6 @@
- struct pool *pool;
- int getwork_delay;
-
- - if (work->mandatory)
- - return false;
- -
- if (share) {
- /* Technically the rolltime should be correct but some pools
- * advertise a broken expire= that is lower than a meaningful
- @@ -2306,14 +2313,20 @@
- work_expiry = 5;
-
- gettimeofday(&now, NULL);
- - if ((now.tv_sec - work->tv_staged.tv_sec) >= work_expiry)
- + if ((now.tv_sec - work->tv_staged.tv_sec) >= work_expiry) {
- + applog(LOG_DEBUG, "Work stale due to expiry");
- return true;
- + }
-
- - if (work->work_block != work_block)
- + if (work->work_block != work_block) {
- + applog(LOG_DEBUG, "Work stale due to block mismatch");
- return true;
- + }
-
- - if (opt_fail_only && !share && pool != current_pool() && pool->enabled != POOL_REJECTING)
- + if (opt_fail_only && !share && pool != current_pool() && !work->mandatory) {
- + applog(LOG_DEBUG, "Work stale due to fail only pool mismatch");
- return true;
- + }
-
- return false;
- }
- @@ -3011,6 +3024,8 @@
- fprintf(fcfg, ",\n\"api-description\" : \"%s\"", opt_api_description);
- if (opt_api_groups)
- fprintf(fcfg, ",\n\"api-groups\" : \"%s\"", opt_api_groups);
- + if (opt_icarus_options)
- + fprintf(fcfg, ",\n\"icarus-options\" : \"%s\"", opt_icarus_options);
- if (opt_icarus_timing)
- fprintf(fcfg, ",\n\"icarus-timing\" : \"%s\"", opt_icarus_timing);
- fputs("\n}", fcfg);
- @@ -3584,6 +3599,7 @@
- struct work *work = make_work();
- bool rc;
-
- + work->mandatory = true;
- rc = work_decode(json_object_get(val, "result"), work);
- if (rc) {
- applog(LOG_DEBUG, "Successfully retrieved and deciphered work from pool %u %s",
- @@ -3835,6 +3851,7 @@
- memcpy(work_clone, work, sizeof(struct work));
- work_clone->clone = true;
- work_clone->longpoll = false;
- + work_clone->mandatory = false;
- /* Make cloned work appear slightly older to bias towards keeping the
- * master work item which can be further rolled */
- work_clone->tv_staged.tv_sec -= 1;
- @@ -4192,7 +4209,9 @@
- }
- pool_stats->getwork_calls++;
-
- + thread_reportin(mythr);
- hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce);
- + thread_reportin(mythr);
-
- gettimeofday(&getwork_start, NULL);
-
- --- a/configure.ac
- +++ b/configure.ac
- @@ -2,7 +2,7 @@
- ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
- m4_define([v_maj], [2])
- m4_define([v_min], [6])
- -m4_define([v_mic], [1])
- +m4_define([v_mic], [2])
- ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
- m4_define([v_ver], [v_maj.v_min.v_mic])
- m4_define([lt_rev], m4_eval(v_maj + v_min))
- --- a/debian/changelog
- +++ b/debian/changelog
- @@ -1,112 +1,151 @@
- +cgminer (2.4.3-1) stable; urgency=medium
- + Version 2.4.3 - June 14, 2012
- +
- + * can_roll and should_roll should have no bearing on the cycle period within the
- + miner_thread so remove it.
- + * Check for strategy being changed to load balance when enabling LPs.
- + * Check that all threads on the device that called get_work are waiting on getwork
- + before considering the pool lagging.
- + * Iterate over each thread belonging to each device in the hashmeter instead of
- + searching for them now that they're a list.
- + * When using rotate pool strategy, ensure we only select from alive enabled pools.
- + * Start longpoll from every pool when load balance strategy is in use.
- + * Add mandatory and block fields to the work struct. Flag any shares that are
- + detected as blocks as mandatory to submit, along with longpoll work from a previously
- + rejecting pool.
- + * Consider the fan optimal if fanspeed is dropping but within the optimal speed window.
- + * Fix typo in some API messages (succeess/success)
- + * api.c MMQ stat bugs
- + * Bugfix: Fix warnings when built without libudev support
- + * Bugfix: slay a variety of warnings
- + * Bugfix: modminer: Fix unsigned/signed comparison and similar warnings
- + * API add ModMinerQuad support
- + * Bugfix: Honour forceauto parameter in serial_detect functions
- + * modminer: Temperature sensor improvements
- + * modminer: Make log messages more consistent in format
- + * Only adjust GPU speed up if the fanspeed is within the normal fanrange and hasn't been
- + turned to maximum speed under overheat conditions.
- + * ModMiner use valid .name
- + * New driver: BTCFPGA ModMiner
- + * Abstract generally useful FPGA code into fpgautils.c
- + * API add stats for pool getworks
- + * miner.php option to hide specific fields from the display
- + * miner.php add version numbers to the summary page
- + * Update debian configs to v2.4.2
- + * Add API and FPGA READMEs into Makefile to be included in source distribution.
- + * Icarus - fix unit64_t printf warnings
- +
- + -- nushor <nushor11@gmail.com> Fri, 15 Jun 2012 11:31:51 -0500
- +
- cgminer (2.4.2-1) stable; urgency=medium
- Version 2.4.2 - June 2, 2012
-
- - - API.class compiled with Java SE 6.0_03 - works with Win7x64
- - - miner.php highlight devs too slow finding shares (possibly failing)
- - - API update version to V1.11 and document changes
- - - API save default config file if none specified
- - - api.c save success incorrectly returns error
- - - api.c replace BUFSIZ (linux/windows have different values)
- - - Move RPC API content out of README to API-README
- - - Open a longpoll connection if a pool is in the REJECTING state as it's the
- + * API.class compiled with Java SE 6.0_03 - works with Win7x64
- + * miner.php highlight devs too slow finding shares (possibly failing)
- + * API update version to V1.11 and document changes
- + * API save default config file if none specified
- + * api.c save success incorrectly returns error
- + * api.c replace BUFSIZ (linux/windows have different values)
- + * Move RPC API content out of README to API-README
- + * Open a longpoll connection if a pool is in the REJECTING state as it's the
- only way to re-enable it automatically.
- - - Use only one longpoll as much as possible by using a pthread conditional
- + * Use only one longpoll as much as possible by using a pthread conditional
- broadcast that each longpoll thread waits on and checks if it's the current pool
- before
- - - If shares are known stale, don't use them to decide to disable a pool for
- + * If shares are known stale, don't use them to decide to disable a pool for
- sequential rejects.
- - - Restarting cgminer from within after ADL has been corrupted only leads to a
- + * Restarting cgminer from within after ADL has been corrupted only leads to a
- crash. Display a warning only and disable fanspeed monitoring.
- - - Icarus: fix abort calculation/allow user specified abort
- - - Icarus: make --icarus-timing hidden and document it in FPGA-README
- - - Icarus: high accuracy timing and other bitstream speed support
- - - add-MIPSEB-to-icarus-for-BIG_ENDIAN
- - - work_decode only needs swab32 on midstate under BIG ENDIAN
- - - add compile command to api-example.c
- - - save config bugfix: writing an extra ',' when no gpus
- - - Add dpkg-source commits
- + * Icarus: fix abort calculation/allow user specified abort
- + * Icarus: make --icarus-timing hidden and document it in FPGA-README
- + * Icarus: high accuracy timing and other bitstream speed support
- + * add-MIPSEB-to-icarus-for-BIG_ENDIAN
- + * work_decode only needs swab32 on midstate under BIG ENDIAN
- + * add compile command to api-example.c
- + * save config bugfix: writing an extra ',' when no gpus
- + * Add dpkg-source commits
-
- -- nushor <nushor11@gmail.com> Sun, 03 Jun 2012 22:02:03 -0500
-
- cgminer (2.4.1-1) stable; urgency=low
- Version 2.4.1-1 - May 6, 2012
- - - In the unlikely event of finding a block, display the block solved count with
- + * In the unlikely event of finding a block, display the block solved count with
- the pool it came from for auditing.
- - - Display the device summary on exit even if a device has been disabled.
- - - Use correct pool enabled enums in api.c.
- - - Import Debian packaging configs
- - - Ensure we test for a pool recovering from idle so long as it's not set to
- + * Display the device summary on exit even if a device has been disabled.
- + * Use correct pool enabled enums in api.c.
- + * Import Debian packaging configs
- + * Ensure we test for a pool recovering from idle so long as it's not set to
- disabled.
- - - Fix pool number display.
- - - Give cgminer -T message only if curses is in use.
- - - Reinit_adl is no longer used.
- - - API 'stats' allow devices to add their own stats also for testing/debug
- - - API add getwork stats to cgminer - accesable from API 'stats'
- - - Don't initialise variables to zero when in global scope since they're already
- + * Fix pool number display.
- + * Give cgminer -T message only if curses is in use.
- + * Reinit_adl is no longer used.
- + * API 'stats' allow devices to add their own stats also for testing/debug
- + * API add getwork stats to cgminer - accesable from API 'stats'
- + * Don't initialise variables to zero when in global scope since they're already
- initialised.
- - - Get rid of unitialised variable warning when it's false.
- - - Move a pool to POOL_REJECTING to be disabled only after 3 minutes of
- + * Get rid of unitialised variable warning when it's false.
- + * Move a pool to POOL_REJECTING to be disabled only after 3 minutes of
- continuous rejected shares.
- - - Some tweaks to reporting and logging.
- - - Change FPGA detection order since BFL hangs on an ICA
- - - API support new pool status
- - - Add a temporarily disabled state for enabled pools called POOL_REJECTING and
- + * Some tweaks to reporting and logging.
- + * Change FPGA detection order since BFL hangs on an ICA
- + * API support new pool status
- + * Add a temporarily disabled state for enabled pools called POOL_REJECTING and
- use the work from each longpoll to help determine when a rejecting pool has
- started working again. Switch pools based on the multipool strategy once a pool
- is re-enabled.
- - - Removing extra debug
- - - Fix the benchmark feature by bypassing the new networking code.
- - - Reset sequential reject counter after a pool is disabled for when it is
- + * Removing extra debug
- + * Fix the benchmark feature by bypassing the new networking code.
- + * Reset sequential reject counter after a pool is disabled for when it is
- re-enabled.
- - - Icarus - correct MH/s and U: with work restart set at 8 seconds
- - - ztex updateFreq was always reporting on fpga 0
- - - Trying harder to get 1.15y working
- - - Specifying threads on multi fpga boards extra cgpu
- - - Missing the add cgpu per extra fpga on 1.15y boards
- - - API add last share time to each pool
- - - Don't try to reap curls if benchmarking is enabled.
- + * Icarus - correct MH/s and U: with work restart set at 8 seconds
- + * ztex updateFreq was always reporting on fpga 0
- + * Trying harder to get 1.15y working
- + * Specifying threads on multi fpga boards extra cgpu
- + * Missing the add cgpu per extra fpga on 1.15y boards
- + * API add last share time to each pool
- + * Don't try to reap curls if benchmarking is enabled.
-
- -- nushor <nushor11@gmail.com> Sun, 06 May 2012 11:09:46 -0500
-
- cgminer (2.4.0-1) stable; urgency=low
- Version 2.4.0 - May 3, 2012
-
- - - Only show longpoll warning once when it has failed.
- - - Convert hashes to an unsigned long long as well.
- - - Detect pools that have issues represented by endless rejected shares and
- + * Only show longpoll warning once when it has failed.
- + * Convert hashes to an unsigned long long as well.
- + * Detect pools that have issues represented by endless rejected shares and
- disable them, with a parameter to optionally disable this feature.
- - - Bugfix: Use a 64-bit type for hashes_done (miner_thread) since it can overflow
- + * Bugfix: Use a 64-bit type for hashes_done (miner_thread) since it can overflow
- 32-bit on some FPGAs
- - - Implement an older header fix for a label existing before the pthread_cleanup
- + * Implement an older header fix for a label existing before the pthread_cleanup
- macro.
- - - Limit the number of curls we recruit on communication failures and with
- + * Limit the number of curls we recruit on communication failures and with
- delaynet enabled to 5 by maintaining a per-pool curl count, and using a pthread
- conditional that wakes up when one is returned to the ring buffer.
- - - Generalise add_pool() functions since they're repeated in add_pool_details.
- - - Bugfix: Return failure, rather than quit, if BFwrite fails
- - - Disable failing devices such that the user can attempt to re-enable them
- - - Bugfix: thread_shutdown shouldn't try to free the device, since it's needed
- + * Generalise add_pool() functions since they're repeated in add_pool_details.
- + * Bugfix: Return failure, rather than quit, if BFwrite fails
- + * Disable failing devices such that the user can attempt to re-enable them
- + * Bugfix: thread_shutdown shouldn't try to free the device, since it's needed
- afterward
- - - API bool's and 1TBS fixes
- - - Icarus - minimise code delays and name timer variables
- - - api.c V1.9 add 'restart' + redesign 'quit' so thread exits cleanly
- - - api.c bug - remove extra ']'s in notify command
- - - Increase pool watch interval to 30 seconds.
- - - Reap curls that are unused for over a minute. This allows connections to be
- + * API bool's and 1TBS fixes
- + * Icarus - minimise code delays and name timer variables
- + * api.c V1.9 add 'restart' + redesign 'quit' so thread exits cleanly
- + * api.c bug - remove extra ']'s in notify command
- + * Increase pool watch interval to 30 seconds.
- + * Reap curls that are unused for over a minute. This allows connections to be
- closed, thereby allowing the number of curl handles to always be the minimum
- necessary to not delay networking.
- - - Use the ringbuffer of curls from the same pool for submit as well as getwork
- + * Use the ringbuffer of curls from the same pool for submit as well as getwork
- threads. Since the curl handles were already connected to the same pool and are
- immediately available, share submission will not be delayed by getworks.
- - - Implement a scaleable networking framework designed to cope with any sized
- + * Implement a scaleable networking framework designed to cope with any sized
- network requirements, yet minimise the number of connections being reopened. Do
- this by create a ring buffer linked list of curl handles to be used by getwork,
- recruiting extra handles when none is immediately available.
- - - There is no need for the submit and getwork curls to be tied to the pool
- + * There is no need for the submit and getwork curls to be tied to the pool
- struct.
- - - Do not recruit extra connection threads if there have been connection errors
- + * Do not recruit extra connection threads if there have been connection errors
- to the pool in question.
- - - We should not retry submitting shares indefinitely or we may end up with a
- + * We should not retry submitting shares indefinitely or we may end up with a
- huge backlog during network outages, so discard stale shares if we failed to
- submit them and they've become stale in the interim.
-
- @@ -114,32 +153,32 @@
-
- cgminer (2.3.6-3) stable; urgency=low
- Version 2.3.6-3 - may 3, 2012
- - - More bug fixes, Pre 2.4.1 release.
- + * More bug fixes, Pre 2.4.1 release.
-
- -- nushor <nushor11@gmail.com> Thurs, 03 May 2012 00:36:50 -0500
-
- cgminer (2.3.6-2) stable; urgency=low
- Version 2.3.6-2 - May 2, 2012
- - - Various bug fixes, latest build from repository.
- + * Various bug fixes, latest build from repository.
-
- -- nushor <nushor11@gmail.com> Wed, 02 May 2012 18:17:49 -0500
-
- cgminer (2.3.6-1) stable; urgency=low
-
- Version 2.3.6 - April 29, 2012
- - - Shorten stale share messages slightly.
- - - Protect the freeing of current_hash under mutex_lock to prevent racing on it
- + * Shorten stale share messages slightly.
- + * Protect the freeing of current_hash under mutex_lock to prevent racing on it
- when set_curblock is hit concurrently.
- - - Change default behaviour to submitting stale, removing the --submit-stale
- + * Change default behaviour to submitting stale, removing the --submit-stale
- option and adding a --no-submit-stale option.
- - - Make sure to start the getwork and submit threads when a pool is added on the
- + * Make sure to start the getwork and submit threads when a pool is added on the
- fly. This fixes a crash when a pool is added to running cgminer and then
- switched to.
- - - Faster hardware can easily outstrip the speed we can get work and submit
- + * Faster hardware can easily outstrip the speed we can get work and submit
- shares when using only one connection per pool.
- - - Test the queued list to see if any get/submits are already queued and if they
- + * Test the queued list to see if any get/submits are already queued and if they
- are, start recruiting extra connections by generating new threads.
- - - This allows us to reuse network connections at low loads but recuit new open
- + * This allows us to reuse network connections at low loads but recuit new open
- connections as they're needed, so that cgminer can scale to hardware of any
- size.
-
- --- a/driver-bitforce.c
- +++ b/driver-bitforce.c
- @@ -157,7 +157,7 @@
- return true;
- }
-
- -static void biforce_clear_buffer(struct cgpu_info *bitforce)
- +static void bitforce_clear_buffer(struct cgpu_info *bitforce)
- {
- int fdDev = bitforce->device_fd;
- char pdevbuf[0x100];
- @@ -185,6 +185,8 @@
-
- applog(LOG_WARNING, "BFL%i: Re-initialising", bitforce->device_id);
-
- + bitforce_clear_buffer(bitforce);
- +
- mutex_lock(&bitforce->device_mutex);
- if (fdDev) {
- BFclose(fdDev);
- @@ -239,7 +241,11 @@
- if (!fdDev)
- return false;
-
- - mutex_lock(&bitforce->device_mutex);
- + /* It is not critical getting temperature so don't get stuck if we
- + * can't grab the mutex here */
- + if (mutex_trylock(&bitforce->device_mutex))
- + return false;
- +
- BFwrite(fdDev, "ZLX", 3);
- BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
- mutex_unlock(&bitforce->device_mutex);
- @@ -255,7 +261,7 @@
-
- if (temp > 0) {
- bitforce->temp = temp;
- - if (temp > bitforce->cutofftemp) {
- + if (unlikely(bitforce->cutofftemp > 0 && temp > bitforce->cutofftemp)) {
- applog(LOG_WARNING, "BFL%i: Hit thermal cutoff limit, disabling!", bitforce->device_id);
- bitforce->deven = DEV_RECOVER;
-
- @@ -264,7 +270,15 @@
- bitforce->dev_thermal_cutoff_count++;
- }
- }
- + } else {
- + /* Use the temperature monitor as a kind of watchdog for when
- + * our responses are out of sync and flush the buffer to
- + * hopefully recover */
- + applog(LOG_WARNING, "BFL%i: Garbled response probably throttling, clearing buffer");
- + bitforce_clear_buffer(bitforce);
- + return false;;
- }
- +
- return true;
- }
-
- @@ -287,8 +301,7 @@
- BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
- if (!pdevbuf[0] || !strncasecmp(pdevbuf, "B", 1)) {
- mutex_unlock(&bitforce->device_mutex);
- - if (!restart_wait(WORK_CHECK_INTERVAL_MS))
- - return false;
- + nmsleep(WORK_CHECK_INTERVAL_MS);
- goto re_send;
- } else if (unlikely(strncasecmp(pdevbuf, "OK", 2))) {
- mutex_unlock(&bitforce->device_mutex);
- @@ -300,6 +313,7 @@
- goto re_send;
- }
- applog(LOG_ERR, "BFL%i: Error: Send work reports: %s", bitforce->device_id, pdevbuf);
- + bitforce_clear_buffer(bitforce);
- return false;
- }
-
- @@ -340,6 +354,7 @@
-
- if (unlikely(strncasecmp(pdevbuf, "OK", 2))) {
- applog(LOG_ERR, "BFL%i: Error: Send block data reports: %s", bitforce->device_id, pdevbuf);
- + bitforce_clear_buffer(bitforce);
- return false;
- }
-
- @@ -414,7 +429,7 @@
- }
-
- if (delay_time_ms != bitforce->sleep_ms)
- - applog(LOG_DEBUG, "BFL%i: Wait time changed to: %d", bitforce->device_id, bitforce->sleep_ms, bitforce->wait_ms);
- + applog(LOG_DEBUG, "BFL%i: Wait time changed to: %d, waited %u", bitforce->device_id, bitforce->sleep_ms, bitforce->wait_ms);
-
- /* Work out the average time taken. Float for calculation, uint for display */
- bitforce->avg_wait_f += (tv_to_ms(elapsed) - bitforce->avg_wait_f) / TIME_AVG_CONSTANT;
- @@ -428,6 +443,7 @@
- return 0; /* Device idle */
- else if (strncasecmp(pdevbuf, "NONCE-FOUND", 11)) {
- applog(LOG_WARNING, "BFL%i: Error: Get result reports: %s", bitforce->device_id, pdevbuf);
- + bitforce_clear_buffer(bitforce);
- return 0;
- }
-
- @@ -475,9 +491,10 @@
- {
- struct cgpu_info *bitforce = thr->cgpu;
- unsigned int sleep_time;
- + bool send_ret;
- int64_t ret;
-
- - ret = bitforce_send_work(thr, work);
- + send_ret = bitforce_send_work(thr, work);
-
- if (!bitforce->nonce_range) {
- /* Initially wait 2/3 of the average cycle time so we can request more
- @@ -503,8 +520,10 @@
- bitforce->wait_ms = sleep_time;
- }
-
- - if (ret)
- + if (send_ret)
- ret = bitforce_get_result(thr, work);
- + else
- + ret = -1;
-
- if (ret == -1) {
- ret = 0;
- @@ -513,7 +532,7 @@
- bitforce->device_not_well_reason = REASON_DEV_COMMS_ERROR;
- bitforce->dev_comms_error_count++;
- /* empty read buffer */
- - biforce_clear_buffer(bitforce);
- + bitforce_clear_buffer(bitforce);
- }
- return ret;
- }
- @@ -523,6 +542,20 @@
- return bitforce_get_temp(bitforce);
- }
-
- +static bool bitforce_thread_init(struct thr_info *thr)
- +{
- + struct cgpu_info *bitforce = thr->cgpu;
- + unsigned int wait;
- +
- + /* Pause each new thread at least 100ms between initialising
- + * so the devices aren't making calls all at the same time. */
- + wait = thr->id * MAX_START_DELAY_US;
- + applog(LOG_DEBUG, "BFL%i: Delaying start by %dms", bitforce->device_id, wait / 1000);
- + usleep(wait);
- +
- + return true;
- +}
- +
- static struct api_data *bitforce_api_stats(struct cgpu_info *cgpu)
- {
- struct api_data *root = NULL;
- @@ -546,6 +579,7 @@
- .get_statline_before = get_bitforce_statline_before,
- .get_stats = bitforce_get_stats,
- .thread_prepare = bitforce_thread_prepare,
- + .thread_init = bitforce_thread_init,
- .scanhash = bitforce_scanhash,
- .thread_shutdown = bitforce_shutdown,
- .thread_enable = biforce_thread_enable
- --- a/driver-icarus.c
- +++ b/driver-icarus.c
- @@ -65,7 +65,7 @@
- #define ASSERT1(condition) __maybe_unused static char sizeof_uint32_t_must_be_4[(condition)?1:-1]
- ASSERT1(sizeof(uint32_t) == 4);
-
- -#define ICARUS_READ_TIME ((double)ICARUS_READ_SIZE * (double)8.0 / (double)ICARUS_IO_SPEED)
- +#define ICARUS_READ_TIME(baud) ((double)ICARUS_READ_SIZE * (double)8.0 / (double)(baud))
-
- // Fraction of a second, USB timeout is measured in
- // i.e. 10 means 1/10 of a second
- @@ -176,11 +176,36 @@
- // (which will only affect W)
- uint64_t history_count;
- struct timeval history_time;
- +
- + // icarus-options
- + int baud;
- + int work_division;
- + int fpga_count;
- + uint32_t nonce_mask;
- };
-
- +#define END_CONDITION 0x0000ffff
- +
- // One for each possible device
- static struct ICARUS_INFO **icarus_info;
-
- +// Looking for options in --icarus-timing and --icarus-options:
- +//
- +// Code increments this each time we start to look at a device
- +// However, this means that if other devices are checked by
- +// the Icarus code (e.g. BFL) they will count in the option offset
- +//
- +// This, however, is deterministic so that's OK
- +//
- +// If we were to increment after successfully finding an Icarus
- +// that would be random since an Icarus may fail and thus we'd
- +// not be able to predict the option order
- +//
- +// This also assumes that serial_detect() checks them sequentially
- +// and in the order specified on the command line
- +//
- +static int option_offset = -1;
- +
- struct device_api icarus_api;
-
- static void rev(unsigned char *s, size_t l)
- @@ -195,8 +220,8 @@
- }
- }
-
- -#define icarus_open2(devpath, purge) serial_open(devpath, 115200, ICARUS_READ_FAULT_DECISECONDS, purge)
- -#define icarus_open(devpath) icarus_open2(devpath, false)
- +#define icarus_open2(devpath, baud, purge) serial_open(devpath, baud, ICARUS_READ_FAULT_DECISECONDS, purge)
- +#define icarus_open(devpath, baud) icarus_open2(devpath, baud, false)
-
- static int icarus_gets(unsigned char *buf, int fd, struct timeval *tv_finish, struct thr_info *thr, int read_count)
- {
- @@ -272,7 +297,7 @@
- }
- }
-
- -static void set_timing_mode(struct cgpu_info *icarus)
- +static void set_timing_mode(int this_option_offset, struct cgpu_info *icarus)
- {
- struct ICARUS_INFO *info = icarus_info[icarus->device_id];
- double Hs;
- @@ -285,7 +310,7 @@
- buf[0] = '\0';
- else {
- ptr = opt_icarus_timing;
- - for (i = 0; i < icarus->device_id; i++) {
- + for (i = 0; i < this_option_offset; i++) {
- comma = strchr(ptr, ',');
- if (comma == NULL)
- break;
- @@ -354,11 +379,123 @@
-
- applog(LOG_DEBUG, "Icarus: Init: %d mode=%s read_count=%d Hs=%e",
- icarus->device_id, timing_mode_str(info->timing_mode), info->read_count, info->Hs);
- +}
- +
- +static uint32_t mask(int work_division)
- +{
- + char err_buf[BUFSIZ+1];
- + uint32_t nonce_mask = 0x7fffffff;
-
- + // yes we can calculate these, but this way it's easy to see what they are
- + switch (work_division) {
- + case 1:
- + nonce_mask = 0xffffffff;
- + break;
- + case 2:
- + nonce_mask = 0x7fffffff;
- + break;
- + case 4:
- + nonce_mask = 0x3fffffff;
- + break;
- + case 8:
- + nonce_mask = 0x1fffffff;
- + break;
- + default:
- + sprintf(err_buf, "Invalid2 icarus-options for work_division (%d) must be 1, 2, 4 or 8", work_division);
- + quit(1, err_buf);
- + }
- +
- + return nonce_mask;
- +}
- +
- +static void get_options(int this_option_offset, int *baud, int *work_division, int *fpga_count)
- +{
- + char err_buf[BUFSIZ+1];
- + char buf[BUFSIZ+1];
- + char *ptr, *comma, *colon, *colon2;
- + size_t max;
- + int i, tmp;
- +
- + if (opt_icarus_options == NULL)
- + buf[0] = '\0';
- + else {
- + ptr = opt_icarus_options;
- + for (i = 0; i < this_option_offset; i++) {
- + comma = strchr(ptr, ',');
- + if (comma == NULL)
- + break;
- + ptr = comma + 1;
- + }
- +
- + comma = strchr(ptr, ',');
- + if (comma == NULL)
- + max = strlen(ptr);
- + else
- + max = comma - ptr;
- +
- + if (max > BUFSIZ)
- + max = BUFSIZ;
- + strncpy(buf, ptr, max);
- + buf[max] = '\0';
- + }
- +
- + *baud = ICARUS_IO_SPEED;
- + *work_division = 2;
- + *fpga_count = 2;
- +
- + if (*buf) {
- + colon = strchr(buf, ':');
- + if (colon)
- + *(colon++) = '\0';
- +
- + if (*buf) {
- + tmp = atoi(buf);
- + switch (tmp) {
- + case 115200:
- + *baud = 115200;
- + break;
- + case 57600:
- + *baud = 57600;
- + break;
- + default:
- + sprintf(err_buf, "Invalid icarus-options for baud (%s) must be 115200 or 57600", buf);
- + quit(1, err_buf);
- + }
- + }
- +
- + if (colon && *colon) {
- + colon2 = strchr(colon, ':');
- + if (colon2)
- + *(colon2++) = '\0';
- +
- + if (*colon) {
- + tmp = atoi(colon);
- + if (tmp == 1 || tmp == 2 || tmp == 4 || tmp == 8) {
- + *work_division = tmp;
- + *fpga_count = tmp; // default to the same
- + } else {
- + sprintf(err_buf, "Invalid icarus-options for work_division (%s) must be 1, 2, 4 or 8", colon);
- + quit(1, err_buf);
- + }
- + }
- +
- + if (colon2 && *colon2) {
- + tmp = atoi(colon2);
- + if (tmp > 0 && tmp <= *work_division)
- + *fpga_count = tmp;
- + else {
- + sprintf(err_buf, "Invalid icarus-options for fpga_count (%s) must be >0 and <=work_division (%d)", colon2, *work_division);
- + quit(1, err_buf);
- + }
- + }
- + }
- + }
- }
-
- static bool icarus_detect_one(const char *devpath)
- {
- + int this_option_offset = ++option_offset;
- +
- struct ICARUS_INFO *info;
- struct timeval tv_start, tv_finish;
- int fd;
- @@ -379,9 +516,13 @@
- unsigned char ob_bin[64], nonce_bin[ICARUS_READ_SIZE];
- char *nonce_hex;
-
- + int baud, work_division, fpga_count;
- +
- + get_options(this_option_offset, &baud, &work_division, &fpga_count);
- +
- applog(LOG_DEBUG, "Icarus Detect: Attempting to open %s", devpath);
-
- - fd = icarus_open2(devpath, true);
- + fd = icarus_open2(devpath, baud, true);
- if (unlikely(fd == -1)) {
- applog(LOG_ERR, "Icarus Detect: Failed to open %s", devpath);
- return false;
- @@ -429,6 +570,9 @@
- applog(LOG_INFO, "Found Icarus at %s, mark as %d",
- devpath, icarus->device_id);
-
- + applog(LOG_DEBUG, "Icarus: Init: %d baud=%d work_division=%d fpga_count=%d",
- + icarus->device_id, baud, work_division, fpga_count);
- +
- // Since we are adding a new device on the end it needs to always be allocated
- icarus_info[icarus->device_id] = (struct ICARUS_INFO *)malloc(sizeof(struct ICARUS_INFO));
- if (unlikely(!(icarus_info[icarus->device_id])))
- @@ -439,10 +583,15 @@
- // Initialise everything to zero for a new device
- memset(info, 0, sizeof(struct ICARUS_INFO));
-
- - info->golden_hashes = (golden_nonce_val & 0x7fffffff) << 1;
- + info->baud = baud;
- + info->work_division = work_division;
- + info->fpga_count = fpga_count;
- + info->nonce_mask = mask(work_division);
- +
- + info->golden_hashes = (golden_nonce_val & info->nonce_mask) * fpga_count;
- timersub(&tv_finish, &tv_start, &(info->golden_tv));
-
- - set_timing_mode(icarus);
- + set_timing_mode(this_option_offset, icarus);
-
- return true;
- }
- @@ -458,7 +607,7 @@
-
- struct timeval now;
-
- - int fd = icarus_open(icarus->device_path);
- + int fd = icarus_open(icarus->device_path, icarus_info[icarus->device_id]->baud);
- if (unlikely(-1 == fd)) {
- applog(LOG_ERR, "Failed to open Icarus on %s",
- icarus->device_path);
- @@ -565,11 +714,9 @@
-
- submit_nonce(thr, work, nonce);
-
- - hash_count = (nonce & 0x7fffffff);
- - if (hash_count++ == 0x7fffffff)
- - hash_count = 0xffffffff;
- - else
- - hash_count <<= 1;
- + hash_count = (nonce & info->nonce_mask);
- + hash_count++;
- + hash_count *= info->fpga_count;
-
- if (opt_debug || info->do_icarus_timing)
- timersub(&tv_finish, &tv_start, &elapsed);
- @@ -580,7 +727,9 @@
- }
-
- // ignore possible end condition values
- - if (info->do_icarus_timing && (nonce & 0x7fffffff) > 0x000fffff && (nonce & 0x7fffffff) < 0x7ff00000) {
- + if (info->do_icarus_timing
- + && ((nonce & info->nonce_mask) > END_CONDITION)
- + && ((nonce & info->nonce_mask) < (info->nonce_mask & ~END_CONDITION))) {
- gettimeofday(&tv_history_start, NULL);
-
- history0 = &(info->history[0]);
- @@ -590,7 +739,7 @@
-
- Ti = (double)(elapsed.tv_sec)
- + ((double)(elapsed.tv_usec))/((double)1000000)
- - - ICARUS_READ_TIME;
- + - ((double)ICARUS_READ_TIME(info->baud));
- Xi = (double)hash_count;
- history0->sumXiTi += Xi * Ti;
- history0->sumXi += Xi;
- @@ -700,6 +849,9 @@
- root = api_add_uint(root, "timing_values", &(info->history[0].values), false);
- root = api_add_const(root, "timing_mode", timing_mode_str(info->timing_mode), false);
- root = api_add_bool(root, "is_timing", &(info->do_icarus_timing), false);
- + root = api_add_int(root, "baud", &(info->baud), false);
- + root = api_add_int(root, "work_division", &(info->work_division), false);
- + root = api_add_int(root, "fpga_count", &(info->fpga_count), false);
-
- return root;
- }
- --- a/driver-opencl.c
- +++ b/driver-opencl.c
- @@ -660,9 +660,19 @@
-
- for (gpu = 0; gpu < nDevs; gpu++) {
- struct cgpu_info *cgpu = &gpus[gpu];
- + double displayed_rolling, displayed_total;
- + bool mhash_base = true;
-
- - wlog("GPU %d: %.1f / %.1f Mh/s | A:%d R:%d HW:%d U:%.2f/m I:%d\n",
- - gpu, cgpu->rolling, cgpu->total_mhashes / total_secs,
- + displayed_rolling = cgpu->rolling;
- + displayed_total = cgpu->total_mhashes / total_secs;
- + if (displayed_rolling < 1) {
- + displayed_rolling *= 1000;
- + displayed_total *= 1000;
- + mhash_base = false;
- + }
- +
- + wlog("GPU %d: %.1f / %.1f %sh/s | A:%d R:%d HW:%d U:%.2f/m I:%d\n",
- + gpu, displayed_rolling, displayed_total, mhash_base ? "M" : "K",
- cgpu->accepted, cgpu->rejected, cgpu->hw_errors,
- cgpu->utility, cgpu->intensity);
- #ifdef HAVE_ADL
- @@ -710,7 +720,10 @@
- if (thr->cgpu != cgpu)
- continue;
- get_datestamp(checkin, &thr->last);
- - wlog("Thread %d: %.1f Mh/s %s ", i, thr->rolling, cgpu->deven != DEV_DISABLED ? "Enabled" : "Disabled");
- + displayed_rolling = thr->rolling;
- + if (!mhash_base)
- + displayed_rolling *= 1000;
- + wlog("Thread %d: %.1f %sh/s %s ", i, displayed_rolling, mhash_base ? "M" : "K" , cgpu->deven != DEV_DISABLED ? "Enabled" : "Disabled");
- switch (cgpu->status) {
- default:
- case LIFE_WELL:
- --- a/miner.h
- +++ b/miner.h
- @@ -500,6 +500,11 @@
- quit(1, "WTF MUTEX ERROR ON UNLOCK!");
- }
-
- +static inline int mutex_trylock(pthread_mutex_t *lock)
- +{
- + return pthread_mutex_trylock(lock);
- +}
- +
- static inline void wr_lock(pthread_rwlock_t *lock)
- {
- if (unlikely(pthread_rwlock_wrlock(lock)))
- @@ -557,6 +562,7 @@
- extern bool opt_api_network;
- extern bool opt_delaynet;
- extern bool opt_restart;
- +extern char *opt_icarus_options;
- extern char *opt_icarus_timing;
- #ifdef USE_BITFORCE
- extern bool opt_bfl_noncerange;
- --- a/miner.php
- +++ b/miner.php
- @@ -87,11 +87,13 @@
- 'DATE' => null,
- 'RIGS' => null,
- 'SUMMARY' => array('Elapsed', 'MHS av', 'Found Blocks=Blks', 'Accepted', 'Rejected=Rej', 'Utility'),
- - 'DEVS' => array('ID', 'Name', 'GPU', 'Status', 'MHS av', 'Accepted', 'Rejected=Rej', 'Utility'),
- + 'DEVS+NOTIFY' => array('DEVS.Name=Name', 'DEVS.ID=ID', 'DEVS.Status=Status', 'DEVS.Temperature=Temp',
- + 'DEVS.MHS av=MHS av', 'DEVS.Accepted=Accept', 'DEVS.Rejected=Rej',
- + 'DEVS.Utility=Utility', 'NOTIFY.Last Not Well=Not Well'),
- 'POOL' => array('POOL', 'Status', 'Accepted', 'Rejected=Rej', 'Last Share Time'));
- $mobilesum = array(
- 'SUMMARY' => array('MHS av', 'Found Blocks', 'Accepted', 'Rejected', 'Utility'),
- - 'DEVS' => array('MHS av', 'Accepted', 'Rejected', 'Utility'),
- + 'DEVS+NOTIFY' => array('DEVS.MHS av', 'DEVS.Accepted', 'DEVS.Rejected', 'DEVS.Utility'),
- 'POOL' => array('Accepted', 'Rejected'));
- #
- # customsummarypages is an array of these Custom Summary Pages
- @@ -716,6 +718,9 @@
- if ($class == '' && ($rownum % 2) == 0)
- $class = $c2class;
-
- + if ($ret == '')
- + $ret = $b;
- +
- return array($ret, $class);
- }
- #
- @@ -1274,8 +1279,171 @@
- 'GPU' => 'devs', // You would normally use DEVS
- 'PGA' => 'devs', // You would normally use DEVS
- 'NOTIFY' => 'notify',
- + 'DEVDETAILS' => 'devdetails',
- + 'STATS' => 'stats',
- 'CONFIG' => 'config');
- #
- +function joinfields($section1, $section2, $join, $results)
- +{
- + global $sectionmap;
- +
- + $name1 = $sectionmap[$section1];
- + $name2 = $sectionmap[$section2];
- + $newres = array();
- +
- + // foreach rig in section1
- + foreach ($results[$name1] as $rig => $result)
- + {
- + $status = null;
- +
- + // foreach answer section in the rig api call
- + foreach ($result as $name1b => $fields1b)
- + {
- + if ($name1b == 'STATUS')
- + {
- + // remember the STATUS from section1
- + $status = $result[$name1b];
- + continue;
- + }
- +
- + // foreach answer section in the rig api call (for the other api command)
- + foreach ($results[$name2][$rig] as $name2b => $fields2b)
- + {
- + if ($name2b == 'STATUS')
- + continue;
- +
- + // If match the same field values of fields in $join
- + $match = true;
- + foreach ($join as $field)
- + if ($fields1b[$field] != $fields2b[$field])
- + {
- + $match = false;
- + break;
- + }
- +
- + if ($match === true)
- + {
- + if ($status != null)
- + {
- + $newres[$rig]['STATUS'] = $status;
- + $status = null;
- + }
- +
- + $subsection = $section1.'+'.$section2;
- + $subsection .= preg_replace('/[^0-9]/', '', $name1b.$name2b);
- +
- + foreach ($fields1b as $nam => $val)
- + $newres[$rig][$subsection]["$section1.$nam"] = $val;
- + foreach ($fields2b as $nam => $val)
- + $newres[$rig][$subsection]["$section2.$nam"] = $val;
- + }
- + }
- + }
- + }
- + return $newres;
- +}
- +#
- +function joinall($section1, $section2, $results)
- +{
- + global $sectionmap;
- +
- + $name1 = $sectionmap[$section1];
- + $name2 = $sectionmap[$section2];
- + $newres = array();
- +
- + // foreach rig in section1
- + foreach ($results[$name1] as $rig => $result)
- + {
- + // foreach answer section in the rig api call
- + foreach ($result as $name1b => $fields1b)
- + {
- + if ($name1b == 'STATUS')
- + {
- + // copy the STATUS from section1
- + $newres[$rig][$name1b] = $result[$name1b];
- + continue;
- + }
- +
- + // foreach answer section in the rig api call (for the other api command)
- + foreach ($results[$name2][$rig] as $name2b => $fields2b)
- + {
- + if ($name2b == 'STATUS')
- + continue;
- +
- + $subsection = $section1.'+'.$section2;
- + $subsection .= preg_replace('/[^0-9]/', '', $name1b.$name2b);
- +
- + foreach ($fields1b as $nam => $val)
- + $newres[$rig][$subsection]["$section1.$nam"] = $val;
- + foreach ($fields2b as $nam => $val)
- + $newres[$rig][$subsection]["$section2.$nam"] = $val;
- + }
- + }
- + }
- + return $newres;
- +}
- +#
- +function joinsections($sections, $results, $errors)
- +{
- + global $sectionmap;
- +
- +#echo "results['pools']=".print_r($results['pools'],true)."<br>";
- +
- + // GPU's don't have Name,ID fields - so create them
- + foreach ($results as $section => $res)
- + foreach ($res as $rig => $result)
- + foreach ($result as $name => $fields)
- + {
- + $subname = preg_replace('/[0-9]/', '', $name);
- + if ($subname == 'GPU' and isset($result[$name]['GPU']))
- + {
- + $results[$section][$rig][$name]['Name'] = 'GPU';
- + $results[$section][$rig][$name]['ID'] = $result[$name]['GPU'];
- + }
- + }
- +
- + foreach ($sections as $section => $fields)
- + if ($section != 'DATE' && !isset($sectionmap[$section]))
- + {
- + $both = explode('+', $section, 2);
- + if (count($both) > 1)
- + {
- + switch($both[0])
- + {
- + case 'SUMMARY':
- + switch($both[1])
- + {
- + case 'POOL':
- + case 'DEVS':
- + case 'CONFIG':
- + $sectionmap[$section] = $section;
- + $results[$section] = joinall($both[0], $both[1], $results);
- + break;
- + }
- + break;
- + case 'DEVS':
- + $join = array('Name', 'ID');
- + switch($both[1])
- + {
- + case 'NOTIFY':
- + case 'DEVDETAILS':
- + $sectionmap[$section] = $section;
- + $results[$section] = joinfields($both[0], $both[1], $join, $results);
- + break;
- + }
- + break;
- + default:
- + $errors[] = "Error: Invalid section '$section'";
- + break;
- + }
- + }
- + else
- + $errors[] = "Error: Invalid section '$section'";
- + }
- +
- + return array($results, $errors);
- +}
- +#
- function secmatch($section, $field)
- {
- if ($section == $field)
- @@ -1335,7 +1503,14 @@
- $value = null;
- }
-
- - list($showvalue, $class) = fmt($secname, $name, $value, $when, $row);
- + if (strpos($secname, '+') === false)
- + list($showvalue, $class) = fmt($secname, $name, $value, $when, $row);
- + else
- + {
- + $parts = explode('.', $name, 2);
- + list($showvalue, $class) = fmt($parts[0], $parts[1], $value, $when, $row);
- + }
- +
- echo "<td$class align=right>$showvalue</td>";
- }
- endrow();
- @@ -1356,15 +1531,19 @@
- $errors = array();
- foreach ($sections as $section => $fields)
- {
- - if (isset($sectionmap[$section]))
- + $all = explode('+', $section);
- + foreach ($all as $section)
- {
- - $cmd = $sectionmap[$section];
- - if (!isset($cmds[$cmd]))
- - $cmds[$cmd] = 1;
- + if (isset($sectionmap[$section]))
- + {
- + $cmd = $sectionmap[$section];
- + if (!isset($cmds[$cmd]))
- + $cmds[$cmd] = 1;
- + }
- + else
- + if ($section != 'DATE')
- + $errors[] = "Error: unknown section '$section' in custom summary page '$pagename'";
- }
- - else
- - if ($section != 'DATE')
- - $errors[] = "Error: unknown section '$section' in custom summary page '$pagename'";
- }
-
- $results = array();
- @@ -1399,6 +1578,7 @@
- $shownsomething = false;
- if (count($results) > 0)
- {
- + list($results, $errors) = joinsections($sections, $results, $errors);
- $first = true;
- foreach ($sections as $section => $fields)
- {
|