enum filegetter_code service_filegetter_stop(service_filegetter_tp sfg) { assert(sfg); service_filegetter_log(sfg, SFG_INFO, "shutting down filegetter"); enum filegetter_code result = FG_SUCCESS; if(sfg->think_times != NULL) { cdf_free(sfg->think_times); sfg->think_times = NULL; } if(sfg->downloads != NULL) { g_tree_destroy(sfg->downloads); sfg->downloads = NULL; } if(sfg->state != SFG_DONE) { result = filegetter_shutdown(&sfg->fg); sfg->current_download = NULL; sfg->state = SFG_DONE; } return result; }
enum filegetter_code service_filegetter_activate(service_filegetter_tp sfg, gint sockd) { assert(sfg); start_over: if((sfg->state == SFG_THINKING || sfg->state == SFG_DOWNLOADING) && sfg->expire.tv_sec > 0) { /* they set a service expiration, check if we have expired */ struct timespec now; clock_gettime(CLOCK_REALTIME, &now); if(now.tv_sec > sfg->expire.tv_sec) { return service_filegetter_expire(sfg); } } if(sfg->state == SFG_THINKING) { struct timespec now; clock_gettime(CLOCK_REALTIME, &now); if(now.tv_sec >= sfg->wakeup.tv_sec) { /* time to wake up and download the next file */ service_filegetter_download_next(sfg); } else { return FG_ERR_WOULDBLOCK; } } if(sfg->state != SFG_DOWNLOADING || sfg->fg.sockd != sockd) { return FG_ERR_INVALID; } reactivate:; enum filegetter_code result = filegetter_activate(&sfg->fg); if(result == FG_ERR_FATAL || result == FG_ERR_SOCKSCONN) { /* it had to shut down */ service_filegetter_log(sfg, SFG_NOTICE, "filegetter shutdown due to error '%s'... retrying in 60 seconds", filegetter_codetoa(result)); filegetter_shutdown(&sfg->fg); filegetter_start(&sfg->fg, sfg->fg.epolld); /* set wakeup timer and call the sleep function */ sfg->state = SFG_THINKING; clock_gettime(CLOCK_REALTIME, &sfg->wakeup); sfg->wakeup.tv_sec += 60; (*sfg->sleep_cb)(sfg, 60); service_filegetter_log(sfg, SFG_NOTICE, "[fg-pause] pausing for 60 seconds"); return FG_ERR_WOULDBLOCK; } else if(result != FG_OK_200 && result != FG_ERR_WOULDBLOCK) { service_filegetter_log(sfg, SFG_CRITICAL, "filegetter shutdown due to protocol error '%s'...", filegetter_codetoa(result)); filegetter_shutdown(&sfg->fg); return result; } /* report progress */ filegetter_filestats_t stats; filegetter_stat_download(&sfg->fg, &stats); service_filegetter_report(sfg, SFG_INFO, "[fg-download-progress]", &stats, sfg->downloads_completed+1, sfg->downloads_requested); if(result == FG_OK_200) { /* completed a download */ sfg->downloads_completed++; sfg->state = SFG_THINKING; /* report completion stats */ service_filegetter_report(sfg, SFG_NOTICE, "[fg-download-complete]", &stats, sfg->downloads_completed, sfg->downloads_requested); if(sfg->downloads_requested > 0 && sfg->downloads_completed >= sfg->downloads_requested) { return service_filegetter_expire(sfg); } else { if(sfg->type == SFG_MULTI && sfg->think_times != NULL) { /* get think time and set wakeup timer */ gdouble percentile = (gdouble)(((gdouble)rand()) / ((gdouble)RAND_MAX)); guint sleeptime = (guint) (cdf_getValue(sfg->think_times, percentile) / 1000); clock_gettime(CLOCK_REALTIME, &sfg->wakeup); sfg->wakeup.tv_sec += sleeptime; /* dont sleep if it would put us beyond our expiration (if its set) */ if(sfg->expire.tv_sec > 0 && sfg->wakeup.tv_sec > sfg->expire.tv_sec) { return service_filegetter_expire(sfg); } /* call the sleep function, then check if we are done thinking */ (*sfg->sleep_cb)(sfg, sleeptime); goto start_over; } else { /* reset download file */ service_filegetter_download_next(sfg); goto reactivate; } } } return result; }
static enum filegetter_code filegetter_die(filegetter_tp fg, gchar* msg) { filegetter_shutdown(fg); fprintf(stderr, "%s", msg); return FG_ERR_FATAL; }