static double time_diff (const GTimeVal *first, const GTimeVal *second) { double first_ms = timeval_to_ms (first); double second_ms = timeval_to_ms (second); return first_ms - second_ms; }
/* * Cleanup at the end of the run, produce any final output that might be * required. */ void _cleanup(void) { struct timeval end_time; uint64_t ms; gettimeofday(&end_time, NULL); ms = timeval_to_ms(end_time) - timeval_to_ms(start_time); LOCK; /* If plan_no_plan() wasn't called, and we don't have a plan, and we're not skipping everything, then something happened before we could produce any output */ if(!no_plan && !have_plan && !skip_all) { diag("Looks like your test died before it could output anything."); UNLOCK; return; } if(test_died) { diag("Looks like your test died just after %d.", test_count); UNLOCK; return; } /* No plan provided, but now we know how many tests were run, and can print the header at the end */ if(!skip_all && (no_plan || !have_plan)) { printf("1..%d\n", test_count); } if((have_plan && !no_plan) && e_tests < test_count) { diag("Looks like you planned %d %s but ran %d extra.", e_tests, e_tests == 1 ? "test" : "tests", test_count - e_tests); ok(0, "plan_tests() doesn't match number of test results"); UNLOCK; return; } if((have_plan || !no_plan) && e_tests > test_count) { diag("Looks like you planned %d %s but only ran %d.", e_tests, e_tests == 1 ? "test" : "tests", test_count); ok(0, "plan_tests() doesn't match number of test results"); UNLOCK; return; } if(failures) diag("Looks like you failed %d %s of %d.", failures, failures == 1 ? "test" : "tests", test_count); diag("ELAPSED: %" PRIu64 "ms\n", ms); UNLOCK; }
static unsigned long sock_calc_timeout(struct sock *sk) { unsigned long timeout = timeval_to_ms(&sk->opt.so_rcvtimeo); if (timeout == 0) { timeout = SCHED_TIMEOUT_INFINITE; } return timeout; }
/* get current time in ms */ ir_uint64 get_time_in_ms(void) { struct timeval timestruct; gettimeofday(×truct, NULL); return timeval_to_ms(×truct); }
uint64_t server_get_time() { struct timeval tv; if(gettimeofday(&tv, NULL) == -1) return 0L; return timeval_to_ms(tv); }
void check_sleep_ms(int ms) { struct timeval start = gettimeofday(); sleep_ms(ms); struct timeval now = gettimeofday(); int slept_ms = timeval_to_ms(timeval_subtract(now, start)); int delta = max(100, slept_ms / 10); TS_ASSERT_DELTA(ms, slept_ms, delta); }
int win32_dispatch(struct event_base *base, struct timeval *tv) { struct win32op *win32op = base->evbase; int res = 0; unsigned j, i; int fd_count; SOCKET s; if (win32op->resize_out_sets) { size_t size = FD_SET_ALLOC_SIZE(win32op->fd_setsz); if (!(win32op->readset_out = mm_realloc(win32op->readset_out, size))) return (-1); if (!(win32op->exset_out = mm_realloc(win32op->exset_out, size))) return (-1); if (!(win32op->writeset_out = mm_realloc(win32op->writeset_out, size))) return (-1); win32op->resize_out_sets = 0; } fd_set_copy(win32op->readset_out, win32op->readset_in); fd_set_copy(win32op->exset_out, win32op->writeset_in); fd_set_copy(win32op->writeset_out, win32op->writeset_in); fd_count = (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ? win32op->readset_out->fd_count : win32op->writeset_out->fd_count; if (!fd_count) { /* Windows doesn't like you to call select() with no sockets */ Sleep(timeval_to_ms(tv)); evsig_process(base); return (0); } EVBASE_RELEASE_LOCK(base, EVTHREAD_WRITE, th_base_lock); res = select(fd_count, (struct fd_set*)win32op->readset_out, (struct fd_set*)win32op->writeset_out, (struct fd_set*)win32op->exset_out, tv); EVBASE_ACQUIRE_LOCK(base, EVTHREAD_WRITE, th_base_lock); event_debug(("%s: select returned %d", __func__, res)); if(res <= 0) { evsig_process(base); return res; } else if (base->sig.evsig_caught) { evsig_process(base); } if (win32op->readset_out->fd_count) { i = rand() % win32op->readset_out->fd_count; for (j=0; j<win32op->readset_out->fd_count; ++j) { if (++i >= win32op->readset_out->fd_count) i = 0; s = win32op->readset_out->fd_array[i]; evmap_io_active(base, s, EV_READ); } } if (win32op->exset_out->fd_count) { i = rand() % win32op->exset_out->fd_count; for (j=0; j<win32op->exset_out->fd_count; ++j) { if (++i >= win32op->exset_out->fd_count) i = 0; s = win32op->exset_out->fd_array[i]; evmap_io_active(base, s, EV_WRITE); } } if (win32op->writeset_out->fd_count) { SOCKET s; i = rand() % win32op->writeset_out->fd_count; for (j=0; j<win32op->writeset_out->fd_count; ++j) { if (++i >= win32op->writeset_out->fd_count) i = 0; s = win32op->writeset_out->fd_array[i]; evmap_io_active(base, s, EV_WRITE); } } return (0); }
int server_run() { struct timeval* timeout; struct timeval tv, current; timer_callback* timcb; socket_callback* sockcb; fd_set rfds, wfds; int r; /* No watches have been set */ ASSERT(ctx.max_fd > -1); ctx.stopped = 0; while(!ctx.stopped) { /* Watch for the various fds */ memcpy(&rfds, &ctx.read_fds, sizeof(rfds)); memcpy(&wfds, &ctx.write_fds, sizeof(wfds)); /* Prepare for timers */ timeout = NULL; if(gettimeofday(¤t, NULL) == -1) return -1; /* Cycle through timers */ for(timcb = ctx.timers; timcb; ) { ASSERT(timcb->callback); /* Call any timers that have already passed */ if(timeval_compare(¤t, &timcb->at) >= 0) { /* Convert to milliseconds, and make the call */ r = (timcb->callback)(timeval_to_ms(current), timcb->arg); /* Reset timer if so desired */ if (r == 1 && !timeval_empty(&timcb->interval)) { timeval_add(&timcb->at, &timcb->interval); /* If the time has already passed, just use current time */ if(timeval_compare(&(timcb->at), ¤t) <= 0) memcpy(&(timcb->at), ¤t, sizeof(timcb->at)); } /* Otherwise remove it. Either one shot, or returned 0 */ else { timcb = remove_timer(timcb); continue; } } /* Get soonest timer */ if (!timeout || timeval_compare(&timcb->at, timeout) < 0) timeout = &timcb->at; timcb = timcb->next; } /* Convert to an offset */ if(timeout) { memcpy(&tv, timeout, sizeof(tv)); timeout = &tv; timeval_subtract(timeout, ¤t); } /* fprintf(stderr, "selecting with timeout: "); timeval_dump(timeout); fprintf(stderr, "\n"); */ r = select(ctx.max_fd, &rfds, &wfds, NULL, timeout); if (r < 0) { /* Interrupted so try again, and possibly exit */ if (errno == EINTR) continue; /* Programmer errors */ ASSERT (errno != EBADF); ASSERT (errno != EINVAL); return r; } /* Timeout, just jump to timeout processing */ if(r == 0) continue; for(sockcb = ctx.callbacks; sockcb; sockcb = sockcb->next) { ASSERT(sockcb->fd != -1); /* Call any that are set */ if (FD_ISSET(sockcb->fd, &rfds)) (sockcb->callback)(sockcb->fd, SERVER_READ, sockcb->arg); if (FD_ISSET(sockcb->fd, &wfds)) (sockcb->callback)(sockcb->fd, SERVER_WRITE, sockcb->arg); } } return 0; }
static void mainloop (void) { /* data is persistant across calls */ static struct timeval timestruct; static int changequartersec, changesec, changemin, changehour; static time_t lasttime, lastmin, lasthour, last4sec, last5sec, last20sec; static time_t lastautoadd; static time_t last3min, last2min, lastignoredec; static int first_loop = 1; static ir_uint64 last250ms; userinput *pubplist; userinput *urehash; ir_uint64 xdccsent; unsigned int i; int highests; unsigned int ss; upload *ul; transfer *tr; channel_t *ch; xdcc *xd; dccchat_t *chat; updatecontext(); gnetwork = NULL; if (first_loop) { /* init if first time called */ FD_ZERO(&gdata.readset); FD_ZERO(&gdata.writeset); changehour=changemin=changesec=changequartersec=0; gettimeofday(×truct, NULL); last250ms = gdata.curtimems; gdata.curtimems = timeval_to_ms(×truct); ioutput(OUT_S|OUT_L|OUT_D, COLOR_NO_COLOR, "Startup" " running: %ld ms", (long)(gdata.curtimems - last250ms)); gdata.curtime = timestruct.tv_sec; lasttime=gdata.curtime; last250ms = gdata.curtimems; lastmin=(lasttime/60)-1; lasthour=(lasttime/60/60)-1; last4sec = last5sec = last20sec = last2min = last3min = lasttime; lastignoredec = lasttime; for (ss=0; ss<gdata.networks_online; ss++) { gdata.networks[ss].lastnotify = lasttime; gdata.networks[ss].lastslow = lasttime; gdata.networks[ss].server_input_line[0] = '\0'; } gdata.cursendptr = 0; lastautoadd = gdata.curtime + 60; first_loop = 0; } updatecontext(); FD_ZERO(&gdata.readset); FD_ZERO(&gdata.writeset); FD_ZERO(&gdata.execset); highests = 0; #ifdef USE_CURL fetch_multi_fdset(&gdata.readset, &gdata.writeset, &gdata.execset, &highests); #endif /* USE_CURL */ highests = irc_select(highests); if (!gdata.background) { FD_SET(fileno(stdin), &gdata.readset); highests = max2(highests, fileno(stdin)); } highests = chat_select_fdset(highests); highests = t_select_fdset(highests, changequartersec); highests = l_select_fdset(highests, changequartersec); #ifndef WITHOUT_TELNET highests = telnet_select_fdset(highests); #endif /* WITHOUT_TELNET */ #ifndef WITHOUT_HTTP highests = h_select_fdset(highests, changequartersec); #endif /* WITHOUT_HTTP */ if (gdata.md5build.file_fd != FD_UNUSED) { assert(gdata.md5build.xpack); FD_SET(gdata.md5build.file_fd, &gdata.readset); highests = max2(highests, gdata.md5build.file_fd); } updatecontext(); if (gdata.debug > 81) { select_dump("try", highests); } if (gdata.attop) gotobot(); tostdout_write(); gettimeofday(×truct, NULL); gdata.selecttimems = timeval_to_ms(×truct); if (ir_kqueue_select(highests+1, &gdata.readset, &gdata.writeset, &gdata.execset) < 0) { if (errno != EINTR) { outerror(OUTERROR_TYPE_WARN,"Select returned an error: %s",strerror(errno)); usleep(10000); /* prevent fast spinning */ } /* data is undefined on error, zero and continue */ FD_ZERO(&gdata.readset); FD_ZERO(&gdata.writeset); FD_ZERO(&gdata.execset); } if (gdata.debug > 81) { select_dump("got", highests); } /*----- one second check ----- */ updatecontext(); if (gettimeofday(×truct, NULL) < 0) { outerror(OUTERROR_TYPE_CRASH,"gettimeofday() failed! %s\n",strerror(errno)); } gdata.curtimems = timeval_to_ms(×truct); gdata.curtime = timestruct.tv_sec; if (gdata.curtimems > gdata.selecttimems + 1000) outerror(OUTERROR_TYPE_WARN, "Iroffer was blocked for %lims", (long)(gdata.curtimems - gdata.selecttimems)); /* adjust for drift and cpu usage */ if ((gdata.curtimems > (last250ms+1000)) || (gdata.curtimems < last250ms)) { /* skipped forward or backwards, correct */ last250ms = gdata.curtimems-250; } if (gdata.curtimems >= (last250ms+250)) { changequartersec = 1; /* note bandwidth limiting requires no drift! */ last250ms += 250; } else { changequartersec = 0; } changesec = 0; if (gdata.curtime != lasttime) { if (gdata.curtime < lasttime - MAX_WAKEUP_WARN) { outerror(OUTERROR_TYPE_WARN, "System Time Changed Backwards %lim %lis!!\n", (long)(lasttime-gdata.curtime)/60, (long)(lasttime-gdata.curtime)%60); } if (gdata.curtime > lasttime + MAX_WAKEUP_WARN) { outerror(OUTERROR_TYPE_WARN, "System Time Changed Forward or Mainloop Skipped %lim %lis!!\n", (long)(gdata.curtime-lasttime)/60, (long)(gdata.curtime-lasttime)%60); if (gdata.debug > 0) { dump_slow_context(); } } if (gdata.curtime > lasttime + MAX_WAKEUP_ERR) { outerror(OUTERROR_TYPE_WARN, "System Time Changed Forward or Mainloop Skipped %lim %lis!!\n", (long)(gdata.curtime-lasttime)/60, (long)(gdata.curtime-lasttime)%60); if (gdata.debug > 0) { dumpcontext(); } } lasttime = gdata.curtime; changesec = 1; } if (changesec && lasttime/60/60 != lasthour) { lasthour = lasttime/60/60; changehour = 1; } if (changesec && lasttime/60 != lastmin) { lastmin = lasttime/60; changemin = 1; } if (gdata.needsshutdown) { gdata.needsshutdown = 0; shutdowniroffer(); } if (gdata.needsreap) { gdata.needsreap = 0; irc_resolved(); } #ifdef USE_CURL fetch_perform(); #endif /* USE_CURL */ updatecontext(); if (changesec) { gdata.totaluptime++; gdata.xdccsent[(gdata.curtime+1)%XDCC_SENT_SIZE] = 0; gdata.xdccrecv[(gdata.curtime+1)%XDCC_SENT_SIZE] = 0; xdccsent = 0; for (i=0; i<XDCC_SENT_SIZE; i++) xdccsent += (ir_uint64)gdata.xdccsum[i]; if (((float)xdccsent)/XDCC_SENT_SIZE/1024.0 > gdata.sentrecord) gdata.sentrecord = ((float)xdccsent)/XDCC_SENT_SIZE/1024.0; gdata.xdccsum[(gdata.curtime+1)%XDCC_SENT_SIZE] = 0; run_delayed_jobs(); } updatecontext(); /*----- see if anything waiting on console ----- */ gdata.needsclear = 0; if (!gdata.background && FD_ISSET(fileno(stdin), &gdata.readset)) parseconsole(); irc_perform(changesec); l_perform(changesec); chat_perform(); t_perform(changesec, changequartersec); #ifndef WITHOUT_TELNET telnet_perform(); #endif /* WITHOUT_TELNET */ #ifndef WITHOUT_HTTP h_perform(changesec, changequartersec); #endif /* WITHOUT_HTTP */ /*----- time for a delayed shutdown? ----- */ if (changesec && gdata.delayedshutdown) { if (!irlist_size(&gdata.trans)) { ioutput(OUT_S|OUT_L|OUT_D, COLOR_NO_COLOR, "Delayed Shutdown Activated, No Transfers Remaining"); shutdowniroffer(); } } updatecontext(); for (ss=0; ss<gdata.networks_online; ss++) { gnetwork = &(gdata.networks[ss]); /*----- send server stuff ----- */ if (changesec) { sendserver(); if (gdata.curtime%INAMNT_SIZE == (INAMNT_SIZE-1)) gnetwork->inamnt[0] = 0; else gnetwork->inamnt[gdata.curtime%INAMNT_SIZE+1] = 0; } /*----- see if we can send out some xdcc lists */ if (changesec && gnetwork->serverstatus == SERVERSTATUS_CONNECTED) { if (!irlist_size((&gnetwork->serverq_normal)) && !irlist_size(&(gnetwork->serverq_slow))) sendxdlqueue(); } } gnetwork = NULL; /*----- see if its time to change maxb */ if (changehour) { gdata.maxb = gdata.overallmaxspeed; if (gdata.overallmaxspeeddayspeed != gdata.overallmaxspeed) { struct tm *localt; localt = localtime(&gdata.curtime); if ((unsigned int)localt->tm_hour >= gdata.overallmaxspeeddaytimestart && (unsigned int)localt->tm_hour < gdata.overallmaxspeeddaytimeend && ( gdata.overallmaxspeeddaydays & (1 << (unsigned int)localt->tm_wday)) ) gdata.maxb = gdata.overallmaxspeeddayspeed; } isrotatelog(); expire_options(); } /*----- see if we've hit a transferlimit or need to reset counters */ if (changesec) { unsigned int ii; unsigned int transferlimits_over = 0; for (ii=0; ii<NUMBER_TRANSFERLIMITS; ii++) { /* reset counters? */ if ((!gdata.transferlimits[ii].ends) || (gdata.transferlimits[ii].ends < gdata.curtime)) { struct tm *localt; if (gdata.transferlimits[ii].limit && gdata.transferlimits[ii].ends) { ioutput(OUT_S|OUT_L|OUT_D, COLOR_NO_COLOR, "Resetting %s transfer limit, used %" LLPRINTFMT "uMB of the %" LLPRINTFMT "uMB limit", transferlimit_type_to_string(ii), gdata.transferlimits[ii].used / 1024 / 1024, gdata.transferlimits[ii].limit / 1024 / 1024); } /* find our next end time */ localt = localtime(&gdata.curtime); localt->tm_sec = localt->tm_min = localt->tm_hour = 0; /* midnight */ switch (ii) { case TRANSFERLIMIT_DAILY: /* tomorrow */ localt->tm_mday++; break; case TRANSFERLIMIT_WEEKLY: /* next sunday morning */ localt->tm_mday += 7 - localt->tm_wday; break; case TRANSFERLIMIT_MONTHLY: /* next month */ localt->tm_mday = gdata.start_of_month; localt->tm_mon++; break; default: outerror(OUTERROR_TYPE_CRASH, "unknown type %u", ii); } /* tm_wday and tm_yday are ignored in mktime() */ gdata.transferlimits[ii].ends = mktime(localt); gdata.transferlimits[ii].used = 0; if ( ii == TRANSFERLIMIT_DAILY ) reset_download_limits(); } if (!transferlimits_over && gdata.transferlimits[ii].limit && (gdata.transferlimits[ii].used >= gdata.transferlimits[ii].limit)) { transferlimits_over = 1 + ii; if (!gdata.transferlimits_over) { char *tempstr = transfer_limit_exceeded_msg(ii); ioutput(OUT_S|OUT_L|OUT_D, COLOR_NO_COLOR, "All %" LLPRINTFMT "uMB of the %s transfer limit used. Stopping transfers.", gdata.transferlimits[ii].limit / 1024 / 1024, transferlimit_type_to_string(ii)); /* remove queued users */ queue_all_remove(&gdata.mainqueue, tempstr); queue_all_remove(&gdata.idlequeue, tempstr); /* stop transfers */ for (tr = irlist_get_head(&gdata.trans); tr; tr = irlist_get_next(tr)) { if (tr->tr_status != TRANSFER_STATUS_DONE) { gnetwork = &(gdata.networks[tr->net]); t_closeconn(tr,tempstr,0); } } gnetwork = NULL; mydelete(tempstr); } } } if (gdata.transferlimits_over != transferlimits_over) { if (!transferlimits_over) { ioutput(OUT_S|OUT_L|OUT_D, COLOR_NO_COLOR, "No longer over any transfer limits. Transfers are now allowed."); } gdata.transferlimits_over = transferlimits_over; } } /*----- gdata.autoignore_threshold seconds ----- */ if (changesec && ((unsigned)gdata.curtime > (lastignoredec + gdata.autoignore_threshold))) { igninfo *ignore; lastignoredec += gdata.autoignore_threshold; ignore = irlist_get_head(&gdata.ignorelist); while(ignore) { ignore->bucket--; if ((ignore->flags & IGN_IGNORING) && (ignore->bucket == 0)) { ignore->flags &= ~IGN_IGNORING; ioutput(OUT_S|OUT_L|OUT_D, COLOR_NO_COLOR, "Ignore removed for %s",ignore->hostmask); write_statefile(); } if (ignore->bucket == 0) { mydelete(ignore->hostmask); ignore = irlist_delete(&gdata.ignorelist, ignore); } else { ignore = irlist_get_next(ignore); } } } /*----- periodicmsg_time seconds ----- */ if (changesec) { send_periodicmsg(); } updatecontext(); /*----- 5 seconds ----- */ if (changesec && (gdata.curtime - last5sec > 4)) { last5sec = gdata.curtime; updatecontext(); /*----- server timeout ----- */ for (ss=0; ss<gdata.networks_online; ss++) { gnetwork = &(gdata.networks[ss]); if (gdata.needsshutdown) continue; if ((gnetwork->serverstatus == SERVERSTATUS_CONNECTED) && (gdata.curtime > gnetwork->lastservercontact + SRVRTOUT)) { if (gnetwork->servertime < 3) { const char *servname = gnetwork->curserveractualname ? gnetwork->curserveractualname : gnetwork->curserver.hostname; size_t len = 6 + strlen(servname); char *tempstr3 = mymalloc(len + 1); snprintf(tempstr3, len + 1, "PING %s\n", servname); writeserver_ssl(tempstr3, len); if (gdata.debug > 0) { tempstr3[len-1] = '\0'; len--; ioutput(OUT_S, COLOR_MAGENTA, "<NORES<: %s", tempstr3); } mydelete(tempstr3); gnetwork->servertime++; } else if (gnetwork->servertime == 3) { ioutput(OUT_S|OUT_L|OUT_D, COLOR_RED, "Closing Server Connection on %s: No Response for %u minutes.", gnetwork->name, SRVRTOUT/60); close_server(); gnetwork->servertime = 0; } } /*----- ping server ----- */ if (gnetwork->recentsent) { pingserver(); gnetwork->recentsent--; } } } /* networks */ gnetwork = NULL; /*----- 4 seconds ----- */ if (changesec && (gdata.curtime - last4sec > 3)) { /*----- update lastspeed, check minspeed ----- */ tr = irlist_get_head(&gdata.trans); while(tr) { if ( tr->con.connecttime+(MIN_TL/2) > gdata.curtime ) /* initial */ { tr->lastspeed = (tr->lastspeed)*DCL_SPDW_I + (((float)(tr->bytessent-tr->lastspeedamt))/1024.0)*(1.0-DCL_SPDW_I)/((float)(gdata.curtime-last4sec)*1.0); } else /* ongoing */ { tr->lastspeed = (tr->lastspeed)*DCL_SPDW_O + (((float)(tr->bytessent-tr->lastspeedamt))/1024.0)*(1.0-DCL_SPDW_O)/((float)(gdata.curtime-last4sec)*1.0); } tr->lastspeedamt = tr->bytessent; t_checkminspeed(tr); tr = irlist_get_next(tr); } ul = irlist_get_head(&gdata.uploads); while(ul) { if ( ul->con.connecttime+(MIN_TL/2) > gdata.curtime ) /* initial */ { ul->lastspeed = (ul->lastspeed)*DCL_SPDW_I + (((float)(ul->bytesgot-ul->lastspeedamt))/1024.0)*(1.0-DCL_SPDW_I)/((float)(gdata.curtime-last4sec)*1.0); } else /* ongoing */ { ul->lastspeed = (ul->lastspeed)*DCL_SPDW_O + (((float)(ul->bytesgot-ul->lastspeedamt))/1024.0)*(1.0-DCL_SPDW_O)/((float)(gdata.curtime-last4sec)*1.0); } ul->lastspeedamt = ul->bytesgot; ul = irlist_get_next(ul); } last4sec = gdata.curtime; } updatecontext(); /*----- check for size change ----- */ if (changesec) checktermsize(); updatecontext(); for (ss=0; ss<gdata.networks_online; ss++) { gnetwork = &(gdata.networks[ss]); /*----- plist stuff ----- */ if ((gnetwork->serverstatus == SERVERSTATUS_CONNECTED) && changemin && irlist_size(&gdata.xdccs) && !gdata.transferlimits_over && (irlist_size(&(gnetwork->serverq_channel)) < irlist_size(&gdata.xdccs)) && (!gdata.queuesize || irlist_size(&gdata.mainqueue) < gdata.queuesize) && (gdata.nolisting <= gdata.curtime)) { char *tchanf = NULL, *tchanm = NULL, *tchans = NULL; for(ch = irlist_get_head(&(gnetwork->channels)); ch; ch = irlist_get_next(ch)) { if ((ch->flags & CHAN_ONCHAN) && (ch->nextann < gdata.curtime) && ch->plisttime && (((gdata.curtime / 60) % ch->plisttime) == ch->plistoffset)) { ch->nextmsg = gdata.curtime + ch->delay; if (ch->pgroup != NULL) { ioutput(OUT_S|OUT_D, COLOR_NO_COLOR, "Plist sent to %s (pgroup)", ch->name); pubplist = mycalloc(sizeof(userinput)); pubplist->method = method_xdl_channel; pubplist->net = gnetwork->net; pubplist->level = ADMIN_LEVEL_PUBLIC; a_fillwith_plist(pubplist, ch->name, ch); u_parseit(pubplist); mydelete(pubplist); continue; } if (ch->flags & CHAN_MINIMAL) { if (tchanm) { strncat(tchanm,",",maxtextlength-strlen(tchanm)-1); strncat(tchanm,ch->name,maxtextlength-strlen(tchanm)-1); } else { tchanm = mymalloc(maxtextlength); strncpy(tchanm,ch->name,maxtextlength-1); } } else if (ch->flags & CHAN_SUMMARY) { if (tchans) { strncat(tchans,",",maxtextlength-strlen(tchans)-1); strncat(tchans,ch->name,maxtextlength-strlen(tchans)-1); } else { tchans = mymalloc(maxtextlength); strncpy(tchans,ch->name,maxtextlength-1); } } else { if (tchanf) { strncat(tchanf,",",maxtextlength-strlen(tchanf)-1); strncat(tchanf,ch->name,maxtextlength-strlen(tchanf)-1); } else { tchanf = mymalloc(maxtextlength); strncpy(tchanf,ch->name,maxtextlength-1); } } } } if (tchans) { if (gdata.restrictprivlist && !gdata.creditline && !irlist_size(&gdata.headline)) { ioutput(OUT_S|OUT_D, COLOR_NO_COLOR, "Can't send Summary Plist to %s (restrictprivlist is set and no creditline or headline, summary makes no sense!)", tchans); } else { ioutput(OUT_S|OUT_D, COLOR_NO_COLOR, "Plist sent to %s (summary)", tchans); pubplist = mycalloc(sizeof(userinput)); a_fillwith_msg2(pubplist, tchans, "XDL"); pubplist->method = method_xdl_channel_sum; u_parseit(pubplist); mydelete(pubplist); } mydelete(tchans); } if (tchanf) { ioutput(OUT_S|OUT_D, COLOR_NO_COLOR, "Plist sent to %s (full)", tchanf); pubplist = mycalloc(sizeof(userinput)); a_fillwith_plist(pubplist, tchanf, NULL); pubplist->method = method_xdl_channel; u_parseit(pubplist); mydelete(pubplist); mydelete(tchanf); } if (tchanm) { ioutput(OUT_S|OUT_D, COLOR_NO_COLOR, "Plist sent to %s (minimal)", tchanm); pubplist = mycalloc(sizeof(userinput)); a_fillwith_msg2(pubplist, tchanm, "XDL"); pubplist->method = method_xdl_channel_min; u_parseit(pubplist); mydelete(pubplist); mydelete(tchanm); } } } /* networks */ gnetwork = NULL; updatecontext(); /*----- low bandwidth send, save state file ----- */ if (changesec && (gdata.curtime - last3min > 180)) { last3min = gdata.curtime; xdccsent = 0; for (i=0; i<XDCC_SENT_SIZE; i++) xdccsent += (ir_uint64)gdata.xdccsent[i]; xdccsent /= XDCC_SENT_SIZE*1024; if ((xdccsent < (unsigned)gdata.lowbdwth) && !gdata.exiting && irlist_size(&gdata.mainqueue) && (irlist_size(&gdata.trans) < gdata.maxtrans)) { check_idle_queue(0); send_from_queue(1, 0, NULL); } write_files(); } updatecontext(); for (ss=0; ss<gdata.networks_online; ss++) { gnetwork = &(gdata.networks[ss]); /*----- queue notify ----- */ if (changesec && gdata.notifytime && (!gdata.quietmode) && ((unsigned)gdata.curtime > (gnetwork->lastnotify + (gdata.notifytime*60)))) { gnetwork->lastnotify = gdata.curtime; if (gnetwork->serverstatus == SERVERSTATUS_CONNECTED) { if ((irlist_size(&(gnetwork->serverq_fast)) >= 10) || (irlist_size(&(gnetwork->serverq_normal)) >= 10) || (irlist_size(&(gnetwork->serverq_slow)) >= 50)) { ioutput(OUT_S|OUT_D|OUT_L, COLOR_NO_COLOR, "notifications skipped on %s, server queue is rather large", gnetwork->name); } else { notifyqueued(); notifybandwidth(); notifybandwidthtrans(); } } } } /* networks */ gnetwork = NULL; updatecontext(); /*----- log stats / remote admin stats ----- */ if ( changesec && ((unsigned)gdata.curtime >= (last2min + gdata.status_time_dcc_chat))) { last2min = gdata.curtime; if (gdata.logstats) { logstat(); chat_writestatus(); } } updatecontext(); /* look to see if any files changed */ if (changesec) look_for_file_remove(); updatecontext(); /*----- 20 seconds ----- */ if (changesec && (gdata.curtime - last20sec > 19)) { expire_badip(); if (gdata.logfd != FD_UNUSED) { /* cycle */ close(gdata.logfd); gdata.logfd = FD_UNUSED; } updatecontext(); for (ss=0; ss<gdata.networks_online; ss++) { gnetwork = &(gdata.networks[ss]); /* try rejoining channels not on */ ch = irlist_get_head(&(gnetwork->channels)); while(ch) { if ((gnetwork->serverstatus == SERVERSTATUS_CONNECTED) && !(ch->flags & CHAN_ONCHAN)) { joinchannel(ch); } ch = irlist_get_next(ch); } } /* networks */ gnetwork = NULL; last20sec = gdata.curtime; updatecontext(); for (ss=0; ss<gdata.networks_online; ss++) { gnetwork = &(gdata.networks[ss]); /* try to regain nick */ if (!gnetwork->user_nick || strcmp(get_config_nick(), gnetwork->user_nick)) { writeserver(WRITESERVER_NORMAL, "NICK %s", get_config_nick()); } } /* networks */ gnetwork = NULL; updatecontext(); /* update status line */ if (!gdata.background && !gdata.noscreen) { char tempstr[maxtextlength]; char tempstr2[maxtextlengthshort]; if (gdata.attop) gotobot(); tostdout(IRVT_SAVE_CURSOR); getstatusline(tempstr,maxtextlength); tempstr[min2(maxtextlength-2,gdata.termcols-4)] = '\0'; snprintf(tempstr2, maxtextlengthshort, IRVT_CURSOR_HOME1 "[ %%-%us ]", gdata.termlines - 1, gdata.termcols - 4); tostdout(tempstr2,tempstr); tostdout(IRVT_CURSOR_HOME2 IRVT_UNSAVE_CURSOR, gdata.termlines, gdata.termcols); } admin_jobs(); #ifdef USE_RUBY rehash_myruby(1); #endif /* USE_RUBY */ delayed_announce(); } updatecontext(); if (changemin) { reverify_restrictsend(); update_hour_dinoex(lastmin); check_idle_queue(0); clean_uploadhost(); auto_rehash(); } updatecontext(); if ((gdata.md5build.file_fd != FD_UNUSED) && FD_ISSET(gdata.md5build.file_fd, &gdata.readset)) { ssize_t howmuch; #if defined(_OS_CYGWIN) int reads_per_loop = 32; #else /* _OS_CYGWIN */ int reads_per_loop = 64; #endif /* _OS_CYGWIN */ assert(gdata.md5build.xpack); while (reads_per_loop--) { howmuch = read(gdata.md5build.file_fd, gdata.sendbuff, BUFFERSIZE); if (gdata.debug >30) { ioutput(OUT_S, COLOR_YELLOW, "MD5: [Pack %u] read %ld", number_of_pack(gdata.md5build.xpack), (long)howmuch); } if ((howmuch < 0) && (errno != EAGAIN)) { outerror(OUTERROR_TYPE_WARN, "MD5: [Pack %u] Can't read data from file '%s': %s", number_of_pack(gdata.md5build.xpack), gdata.md5build.xpack->file, strerror(errno)); event_close(gdata.md5build.file_fd); gdata.md5build.file_fd = FD_UNUSED; gdata.md5build.xpack = NULL; break; } else if (howmuch < 0) { break; } else if (howmuch == 0) { /* EOF */ outerror(OUTERROR_TYPE_WARN, "MD5: [Pack %u] Can't read data from file '%s': %s", number_of_pack(gdata.md5build.xpack), gdata.md5build.xpack->file, "truncated"); start_md5_hash(gdata.md5build.xpack, number_of_pack(gdata.md5build.xpack)); break; } /* else got data */ MD5Update(&gdata.md5build.md5sum, gdata.sendbuff, howmuch); if (!gdata.nocrc32) crc32_update((char *)gdata.sendbuff, howmuch); gdata.md5build.bytes += howmuch; if (gdata.md5build.bytes == gdata.md5build.xpack->st_size) { complete_md5_hash(); break; } } } if (!gdata.nomd5sum && changesec && (!gdata.md5build.xpack)) { unsigned int packnum = 1; /* see if any pack needs a md5sum calculated */ if (gdata.nomd5_start <= gdata.curtime) for (xd = irlist_get_head(&gdata.xdccs); xd; xd = irlist_get_next(xd), packnum++) { if (!gdata.nocrc32) { if (!xd->has_crc32) xd->has_md5sum = 0; /* force recheck with crc */ } if (!xd->has_md5sum) { if (verifyshell(&gdata.md5sum_exclude, xd->file)) continue; if (!gdata.attop) gototop(); start_md5_hash(xd, packnum); break; } } } updatecontext(); if (gdata.exiting && has_closed_servers()) { for (chat = irlist_get_head(&gdata.dccchats); chat; chat = irlist_delete(&gdata.dccchats,chat)) { writedccchat(chat, 0, "iroffer exited, Closing DCC Chat\n"); shutdowndccchat(chat,1); } mylog("iroffer exited\n\n"); exit_iroffer(0); } updatecontext(); if (gdata.needsrehash) { gdata.needsrehash = 0; urehash = mycalloc(sizeof(userinput)); a_fillwith_msg2(urehash, NULL, "REHASH"); urehash->method = method_out_all; /* just OUT_S|OUT_L|OUT_D it */ urehash->net = 0; urehash->level = ADMIN_LEVEL_FULL; u_parseit(urehash); mydelete(urehash); } updatecontext(); chat = irlist_get_head(&gdata.dccchats); while (chat) { if (chat->status == DCCCHAT_UNUSED) { chat = irlist_delete(&gdata.dccchats,chat); } else { flushdccchat(chat); chat = irlist_get_next(chat); } } if (gdata.autoadd_time > 0) { if (changesec && ((unsigned)gdata.curtime > (lastautoadd + gdata.autoadd_time))) { lastautoadd = gdata.curtime; autoadd_all(); } } /* END */ updatecontext(); if (gdata.needsclear) drawbot(); changehour=changemin=0; }
/* Fill TCP header */ skb->h.th->psh = (len == 0); tcp_set_ack_field(skb->h.th, tcp_sk->rem.seq); send_seq_from_sock(tcp_sk, skb); } return pb - buff; } #if MAX_SIMULTANEOUS_TX_PACK > 0 static int tcp_wait_tx_ready(struct sock *sk, int timeout) { int ret; ret = 0; sched_lock(); { while (MAX_SIMULTANEOUS_TX_PACK <= skb_queue_count(&sk->tx_queue)) { ret = sock_wait(sk, POLLOUT | POLLERR, timeout); if (ret < 0) { break; } } } sched_unlock(); return ret; } #else static inline int tcp_wait_tx_ready(struct sock *sk, int timeout) { return 0; } #endif #define REM_WIND_MAX_SIZE (1460 * 100) /* FIXME use txqueuelen for netdev */ static int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int flags) { struct tcp_sock *tcp_sk; size_t len; int ret, timeout; (void)flags; assert(sk); assert(msg); timeout = timeval_to_ms(&sk->opt.so_sndtimeo); if (timeout == 0) { timeout = SCHED_TIMEOUT_INFINITE; } tcp_sk = to_tcp_sock(sk); debug_print(3, "tcp_sendmsg: sk %p\n", to_sock(tcp_sk)); sendmsg_again: assert(tcp_sk->state < TCP_MAX_STATE); switch (tcp_sk->state) { default: return -ENOTCONN; case TCP_SYN_SENT: case TCP_SYN_RECV: sched_lock(); { ret = sock_wait(sk, POLLOUT | POLLERR, timeout); } sched_unlock(); if (ret != 0) { return ret; } goto sendmsg_again; case TCP_ESTABIL: case TCP_CLOSEWAIT: sched_lock(); { while ((min(tcp_sk->rem.wind.size, REM_WIND_MAX_SIZE) <= tcp_sk->self.seq - tcp_sk->last_ack) || tcp_sk->rexmit_mode) { ret = sock_wait(sk, POLLOUT | POLLERR, timeout); if (ret != 0) { sched_unlock(); return ret; } } } sched_unlock(); len = tcp_write(tcp_sk, msg->msg_iov->iov_base, msg->msg_iov->iov_len); ret = tcp_wait_tx_ready(sk, timeout); if (0 > ret) { return ret; } return len; case TCP_FINWAIT_1: case TCP_FINWAIT_2: case TCP_CLOSING: case TCP_LASTACK: case TCP_TIMEWAIT: return -EPIPE; } }
static uint64_t get_raw_ms(void) { struct timeval tv; gettimeofday(&tv, NULL); return timeval_to_ms(&tv); }
void test_timeval_to_ms() { TS_ASSERT_EQUALS(0, timeval_to_ms(zero)); TS_ASSERT_EQUALS(1900, timeval_to_ms(a)); TS_ASSERT_EQUALS(2100, timeval_to_ms(b)); TS_ASSERT_EQUALS(4000, timeval_to_ms(c)); }
int qemuMigrationPrepareDirect(struct qemud_driver *driver, virConnectPtr dconn, const char *uri_in, char **uri_out, const char *dname, const char *dom_xml) { static int port = 0; virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; int this_port; char *hostname = NULL; char migrateFrom [64]; const char *p; virDomainEventPtr event = NULL; int ret = -1; int internalret; qemuDomainObjPrivatePtr priv = NULL; struct timeval now; if (gettimeofday(&now, NULL) < 0) { virReportSystemError(errno, "%s", _("cannot get time of day")); return -1; } /* The URI passed in may be NULL or a string "tcp://somehostname:port". * * If the URI passed in is NULL then we allocate a port number * from our pool of port numbers and return a URI of * "tcp://ourhostname:port". * * If the URI passed in is not NULL then we try to parse out the * port number and use that (note that the hostname is assumed * to be a correct hostname which refers to the target machine). */ if (uri_in == NULL) { this_port = QEMUD_MIGRATION_FIRST_PORT + port++; if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0; /* Get hostname */ if ((hostname = virGetHostname(NULL)) == NULL) goto cleanup; if (STRPREFIX(hostname, "localhost")) { qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("hostname on destination resolved to localhost, but migration requires an FQDN")); goto cleanup; } /* XXX this really should have been a properly well-formed * URI, but we can't add in tcp:// now without breaking * compatability with old targets. We at least make the * new targets accept both syntaxes though. */ /* Caller frees */ internalret = virAsprintf(uri_out, "tcp:%s:%d", hostname, this_port); if (internalret < 0) { virReportOOMError(); goto cleanup; } } else { /* Check the URI starts with "tcp:". We will escape the * URI when passing it to the qemu monitor, so bad * characters in hostname part don't matter. */ if (!STRPREFIX (uri_in, "tcp:")) { qemuReportError (VIR_ERR_INVALID_ARG, "%s", _("only tcp URIs are supported for KVM/QEMU migrations")); goto cleanup; } /* Get the port number. */ p = strrchr (uri_in, ':'); if (p == strchr(uri_in, ':')) { /* Generate a port */ this_port = QEMUD_MIGRATION_FIRST_PORT + port++; if (port == QEMUD_MIGRATION_NUM_PORTS) port = 0; /* Caller frees */ if (virAsprintf(uri_out, "%s:%d", uri_in, this_port) < 0) { virReportOOMError(); goto cleanup; } } else { p++; /* definitely has a ':' in it, see above */ this_port = virParseNumber (&p); if (this_port == -1 || p-uri_in != strlen (uri_in)) { qemuReportError(VIR_ERR_INVALID_ARG, "%s", _("URI ended with incorrect ':port'")); goto cleanup; } } } if (*uri_out) VIR_DEBUG("Generated uri_out=%s", *uri_out); /* Parse the domain XML. */ if (!(def = virDomainDefParseString(driver->caps, dom_xml, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; if (!qemuMigrationIsAllowed(def)) goto cleanup; /* Target domain name, maybe renamed. */ if (dname) { VIR_FREE(def->name); def->name = strdup(dname); if (def->name == NULL) goto cleanup; } if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) goto cleanup; if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, true))) { /* virDomainAssignDef already set the error */ goto cleanup; } def = NULL; priv = vm->privateData; if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; priv->jobActive = QEMU_JOB_MIGRATION_OUT; /* Domain starts inactive, even if the domain XML had an id field. */ vm->def->id = -1; /* Start the QEMU daemon, with the same command-line arguments plus * -incoming tcp:0.0.0.0:port */ snprintf (migrateFrom, sizeof (migrateFrom), "tcp:0.0.0.0:%d", this_port); if (qemuProcessStart(dconn, driver, vm, migrateFrom, true, -1, NULL, VIR_VM_OP_MIGRATE_IN_START) < 0) { qemuAuditDomainStart(vm, "migrated", false); /* Note that we don't set an error here because qemuProcessStart * should have already done that. */ if (!vm->persistent) { if (qemuDomainObjEndJob(vm) > 0) virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } goto endjob; } qemuAuditDomainStart(vm, "migrated", true); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_MIGRATED); ret = 0; endjob: if (vm && qemuDomainObjEndJob(vm) == 0) vm = NULL; /* We set a fake job active which is held across * API calls until the finish() call. This prevents * any other APIs being invoked while incoming * migration is taking place */ if (vm && virDomainObjIsActive(vm)) { priv->jobActive = QEMU_JOB_MIGRATION_IN; priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED; priv->jobStart = timeval_to_ms(now); } cleanup: VIR_FREE(hostname); virDomainDefFree(def); if (ret != 0) VIR_FREE(*uri_out); if (vm) virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); return ret; }
static long duration_ms(struct timeval *tv_end, struct timeval *tv_start) { return timeval_to_ms(tv_end) - timeval_to_ms(tv_start); }
long delta_time_ms (struct timeval *tv, struct timeval *last_tv) { return timeval_to_ms (tv) - timeval_to_ms (last_tv); }
int qemuMigrationWaitForCompletion(struct qemud_driver *driver, virDomainObjPtr vm) { int ret = -1; int status; unsigned long long memProcessed; unsigned long long memRemaining; unsigned long long memTotal; qemuDomainObjPrivatePtr priv = vm->privateData; priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED; while (priv->jobInfo.type == VIR_DOMAIN_JOB_UNBOUNDED) { /* Poll every 50ms for progress & to allow cancellation */ struct timespec ts = { .tv_sec = 0, .tv_nsec = 50 * 1000 * 1000ull }; struct timeval now; int rc; const char *job; switch (priv->jobActive) { case QEMU_JOB_MIGRATION_OUT: job = _("migration job"); break; case QEMU_JOB_SAVE: job = _("domain save job"); break; case QEMU_JOB_DUMP: job = _("domain core dump job"); break; default: job = _("job"); } if (!virDomainObjIsActive(vm)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, _("%s: %s"), job, _("guest unexpectedly quit")); goto cleanup; } if (priv->jobSignals & QEMU_JOB_SIGNAL_CANCEL) { priv->jobSignals ^= QEMU_JOB_SIGNAL_CANCEL; VIR_DEBUG0("Cancelling job at client request"); qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorMigrateCancel(priv->mon); qemuDomainObjExitMonitorWithDriver(driver, vm); if (rc < 0) { VIR_WARN0("Unable to cancel job"); } } else if (priv->jobSignals & QEMU_JOB_SIGNAL_SUSPEND) { priv->jobSignals ^= QEMU_JOB_SIGNAL_SUSPEND; VIR_DEBUG0("Pausing domain for non-live migration"); if (qemuMigrationSetOffline(driver, vm) < 0) VIR_WARN0("Unable to pause domain"); } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME) { unsigned long long ms = priv->jobSignalsData.migrateDowntime; priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_DOWNTIME; priv->jobSignalsData.migrateDowntime = 0; VIR_DEBUG("Setting migration downtime to %llums", ms); qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorSetMigrationDowntime(priv->mon, ms); qemuDomainObjExitMonitorWithDriver(driver, vm); if (rc < 0) VIR_WARN0("Unable to set migration downtime"); } else if (priv->jobSignals & QEMU_JOB_SIGNAL_MIGRATE_SPEED) { unsigned long bandwidth = priv->jobSignalsData.migrateBandwidth; priv->jobSignals ^= QEMU_JOB_SIGNAL_MIGRATE_SPEED; priv->jobSignalsData.migrateBandwidth = 0; VIR_DEBUG("Setting migration bandwidth to %luMbs", bandwidth); qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorSetMigrationSpeed(priv->mon, bandwidth); qemuDomainObjExitMonitorWithDriver(driver, vm); if (rc < 0) VIR_WARN0("Unable to set migration speed"); } /* Repeat check because the job signals might have caused * guest to die */ if (!virDomainObjIsActive(vm)) { qemuReportError(VIR_ERR_INTERNAL_ERROR, _("%s: %s"), job, _("guest unexpectedly quit")); goto cleanup; } qemuDomainObjEnterMonitorWithDriver(driver, vm); rc = qemuMonitorGetMigrationStatus(priv->mon, &status, &memProcessed, &memRemaining, &memTotal); qemuDomainObjExitMonitorWithDriver(driver, vm); if (rc < 0) { priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; goto cleanup; } if (gettimeofday(&now, NULL) < 0) { priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; virReportSystemError(errno, "%s", _("cannot get time of day")); goto cleanup; } priv->jobInfo.timeElapsed = timeval_to_ms(now) - priv->jobStart; switch (status) { case QEMU_MONITOR_MIGRATION_STATUS_INACTIVE: priv->jobInfo.type = VIR_DOMAIN_JOB_NONE; qemuReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"), job, _("is not active")); break; case QEMU_MONITOR_MIGRATION_STATUS_ACTIVE: priv->jobInfo.dataTotal = memTotal; priv->jobInfo.dataRemaining = memRemaining; priv->jobInfo.dataProcessed = memProcessed; priv->jobInfo.memTotal = memTotal; priv->jobInfo.memRemaining = memRemaining; priv->jobInfo.memProcessed = memProcessed; break; case QEMU_MONITOR_MIGRATION_STATUS_COMPLETED: priv->jobInfo.type = VIR_DOMAIN_JOB_COMPLETED; ret = 0; break; case QEMU_MONITOR_MIGRATION_STATUS_ERROR: priv->jobInfo.type = VIR_DOMAIN_JOB_FAILED; qemuReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"), job, _("unexpectedly failed")); break; case QEMU_MONITOR_MIGRATION_STATUS_CANCELLED: priv->jobInfo.type = VIR_DOMAIN_JOB_CANCELLED; qemuReportError(VIR_ERR_OPERATION_FAILED, _("%s: %s"), job, _("canceled by client")); break; } virDomainObjUnlock(vm); qemuDriverUnlock(driver); nanosleep(&ts, NULL); qemuDriverLock(driver); virDomainObjLock(vm); } cleanup: return ret; } /* Prepare is the first step, and it runs on the destination host. * * This version starts an empty VM listening on a localhost TCP port, and * sets up the corresponding virStream to handle the incoming data. */ int qemuMigrationPrepareTunnel(struct qemud_driver *driver, virConnectPtr dconn, virStreamPtr st, const char *dname, const char *dom_xml) { virDomainDefPtr def = NULL; virDomainObjPtr vm = NULL; virDomainEventPtr event = NULL; int ret = -1; int internalret; int dataFD[2] = { -1, -1 }; virBitmapPtr qemuCaps = NULL; qemuDomainObjPrivatePtr priv = NULL; struct timeval now; if (gettimeofday(&now, NULL) < 0) { virReportSystemError(errno, "%s", _("cannot get time of day")); return -1; } /* Parse the domain XML. */ if (!(def = virDomainDefParseString(driver->caps, dom_xml, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; if (!qemuMigrationIsAllowed(def)) goto cleanup; /* Target domain name, maybe renamed. */ if (dname) { VIR_FREE(def->name); def->name = strdup(dname); if (def->name == NULL) goto cleanup; } if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0) goto cleanup; if (!(vm = virDomainAssignDef(driver->caps, &driver->domains, def, true))) { /* virDomainAssignDef already set the error */ goto cleanup; } def = NULL; priv = vm->privateData; if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; priv->jobActive = QEMU_JOB_MIGRATION_OUT; /* Domain starts inactive, even if the domain XML had an id field. */ vm->def->id = -1; if (pipe(dataFD) < 0 || virSetCloseExec(dataFD[0]) < 0) { virReportSystemError(errno, "%s", _("cannot create pipe for tunnelled migration")); goto endjob; } /* check that this qemu version supports the interactive exec */ if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch, NULL, &qemuCaps) < 0) { qemuReportError(VIR_ERR_INTERNAL_ERROR, _("Cannot determine QEMU argv syntax %s"), vm->def->emulator); goto endjob; } /* Start the QEMU daemon, with the same command-line arguments plus * -incoming stdin (which qemu_command might convert to exec:cat or fd:n) */ internalret = qemuProcessStart(dconn, driver, vm, "stdin", true, dataFD[1], NULL, VIR_VM_OP_MIGRATE_IN_START); if (internalret < 0) { qemuAuditDomainStart(vm, "migrated", false); /* Note that we don't set an error here because qemuProcessStart * should have already done that. */ if (!vm->persistent) { virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } goto endjob; } if (virFDStreamOpen(st, dataFD[0]) < 0) { qemuAuditDomainStart(vm, "migrated", false); qemuProcessStop(driver, vm, 0); if (!vm->persistent) { if (qemuDomainObjEndJob(vm) > 0) virDomainRemoveInactive(&driver->domains, vm); vm = NULL; } virReportSystemError(errno, "%s", _("cannot pass pipe for tunnelled migration")); goto endjob; } qemuAuditDomainStart(vm, "migrated", true); event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED, VIR_DOMAIN_EVENT_STARTED_MIGRATED); ret = 0; endjob: if (vm && qemuDomainObjEndJob(vm) == 0) vm = NULL; /* We set a fake job active which is held across * API calls until the finish() call. This prevents * any other APIs being invoked while incoming * migration is taking place */ if (vm && virDomainObjIsActive(vm)) { priv->jobActive = QEMU_JOB_MIGRATION_IN; priv->jobInfo.type = VIR_DOMAIN_JOB_UNBOUNDED; priv->jobStart = timeval_to_ms(now); } cleanup: qemuCapsFree(qemuCaps); virDomainDefFree(def); VIR_FORCE_CLOSE(dataFD[0]); VIR_FORCE_CLOSE(dataFD[1]); if (vm) virDomainObjUnlock(vm); if (event) qemuDomainEventQueue(driver, event); qemuDriverUnlock(driver); return ret; }
ulong_t Solver::verify(const string& filename, int initial_q_param, int verbosity) { timeval time_start; gettimeofday(&time_start, NULL); if (problem_original != 0) delete problem_original; problem_original = new Problem(); Parser* parser = new Parser(); parser->read(filename, *problem_original); delete parser; make_problem_without_outputs(); if (verbosity > 0) { cout << "====================================" << endl; cout << "= Problem without outputs =" << endl; cout << "====================================" << endl; cout << *problem_without_outputs; } for (size_t i = 0; i < problem_without_outputs->get_variables_num(); ++i) { Variable& v = problem_without_outputs->get_variable(i); if (v.get_type() == Variable::REAL) q_params.insert(make_pair(v.get_name(), initial_q_param)); } make_problem_quantized(); if (verbosity > 0) { cout << "====================================" << endl; cout << "= Quantized problem =" << endl; cout << "====================================" << endl; cout << *problem_quantized; } make_problem_discrete(); if (verbosity > 0) { cout << "====================================" << endl; cout << "= Discrete problem =" << endl; cout << "====================================" << endl; cout << *problem_discrete; } make_problem_pb(); if (verbosity > 0) { cout << "====================================" << endl; cout << "= Pseudoboolean problem =" << endl; cout << "====================================" << endl; cout << *problem_pb; } make_model_smv(); if (verbosity > 0) { cout << "====================================" << endl; cout << "= SMV model =" << endl; cout << "====================================" << endl; cout << *model_smv; } verify_model_smv(); //bool stop = false; //while (stop != true) //{ //make_problem_quantized(); //make_problem_discrete(); //make_problem_pb(); //make_model_smv(); //while (true) //{ //if (verify_model_smv() == false) // If SMV model verification fails. //{ //if (check_counterexample() == true) // If counterexample is true. //{ //result = false; // Result is false. //stop = true; // Stop verification process. //break; //} //if (refine_model_smv() == false) // If refinement fails. //{ //change_q_params(); //break; //} //} //else // If SMV model verification succeeds. //{ //result = true; // Result is true. //stop = true; // Stop verification process. //break; //} //} //} timeval time_finish; gettimeofday(&time_finish, NULL); return timeval_to_ms(time_finish) - timeval_to_ms(time_start); }