int R_curl_callback_progress(SEXP fun, double dltotal, double dlnow, double ultotal, double ulnow) { SEXP down = PROTECT(allocVector(REALSXP, 2)); REAL(down)[0] = dltotal; REAL(down)[1] = dlnow; SEXP up = PROTECT(allocVector(REALSXP, 2)); REAL(up)[0] = ultotal; REAL(up)[1] = ulnow; SEXP call = PROTECT(LCONS(fun, LCONS(down, LCONS(up, R_NilValue)))); int ok; SEXP res = PROTECT(R_tryEval(call, R_GlobalEnv, &ok)); if (ok != 0 || pending_interrupt()) { UNPROTECT(4); return 0; } if (TYPEOF(res) != LGLSXP || length(res) != 1) { UNPROTECT(4); Rf_warning("progress callback must return boolean"); return 0; } UNPROTECT(4); return !asLogical(res); }
size_t append_buffer(void *contents, size_t sz, size_t nmemb, void *ctx) { if (pending_interrupt()) return 0; /* avoids compiler warning on windows */ size_t realsize = sz * nmemb; memory *mem = (memory*) ctx; /* realloc is slow on windows, therefore increase buffer to nearest 2^n */ #ifdef _WIN32 mem->buf = realloc(mem->buf, exp2(ceil(log2(mem->size + realsize)))); #else mem->buf = realloc(mem->buf, mem->size + realsize); #endif if (!mem->buf) return 0; /* append data and increment size */ memcpy(&(mem->buf[mem->size]), contents, realsize); mem->size += realsize; return realsize; }
size_t R_curl_callback_read(char *buffer, size_t size, size_t nitems, SEXP fun) { SEXP nbytes = PROTECT(ScalarInteger(size * nitems)); SEXP call = PROTECT(LCONS(fun, LCONS(nbytes, R_NilValue))); int ok; SEXP res = PROTECT(R_tryEval(call, R_GlobalEnv, &ok)); if (ok != 0 || pending_interrupt()) { UNPROTECT(3); return CURL_READFUNC_ABORT; } if (TYPEOF(res) != RAWSXP) { UNPROTECT(3); Rf_warning("read callback must raw vector"); return CURL_READFUNC_ABORT; } size_t bytes_read = length(res); memcpy(buffer, RAW(res), bytes_read); UNPROTECT(3); return bytes_read; }
size_t push_disk(void* contents, size_t sz, size_t nmemb, FILE *ctx) { if (pending_interrupt()) return 0; return fwrite(contents, sz, nmemb, ctx); }
/* * this routine serves two purposes: * 1. report progress * 2. check for deadlocks */ void *reporter(void *arg) { int status; int end = 0; struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = USEC_TO_NSEC(report_interval); tsnorm(&ts); if (duration >= 0) end = duration + time(NULL); /* sleep initially to let everything get up and running */ status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); if (status) { error("from clock_nanosleep: %s\n", strerror(status)); return NULL; } debug("reporter: starting report loop\n"); info("Press Control-C to stop test\nCurrent Inversions: \n"); for (;;) { pthread_mutex_lock(&shutdown_mtx); if (shutdown) { pthread_mutex_unlock(&shutdown_mtx); break; } pthread_mutex_unlock(&shutdown_mtx); /* wait for our reporting interval */ status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); if (status) { error("from clock_nanosleep: %s\n", strerror(status)); break; } /* check for signaled shutdown */ if (!quiet) { pthread_mutex_lock(&shutdown_mtx); if (shutdown == 0) { fputs(UP_ONE, stdout); printf("Current Inversions: %lu\n", total_inversions()); } } pthread_mutex_unlock(&shutdown_mtx); /* if we specified a duration, see if it has expired */ if (end && time(NULL) > end) { info("duration reached (%d seconds)\n", duration); set_shutdown_flag(); continue; } /* check for a pending SIGINT */ if (pending_interrupt()) { info("Keyboard Interrupt!\n"); break; } /* check watchdog stuff */ if ((watchdog_check())) { error("reporter stopping due to watchdog event\n"); set_shutdown_flag(); break; } /* clear watchdog counters */ watchdog_clear(); } debug("reporter: finished\n"); set_shutdown_flag(); return NULL; }