void read_from(ReadSource in, Level& level) { read(in, level.netRaceFlags); read(in, level.playerNum); read(in, level.player, kMaxPlayerNum); read(in, level.scoreStringResID); read(in, level.initialFirst); read(in, level.prologueID); read(in, level.initialNum); read(in, level.songID); read(in, level.conditionFirst); read(in, level.epilogueID); read(in, level.conditionNum); read(in, level.starMapH); read(in, level.briefPointFirst); read(in, level.starMapV); read(in, level.briefPointNum); level.parTime = game_ticks(secs(read<int16_t>(in))); in.shift(2); read(in, level.parKills); read(in, level.levelNameStrNum); read(in, level.parKillRatio); read(in, level.parLosses); int16_t start_time = read<int16_t>(in); level.startTime = secs(start_time & kLevel_StartTimeMask); level.is_training = start_time & kLevel_IsTraining_Bit; }
static unsigned long reportingduration(time_t eventstart, time_t eventduration) { struct tm start, end; time_t eventend; unsigned long result; memcpy(&start, localtime(&eventstart), sizeof(start)); eventend = eventstart + eventduration; memcpy(&end, localtime(&eventend), sizeof(end)); if ((start.tm_mday == end.tm_mday) && (start.tm_mon == end.tm_mon) && (start.tm_year == end.tm_year)) result = reportduration_oneday(start.tm_wday, secs(start.tm_hour, start.tm_min, start.tm_sec), secs(end.tm_hour, end.tm_min, end.tm_sec)); else { int fulldays = (eventduration - (86400-secs(start.tm_hour, start.tm_min, start.tm_sec))) / 86400; int curdow = (start.tm_wday == 6) ? 0 : (start.tm_wday+1); result = reportduration_oneday(start.tm_wday, secs(start.tm_hour, start.tm_min, start.tm_sec), 86400); while (fulldays) { result += reportduration_oneday(curdow, 0, 86400); curdow = (curdow == 6) ? 0 : (curdow+1); fulldays--; } result += reportduration_oneday(curdow, 0, secs(end.tm_hour, end.tm_min, end.tm_sec)); } return result; }
void Timeval::operator+=(const DelayInterval& arg2) { secs() += arg2.seconds(); usecs() += arg2.useconds(); if (useconds() >= MILLION) { usecs() -= MILLION; ++secs(); } }
void Timeval::operator-=(const DelayInterval& arg2) { secs() -= arg2.seconds(); usecs() -= arg2.useconds(); if (usecs() < 0) { usecs() += MILLION; --secs(); } if (secs() < 0) secs() = usecs() = 0; }
ProcessTime ProcessTime::operator-(const ProcessTime& t) { ProcessTime &tt= (ProcessTime&)t; ProcessTime res; if (tt.nano_secs() > nano_secs()) { res._secs = secs() - tt.secs() - 1; res._nano_secs = one_billion - tt.nano_secs() + nano_secs(); } else { res._secs = secs() - tt.secs(); res._nano_secs = nano_secs() - tt.nano_secs(); } return res; }
struct timeval timeval() const { struct timeval t; t.tv_sec = secs(); t.tv_usec = us() - (t.tv_sec * MILLISECONDS); return t; }
int client(int argc, char* argv[]) { cxxtools::Arg<unsigned short> port(argc, argv, 'p', 1234); cxxtools::Arg<const char*> ip(argc, argv, 'i', "127.0.0.1"); cxxtools::Arg<unsigned> secs(argc, argv, 't', 1); cxxtools::Arg<unsigned> bufsize(argc, argv, 't', BUFSIZE); cxxtools::Arg<unsigned> B(argc, argv, 'B', 0); cxxtools::net::Stream conn(ip.getValue(), port); cxxtools::Dynbuffer<char> buffer(bufsize); std::generate(buffer.begin(), buffer.end(), rand); std::cout << "test" << std::endl; if (B.isSet()) run_test(conn, B, buffer.data(), secs); else { for (unsigned bs=256; bs <= bufsize.getValue(); bs <<= 1) run_test(conn, bs, buffer.data(), secs); } return 0; }
int client(int argc, char* argv[]) { cxxtools::Arg<unsigned short> port(argc, argv, 'p', 1234); cxxtools::Arg<const char*> ip(argc, argv, 'i'); cxxtools::Arg<unsigned> secs(argc, argv, 't', 1); cxxtools::Arg<unsigned> bufsize(argc, argv, 't', BUFSIZE); cxxtools::Arg<unsigned> B(argc, argv, 'B', 0); cxxtools::net::TcpSocket conn(ip.getValue(), port); std::vector<char> buffer(bufsize); std::generate(&buffer[0], &buffer[bufsize], rand); std::cout << "test" << std::endl; if (B.isSet()) run_test(conn, B, &buffer[0], secs); else { for (unsigned bs=256; bs <= bufsize.getValue(); bs <<= 1) run_test(conn, bs, &buffer[0], secs); } return 0; }
void SelectLevelScreen::handle_button(Button& button) { switch (button.id) { case OK: _state = FADING_OUT; *_cancelled = false; stack()->push( new ColorFade(ColorFade::TO_COLOR, RgbColor::black(), secs(1), false, NULL)); break; case CANCEL: *_cancelled = true; stack()->pop(this); break; case PREVIOUS: if (_index > 0) { --_index; *_level = Handle<Level>(_chapters[_index] - 1); } adjust_interface(); break; case NEXT: if (_index < _chapters.size() - 1) { ++_index; *_level = Handle<Level>(_chapters[_index] - 1); } adjust_interface(); break; default: throw Exception(format("Got unknown button {0}.", button.id)); } }
void ntpdtest::settime(int y, int m, int d, int H, int M, int S) { time_t days(ntpcal_edate_to_eradays(y-1, m-1, d-1) + 1 - DAY_UNIX_STARTS); time_t secs(ntpcal_etime_to_seconds(H, M, S)); nowtime = days * SECSPERDAY + secs; }
/** * web100clt currently (as of 2015-12-21) requires that its output queue be * drained at the end of the c2s test and hangs if it is not. We don't want to * break it, but that extra second or so should not be part of our measured * transmitted data, because the spec says that it's a 10 second upload from * client to server, not a "10 seconds or a little bit more depending on when * the client starts counting" upload. Therefore, here we read from the * sockets for just a little longer, but ignore the resulting data, so that old * clients don't hang, but newer clients are not penalized for quitting after * 10 seconds, just like the spec says they can. * * TODO: Fix web100clt to eliminate the need for this function. * TODO: Make this function happen in a separate thread (but not a forked * subprocess due to SSL issues). That way old clients being dumb doesn't * slow down new clients' tests. Currently it wastes 1 second per test, * which at 150k tests per day is a waste of 40+ hours of peoples' lives * every day. * * @param c2s_conns The connections to drain * @param streamsNum The number of connections * @param buff The buffer into which we should read data * @param buff_size The size of said buffer */ void drain_old_clients(Connection* c2s_conns, int streamsNum, char* buff, size_t buff_size) { int activeStreams; double trash = 0; // A byte count we ignore. fd_set rfd; int max_fd; double start_time; int msgretvalue, read_error; struct timeval sel_tv; start_time = secs(); activeStreams = connections_to_fd_set(c2s_conns, streamsNum, &rfd, &max_fd); while (activeStreams > 0 && (secs() - start_time) < DRAIN_TIME) { sel_tv.tv_sec = DRAIN_TIME; sel_tv.tv_usec = 0; msgretvalue = select(max_fd + 1, &rfd, NULL, NULL, &sel_tv); if (msgretvalue == -1) { if (errno == EINTR) { // select interrupted. Continue waiting for activity on socket continue; } else { log_println(5, "Socket error while draining the client's send queue: %s. This is likely ok.", strerror(errno)); return; } } else if (msgretvalue == 0) { log_println(5, "Done draining the client's send queue."); return; } else if (msgretvalue > 0) { read_error = read_ready_streams(&rfd, c2s_conns, streamsNum, buff, buff_size, &trash); if (read_error != 0 && read_error != EINTR) { // EINTR is expected, but all other errors are actually errors log_println(5, "Error while trying to drain client's send queue: %s. This is likely ok.", strerror(read_error)); return; } } else { // This should never happen. select() returns -1, 0, or a positive number says POSIX. log_println(0, "Unhandled return value from select: %d.", msgretvalue); return; } // Set up the FD_SET and activeStreams for the next select. activeStreams = connections_to_fd_set(c2s_conns, streamsNum, &rfd, &max_fd); } }
ProcessTime ProcessTime::operator+(const ProcessTime& t) { ProcessTime &tt= (ProcessTime&)t; ProcessTime res; res._secs = secs() + tt.secs(); res._nano_secs = nano_secs() + tt.nano_secs(); if (res.nano_secs() >= one_billion) { res._nano_secs -= one_billion; res._secs += 1; } return res; }
static void build_reportspecs(char *reporttime) { /* Timespec: W:HHMM:HHMM */ char *spec, *timespec; int dow, start, end; int found; reptimecnt = 0; spec = strchr(reporttime, '='); timespec = strdup(spec ? (spec+1) : reporttime); spec = strtok(timespec, ","); while (spec) { if (*spec == '*') { dow = -1; found = sscanf(spec+1, ":%d:%d", &start, &end); } else if ((*spec == 'W') || (*spec == 'w')) { dow = -2; found = sscanf(spec+1, ":%d:%d", &start, &end); } else { found = sscanf(spec, "%d:%d:%d", &dow, &start, &end); } if (found < 2) { errprintf("build_reportspecs: Found too few items in %s\n", spec); } reptimes[reptimecnt].dow = dow; reptimes[reptimecnt].start = secs((start / 100), (start % 100), 0); reptimes[reptimecnt].end = secs((end / 100), (end % 100), 0); reptimecnt++; spec = strtok(NULL, ","); } xfree(timespec); }
/***********************************************************************//** * @brief Time constructor * * @param[in] time Time value (seconds or days). * @param[in] unit Time unit (default: "secs"). * * @exception GException::time_invalid_unit * Invalid time unit specified. * * Constructs a GTime object by setting the time in the native reference * in units of seconds (default) or days. ***************************************************************************/ GTime::GTime(const double& time, const std::string& unit) { // Initialise private members init_members(); // Set time according to timeunit string std::string timeunit = tolower(unit); if (timeunit == "d" || timeunit == "day" || timeunit == "days") { days(time); } else if (timeunit == "s" || timeunit == "sec" || timeunit == "secs") { secs(time); } else { throw GException::time_invalid_unit(G_CONSTRUCT, unit, "Valid timeunit values are: \"d\", \"day\", \"days\"," " \"s\", \"sec\" or \"secs\""); } // Return return; }
void Period::changePart(int s) { if(!type) { addSecs(s*secs()); return; } uint np = type->parts.size(); if(np) { uint p = (part + np + s)%np; if(part == 0 && s < 0) add(t1, type->base, -1); if(part == np - 1 && s > 0) add(t1, type->base, 1); part = p; QDateTime dt = set(from(), type->base, type->parts[part]); setFrom(dt); setTo(dt); p = (part + 1)%np; if(part == np - 1) add(t2, type->base, 1); setTo(set(to(), type->base, type->parts[p])); } else { setFrom(set(from(), type->base)); add(t1, type->base, s); t2 = t1; add(t2, type->base, 1); } }
/** * Perform the client part of the middleBox testing. The middlebox test * is a 5.0 second throughput test from the Server to the Client to * check for duplex mismatch conditions. It determines if routers or * switches in the path may be making changes to some TCP parameters. * @param ctlSocket server control socket descriptor * @param tests set of tests to perform * @param host hostname of the server * @param conn_options connection options * @param buf_size TCP send/receive buffer size * @param testresult_str result obtained from server (containing server ip, * client ip, currentMSS, WinSCaleSent, WinScaleRcvd) * @param jsonSupport Indicates if messages should be sent using JSON format * @return integer * => 0 on success * < 0 if error * Return codes used: * 0 = (the test has been finalized) * > 0 if protocol interactions were not as expected: * 1: Unable to receive protocol message successfully * 2: Wrong message type received * 3: Protocol message received was of invalid length * 4: Protocol payload data received was invalid * 5: Protocol message received was invalid * < 0 if generic error: * -3: Unable to resolve server address * -10: creating connection to server failed * */ int test_mid_clt(int ctlSocket, char tests, char* host, int conn_options, int buf_size, char* testresult_str, int jsonSupport) { char buff[BUFFSIZE + 1]; int msgLen, msgType; int midport = atoi(PORT3); I2Addr sec_addr = NULL; int retcode, inlth; int in2Socket; double t, spdin; uint32_t bytes; struct timeval sel_tv; fd_set rfd; char* jsonMsgValue; enum TEST_STATUS_INT teststatuses = TEST_NOT_STARTED; enum TEST_ID testids = MIDDLEBOX; if (tests & TEST_MID) { // middlebox test has to be performed log_println(1, " <-- Middlebox test -->"); setCurrentTest(TEST_MID); // protocol logs teststatuses = TEST_STARTED; protolog_status(getpid(), testids, teststatuses, ctlSocket); // Initially, expecting a TEST_PREPARE message. Any other message // ..type is unexpected at this stage. msgLen = sizeof(buff); if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) { log_println(0, "Protocol error - missed prepare message!"); return 1; } if (check_msg_type(MIDBOX_TEST_LOG, TEST_PREPARE, msgType, buff, msgLen)) { return 2; } // The server is expected to send a message with a valid payload that // contains the port number that server wants client to bind to for this // test buff[msgLen] = 0; if (jsonSupport) { jsonMsgValue = json_read_map_value(buff, DEFAULT_KEY); strlcpy(buff, jsonMsgValue, sizeof(buff)); msgLen = strlen(buff); free(jsonMsgValue); } if (msgLen <= 0) { log_println(0, "Improper message"); return 3; } if (check_int(buff, &midport)) { // obtained message does not contain // integer port# log_println(0, "Invalid port number"); return 4; } // get server address and set port log_println(1, " -- port: %d", midport); if ((sec_addr = I2AddrByNode(get_errhandle(), host)) == NULL) { log_println(0, "Unable to resolve server address: %s", strerror(errno)); return -3; } I2AddrSetPort(sec_addr, midport); // debug to check if correct port was set in addr struct if (get_debuglvl() > 4) { char tmpbuff[200]; size_t tmpBufLen = 199; memset(tmpbuff, 0, 200); I2AddrNodeName(sec_addr, tmpbuff, &tmpBufLen); log_println(5, "connecting to %s:%d", tmpbuff, I2AddrPort(sec_addr)); } // connect to server using port obtained above if ((retcode = CreateConnectSocket(&in2Socket, NULL, sec_addr, conn_options, buf_size))) { log_println(0, "Connect() for middlebox failed: %s", strerror(errno)); return -10; } // start reading throughput test data from server using the connection // created above printf("Checking for Middleboxes . . . . . . . . . . . . . . . . . . "); fflush(stdout); testresult_str[0] = '\0'; bytes = 0; t = secs() + 5.0; // set timer for 5 seconds, and read for 5 seconds sel_tv.tv_sec = 6; // Time out the socket after 6.5 seconds sel_tv.tv_usec = 5; // 500? FD_ZERO(&rfd); FD_SET(in2Socket, &rfd); for (;;) { if (secs() > t) break; retcode = select(in2Socket+1, &rfd, NULL, NULL, &sel_tv); if (retcode > 0) { inlth = read(in2Socket, buff, sizeof(buff)); if (inlth == 0) break; bytes += inlth; continue; } if (retcode < 0) { printf("nothing to read, exiting read loop\n"); break; } if (retcode == 0) { printf("timer expired, exiting read loop\n"); break; } } // get actual time for which test was run t = secs() - t + 5.0; // calculate throughput in Kbps spdin = ((BITS_8_FLOAT * bytes) / KILO) / t; // Test is complete. Now, get results from server (includes CurrentMSS, // WinScaleSent, WinScaleRcvd..). // The results are sent from server in the form of a TEST_MSG object msgLen = sizeof(buff); if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) { log_println(0, "Protocol error - missed text message!"); return 1; } if (check_msg_type(MIDBOX_TEST_LOG " results", TEST_MSG, msgType, buff, msgLen)) { return 2; } buff[msgLen] = 0; strlcat(testresult_str, buff, MIDBOX_TEST_RES_SIZE); memset(buff, 0, sizeof(buff)); // this should work since the throughput results from the server should // ...fit well within BUFFSIZE snprintf(buff, sizeof(buff), "%0.0f", spdin); log_println(4, "CWND limited speed = %0.2f kbps", spdin); // client now sends throughput it calculated above to server, as a TEST_MSG send_json_message(ctlSocket, TEST_MSG, buff, strlen(buff), jsonSupport, JSON_SINGLE_VALUE); printf("Done\n"); I2AddrFree(sec_addr); // Expect an empty TEST_FINALIZE message from server msgLen = sizeof(buff); if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) { log_println(0, "Protocol error - missed finalize message!"); return 1; } if (check_msg_type(MIDBOX_TEST_LOG, TEST_FINALIZE, msgType, buff, msgLen)) { return 2; } log_println(1, " <-------------------->"); // log protocol test ending teststatuses = TEST_ENDED; protolog_status(getpid(), testids, teststatuses, ctlSocket); setCurrentTest(TEST_NONE); } return 0; }
RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors, QList<RideFile*>*) const { CsvType csvType = generic; QRegExp metricUnits("(km|kph|km/h)", Qt::CaseInsensitive); QRegExp englishUnits("(miles|mph|mp/h)", Qt::CaseInsensitive); QRegExp degCUnits("Temperature .*C", Qt::CaseInsensitive); QRegExp degFUnits("Temperature .*F", Qt::CaseInsensitive); bool metric = true; enum temperature { degF, degC, degNone }; typedef enum temperature Temperature; static Temperature tempType = degNone; QDateTime startTime; // Minutes,Torq (N-m),Km/h,Watts,Km,Cadence,Hrate,ID // Minutes, Torq (N-m),Km/h,Watts,Km,Cadence,Hrate,ID // Minutes,Torq (N-m),Km/h,Watts,Km,Cadence,Hrate,ID,Altitude (m) QRegExp powertapCSV("Minutes,[ ]?Torq \\(N-m\\),(Km/h|MPH),Watts,(Km|Miles),Cadence,Hrate,ID", Qt::CaseInsensitive); // TODO: a more robust regex for ergomo files // i don't have an example with english headers // the ergomo CSV has two rows of headers. units are on the second row. /* ZEIT,STRECKE,POWER,RPM,SPEED,PULS,HÖHE,TEMP,INTERVAL,PAUSE L_SEC,KM,WATT,RPM,KM/H,BPM,METER,°C,NUM,SEC */ QRegExp ergomoCSV("(ZEIT|STRECKE)", Qt::CaseInsensitive); QRegExp motoActvCSV("activity_id", Qt::CaseInsensitive); bool epoch_set = false; quint64 epoch_offset=0; QChar ergomo_separator; int unitsHeader = 1; int total_pause = 0; int currentInterval = 0; int prevInterval = 0; double lastKM=0; // when deriving distance from speed /* Joule 1.0 Version,Date/Time,Km,Minutes,RPE,Tags,"Weight, kg","Work, kJ",FTP,"Sample Rate, s",Device Type,Firmware Version,Last Updated,Category 1,Category 2 6,2012-11-27 13:40:41,0,0,0,,55.8,788,227,1,Joule,18.018,,0, User Name,Power Zone 1,Power Zone 2,Power Zone 3,Power Zone 4,Power Zone 5,Power Zone 6,HR Zone 1,HR Zone 2,HR Zone 3,HR Zone 4,HR Zone 5,Calc Power A,Calc Power B,Calc Power ,0,0,0,0,0,0,150,160,170,180,250,0,-0, Minutes, Torq (N-m),Km/h,Watts,Km,Cadence,Hrate,ID,Altitude (m),Temperature (�C),"Grade, %",Latitude,Longitude,Power Calc'd,Calc Power,Right Pedal,Pedal Power %,Cad. Smoot 0,0,0,45,0,0,69,0,62,16.7,0,0,0,0,0,0,0, */ QRegExp jouleCSV("Device Type,Firmware Version", Qt::CaseInsensitive); QRegExp jouleMetriCSV(",Km,", Qt::CaseInsensitive); // TODO: with all these formats, should the logic change to a switch/case structure? // The iBike format CSV file has five lines of headers (data begins on line 6) // starting with: /* iBike,8,english 2008,8,8,6,32,52 {Various configuration data, recording interval at line[4][4]} Speed (mph),Wind Speed (mph),Power (W),Distance (miles),Cadence (RPM),Heartrate (BPM),Elevation (feet),Hill slope (%),Internal,Internal,Internal,DFPM Power,Latitude,Longitude */ QRegExp iBikeCSV("iBike,\\d\\d?,[a-z]+", Qt::CaseInsensitive); QRegExp moxyCSV("FW Part Number:", Qt::CaseInsensitive); QRegExp gcCSV("secs, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind, slope, temp, interval, lrbalance, lte, rte, lps, rps, smo2, thb, o2hb, hhb"); QRegExp periCSV("mm-dd,hh:mm:ss,SmO2 Live,SmO2 Averaged,THb,Target Power,Heart Rate,Speed,Power,Cadence"); QRegExp freemotionCSV("Stages Data", Qt::CaseInsensitive); QRegExp cpexportCSV("seconds, value,[ model,]* date", Qt::CaseInsensitive); int recInterval = 1; if (!file.open(QFile::ReadOnly)) { errors << ("Could not open ride file: \"" + file.fileName() + "\""); return NULL; } int lineno = 1; QTextStream is(&file); RideFile *rideFile = new RideFile(); int iBikeInterval = 0; bool dfpmExists = false; int iBikeVersion = 0; int secsIndex, minutesIndex = -1; double precWork=0.0; bool eof = false; while (!is.atEnd() && !eof) { // the readLine() method doesn't handle old Macintosh CR line endings // this workaround will load the the entire file if it has CR endings // then split and loop through each line // otherwise, there will be nothing to split and it will read each line as expected. QString linesIn = is.readLine(); QStringList lines = linesIn.split('\r'); // workaround for empty lines if(lines.isEmpty()) { lineno++; continue; } for (int li = 0; li < lines.size(); ++li) { QString line = lines[li]; if (line.length()==0) { continue; } if (lineno == 1) { if (ergomoCSV.indexIn(line) != -1) { csvType = ergomo; rideFile->setDeviceType("Ergomo"); rideFile->setFileFormat("Ergomo CSV (csv)"); unitsHeader = 2; QStringList headers = line.split(';'); if (headers.size()>1) ergomo_separator = ';'; else ergomo_separator = ','; ++lineno; continue; } else if(iBikeCSV.indexIn(line) != -1) { csvType = ibike; rideFile->setDeviceType("iBike"); rideFile->setFileFormat("iBike CSV (csv)"); unitsHeader = 5; iBikeVersion = line.section( ',', 1, 1 ).toInt(); ++lineno; continue; } else if(motoActvCSV.indexIn(line) != -1) { csvType = motoactv; rideFile->setDeviceType("MotoACTV"); rideFile->setFileFormat("MotoACTV CSV (csv)"); unitsHeader = -1; /* MotoACTV files are always metric */ metric = true; ++lineno; continue; } else if(jouleCSV.indexIn(line) != -1) { csvType = joule; rideFile->setDeviceType("Joule"); rideFile->setFileFormat("Joule CSV (csv)"); if(jouleMetriCSV.indexIn(line) != -1) { unitsHeader = 5; metric = true; } else { /* ? */ } ++lineno; continue; } else if(moxyCSV.indexIn(line) != -1) { csvType = moxy; rideFile->setDeviceType("Moxy"); rideFile->setFileFormat("Moxy CSV (csv)"); unitsHeader = 4; recInterval = 1; ++lineno; continue; } else if(gcCSV.indexIn(line) != -1) { csvType = gc; rideFile->setDeviceType("GoldenCheetah"); rideFile->setFileFormat("GoldenCheetah CSV (csv)"); unitsHeader = 1; recInterval = 1; ++lineno; continue; } else if(periCSV.indexIn(line) != -1) { csvType = peripedal; rideFile->setDeviceType("Peripedal"); rideFile->setFileFormat("Peripedal CSV (csv)"); unitsHeader = 1; recInterval = 1; ++lineno; continue; } else if(powertapCSV.indexIn(line) != -1) { csvType = powertap; rideFile->setDeviceType("PowerTap"); rideFile->setFileFormat("PowerTap CSV (csv)"); unitsHeader = 1; ++lineno; continue; } else if(freemotionCSV.indexIn(line) != -1) { csvType = freemotion; rideFile->setDeviceType("Freemotion Bike"); rideFile->setFileFormat("Stages Data (csv)"); unitsHeader = 3; ++lineno; continue; } else if(cpexportCSV.indexIn(line) != -1) { csvType = cpexport; rideFile->setDeviceType("CP Plot Export"); rideFile->setFileFormat("CP Plot Export (csv)"); unitsHeader = 1; ++lineno; continue; } else { // default csvType = generic; rideFile->setDeviceType("Unknow"); rideFile->setFileFormat("Generic CSV (csv)"); } } if (csvType == ibike) { if (lineno == 2) { QStringList f = line.split(","); if (f.size() == 6) { startTime = QDateTime( QDate(f[0].toInt(), f[1].toInt(), f[2].toInt()), QTime(f[3].toInt(), f[4].toInt(), f[5].toInt())); } } else if (lineno == 4) { // this is the line with the iBike configuration data // recording interval is in the [4] location (zero-based array) // the trailing zeroes in the configuration area seem to be causing an error // the number is in the format 5.000000 recInterval = (int)line.section(',',4,4).toDouble(); } } if (csvType == freemotion) { if (lineno == 2) { if (line == "English") metric = false; } } if (csvType == joule && lineno == 2) { // 6,2012-11-27 13:40:41,0,0,0,,55.8,788,227,1,Joule,18.018,,0, QStringList f = line.split(","); if (f.size() >= 2) { int f0l; QStringList f0 = f[1].split("|"); // new format? due to new PowerAgent version (7.5.7.34)? // 6,2011-01-02 21:22:20|2011-01-02 21:22|01/02/2011 21:22|2011-01-02 21-22-20,0,0, ... f0l = f0.size(); if (f0l >= 2) { startTime = QDateTime::fromString(f0[0], "yyyy-MM-dd H:mm:ss"); } else { startTime = QDateTime::fromString(f[1], "yyyy-MM-dd H:mm:ss"); } } } if (lineno == unitsHeader && csvType == generic) { QRegExp timeHeaderSecs("( )*(secs|sec|time)( )*", Qt::CaseInsensitive); QRegExp timeHeaderMins("( )*(min|minutes)( )*", Qt::CaseInsensitive); QStringList headers = line.split(","); QStringListIterator i(headers); while (i.hasNext()) { QString header = i.next(); if (timeHeaderSecs.indexIn(header) != -1) { secsIndex = headers.indexOf(header); } else if (timeHeaderMins.indexIn(header) != -1) { minutesIndex = headers.indexOf(header); } } } else if (lineno == unitsHeader && csvType != moxy && csvType != peripedal) { if (metricUnits.indexIn(line) != -1) metric = true; else if (englishUnits.indexIn(line) != -1) metric = false; else { errors << "Can't find units in first line: \"" + line + "\" of file \"" + file.fileName() + "\"."; delete rideFile; file.close(); return NULL; } if (degCUnits.indexIn(line) != -1) tempType = degC; else if (degFUnits.indexIn(line) != -1) tempType = degF; } else if (lineno > unitsHeader) { double minutes=0,nm=0,kph=0,watts=0,km=0,cad=0,alt=0,hr=0,dfpm=0, seconds=0.0; double temp=RideFile::NoTemp; double slope=0.0; bool ok; double lat = 0.0, lon = 0.0; double headwind = 0.0; double lrbalance = 0.0; double lte = 0.0, rte = 0.0; double lps = 0.0, rps = 0.0; double smo2 = 0.0, thb = 0.0; double o2hb = 0.0, hhb = 0.0; int interval=0; int pause=0; quint64 ms; if (csvType == powertap || csvType == joule) { minutes = line.section(',', 0, 0).toDouble(); nm = line.section(',', 1, 1).toDouble(); kph = line.section(',', 2, 2).toDouble(); watts = line.section(',', 3, 3).toDouble(); km = line.section(',', 4, 4).toDouble(); cad = line.section(',', 5, 5).toDouble(); hr = line.section(',', 6, 6).toDouble(); interval = line.section(',', 7, 7).toInt(); alt = line.section(',', 8, 8).toDouble(); if (csvType == joule && tempType != degNone) { // is the position always the same? // should we read the header and assign positions // to each item instead? temp = line.section(',', 9, 9).toDouble(); if (tempType == degF) { // convert to deg C temp *= FAHRENHEIT_PER_CENTIGRADE + FAHRENHEIT_ADD_CENTIGRADE; } } if (!metric) { km *= KM_PER_MILE; kph *= KM_PER_MILE; alt *= METERS_PER_FOOT; } } else if (csvType == gc) { // GoldenCheetah CVS Format "secs, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind, slope, temp, interval, lrbalance, lte, rte, lps, rps, smo2, thb, o2hb, hhb\n"; seconds = line.section(',', 0, 0).toDouble(); minutes = seconds / 60.0f; cad = line.section(',', 1, 1).toDouble(); hr = line.section(',', 2, 2).toDouble(); km = line.section(',', 3, 3).toDouble(); kph = line.section(',', 4, 4).toDouble(); nm = line.section(',', 5, 5).toDouble(); watts = line.section(',', 6, 6).toDouble(); alt = line.section(',', 7, 7).toDouble(); lon = line.section(',', 8, 8).toDouble(); lat = line.section(',', 9, 9).toDouble(); headwind = line.section(',', 10, 10).toDouble(); slope = line.section(',', 11, 11).toDouble(); temp = line.section(',', 12, 12).toDouble(); interval = line.section(',', 13, 13).toInt(); lrbalance = line.section(',', 14, 14).toInt(); lte = line.section(',', 15, 15).toInt(); rte = line.section(',', 16, 16).toInt(); lps = line.section(',', 17, 17).toInt(); rps = line.section(',', 18, 18).toInt(); smo2 = line.section(',', 19, 19).toInt(); thb = line.section(',', 20, 20).toInt(); o2hb = line.section(',', 21, 21).toInt(); hhb = line.section(',', 22, 22).toInt(); } else if (csvType == peripedal) { //mm-dd,hh:mm:ss,SmO2 Live,SmO2 Averaged,THb,Target Power,Heart Rate,Speed,Power,Cadence // ignore lines with wrong number of entries if (line.split(",").count() != 10) continue; seconds = moxySeconds(line.section(',',1,1)); minutes = seconds / 60.0f; if (startTime == QDateTime()) { QDate date = periDate(line.section(',',0,0)); QTime time = QTime(0,0,0).addSecs(seconds); startTime = QDateTime(date,time); } double aSmo2 = line.section(',', 3, 3).toDouble(); smo2 = line.section(',', 2, 2).toDouble(); // use average if live not available if (aSmo2 && !smo2) smo2 = aSmo2; thb = line.section(',', 4, 4).toDouble(); hr = line.section(',', 6, 6).toDouble(); kph = line.section(',', 7, 7).toDouble(); watts = line.section(',', 8, 8).toDouble(); cad = line.section(',', 10, 10).toDouble(); // dervice distance from speed km = lastKM + (kph/3600.0f); lastKM = km; nm = 0; alt = 0; lon = 0; lat = 0; headwind = 0; slope = 0; temp = 0; interval = 0; lrbalance = 0; lte = 0; rte = 0; lps = 0; rps = 0; o2hb = 0; hhb = 0; } else if (csvType == freemotion) { if (line == "Ride_Totals") { eof = true; continue; } // Time,Miles,MPH,Watts,HR,RPM seconds = QTime::fromString(line.section(',', 0, 0), "m:s").second(); minutes = QTime::fromString(line.section(',', 0, 0), "m:s").minute() + seconds / 60.0f; cad = line.section(',', 5, 5).toDouble(); hr = line.section(',', 4, 4).toDouble(); km = line.section(',', 1, 1).toDouble(); kph = line.section(',', 2, 2).toDouble(); watts = line.section(',', 3, 3).toDouble(); if (!metric) { km *= KM_PER_MILE; kph *= KM_PER_MILE; } } else if (csvType == ibike) { // this must be iBike // can't find time as a column. // will we have to extrapolate based on the recording interval? // reading recording interval from config data in ibike csv file // // For iBike software version 11 or higher: // use "power" field until a the "dfpm" field becomes non-zero. minutes = (recInterval * lineno - unitsHeader)/60.0; nm = 0; //no torque kph = line.section(',', 0, 0).toDouble(); dfpm = line.section( ',', 11, 11).toDouble(); headwind = line.section(',', 1, 1).toDouble(); if( iBikeVersion >= 11 && ( dfpm > 0.0 || dfpmExists ) ) { dfpmExists = true; watts = dfpm; } else { watts = line.section(',', 2, 2).toDouble(); } km = line.section(',', 3, 3).toDouble(); cad = line.section(',', 4, 4).toDouble(); hr = line.section(',', 5, 5).toDouble(); alt = line.section(',', 6, 6).toDouble(); slope = line.section(',', 7, 7).toDouble(); temp = line.section(',', 8, 8).toDouble(); lat = line.section(',', 12, 12).toDouble(); lon = line.section(',', 13, 13).toDouble(); int lap = line.section(',', 9, 9).toInt(); if (lap > 0) { iBikeInterval += 1; interval = iBikeInterval; } if (!metric) { km *= KM_PER_MILE; kph *= KM_PER_MILE; alt *= METERS_PER_FOOT; headwind *= KM_PER_MILE; } } else if (csvType == moxy) { // we get crappy lines with no data so ignore them // I think they're supposed to be delimiters for the file // content, but are just noise to us ! if (line == (" ,,,,,") || line == ",,,,," || line == "" || line == " ") continue; // need to get time from second column and note that // there will be gaps when recording drops so shouldn't // assume it is a continuous stream double seconds = moxySeconds(line.section(',',1,1)); if (startTime == QDateTime()) { QDate date = moxyDate(line.section(',',0,0)); QTime time = QTime(0,0,0).addSecs(seconds); startTime = QDateTime(date,time); } if (seconds >0) { minutes = seconds / 60.0f; smo2 = line.section(',', 2, 2).remove("\"").toDouble(); thb = line.section(',', 4, 4).remove("\"").toDouble(); } } else if(csvType == motoactv) { /* MotoActv saves it all as kind of SI (m, ms, m/s, NM etc) * "double","double",.. so we need to filter out " */ km = line.section(',', 0,0).remove("\"").toDouble()/1000; hr = line.section(',', 2, 2).remove("\"").toDouble(); kph = line.section(',', 3, 3).remove("\"").toDouble()*3.6; lat = line.section(',', 5, 5).remove("\"").toDouble(); /* Item 8 is crank torque, 13 is wheel torque */ nm = line.section(',', 8, 8).remove("\"").toDouble(); /* Ok there's no crank torque, try the wheel */ if(nm == 0.0) { nm = line.section(',', 13, 13).remove("\"").toDouble(); } if(epoch_set == false) { epoch_set = true; epoch_offset = line.section(',', 9,9).remove("\"").toULongLong(&ok, 10); /* We use this first value as the start time */ startTime = QDateTime(); startTime.setMSecsSinceEpoch(epoch_offset); rideFile->setStartTime(startTime); } ms = line.section(',', 9,9).remove("\"").toULongLong(&ok, 10); ms -= epoch_offset; seconds = ms/1000; alt = line.section(',', 10, 10).remove("\"").toDouble(); watts = line.section(',', 11, 11).remove("\"").toDouble(); lon = line.section(',', 15, 15).remove("\"").toDouble(); cad = line.section(',', 16, 16).remove("\"").toDouble(); } else if (csvType == ergomo) { // for ergomo formatted CSV files minutes = line.section(ergomo_separator, 0, 0).toDouble() + total_pause; QString km_string = line.section(ergomo_separator, 1, 1); km_string.replace(",","."); km = km_string.toDouble(); watts = line.section(ergomo_separator, 2, 2).toDouble(); cad = line.section(ergomo_separator, 3, 3).toDouble(); QString kph_string = line.section(ergomo_separator, 4, 4); kph_string.replace(",","."); kph = kph_string.toDouble(); hr = line.section(ergomo_separator, 5, 5).toDouble(); alt = line.section(ergomo_separator, 6, 6).toDouble(); interval = line.section(',', 8, 8).toInt(); if (interval != prevInterval) { prevInterval = interval; if (interval != 0) currentInterval++; } if (interval != 0) interval = currentInterval; pause = line.section(ergomo_separator, 9, 9).toInt(); total_pause += pause; nm = 0; // torque is not provided in the Ergomo file // the ergomo records the time in whole seconds // RECORDING INT. 1, 2, 5, 10, 15 or 30 per sec // Time is *always* perfectly sequential. To find pauses, // you need to read the PAUSE column. minutes = minutes/60.0; if (!metric) { km *= KM_PER_MILE; kph *= KM_PER_MILE; alt *= METERS_PER_FOOT; } } else if (csvType == cpexport) { // seconds, value, (model), date seconds = line.section(',',0,0).toDouble(); minutes = seconds / 60.0f; seconds = lineno -1 ; double avgwatts = line.section(',', 1, 1).toDouble(); watts = avgwatts * seconds - precWork; // 1000 * 1 - 700 precWork = avgwatts * seconds; } else { if (secsIndex > -1) { seconds = line.section(',', secsIndex, secsIndex).toDouble(); minutes = seconds / 60.0f; } } // PT reports no data as watts == -1. if (watts == -1) watts = 0; if(csvType == motoactv) rideFile->appendPoint(seconds, cad, hr, km, kph, nm, watts, alt, lon, lat, 0.0, 0.0, temp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); else if (csvType == moxy) { // hack it in for now // XXX IT COULD BE RECORDED WITH DIFFERENT INTERVALS XXX rideFile->appendPoint(minutes * 60.0, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind, slope, temp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, smo2, thb, 0.0, 0.0, 0.0, interval); rideFile->appendPoint((minutes * 60.0)+1, cad, hr, km, // dupe it so we have 1s recording easier to merge kph, nm, watts, alt, lon, lat, headwind, slope, temp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, smo2, thb, 0.0, 0.0, 0.0, interval); } else { rideFile->appendPoint(minutes * 60.0, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind, slope, temp, lrbalance, lte, rte, lps, rps, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, smo2, thb, 0.0, 0.0, 0.0, interval); } } ++lineno; } } file.close(); // To estimate the recording interval, take the median of the // first 1000 samples and round to nearest millisecond. int n = rideFile->dataPoints().size(); n = qMin(n, 1000); if (n >= 2) { QVector<double> secs(n-1); for (int i = 0; i < n-1; ++i) { double now = rideFile->dataPoints()[i]->secs; double then = rideFile->dataPoints()[i+1]->secs; secs[i] = then - now; } std::sort(secs.begin(), secs.end()); int mid = n / 2 - 1; double recint = round(secs[mid] * 1000.0) / 1000.0; rideFile->setRecIntSecs(recint); } // less than 2 data points is not a valid ride file else { errors << "Insufficient valid data in file \"" + file.fileName() + "\"."; delete rideFile; file.close(); return NULL; } QRegExp rideTime("^.*/(\\d\\d\\d\\d)_(\\d\\d)_(\\d\\d)_" "(\\d\\d)_(\\d\\d)_(\\d\\d)\\.csv$"); rideTime.setCaseSensitivity(Qt::CaseInsensitive); if (startTime != QDateTime()) { // Start time was already set above? rideFile->setStartTime(startTime); } else if (rideTime.indexIn(file.fileName()) >= 0) { // It matches the GC naming convention? QDateTime datetime(QDate(rideTime.cap(1).toInt(), rideTime.cap(2).toInt(), rideTime.cap(3).toInt()), QTime(rideTime.cap(4).toInt(), rideTime.cap(5).toInt(), rideTime.cap(6).toInt())); rideFile->setStartTime(datetime); } else { // Could be yyyyddmm_hhmmss_NAME.csv (case insensitive) rideTime.setPattern("(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)_(\\d\\d)(\\d\\d)(\\d\\d)[^\\.]*\\.csv$"); if (rideTime.indexIn(file.fileName()) >= 0) { QDateTime datetime(QDate(rideTime.cap(1).toInt(), rideTime.cap(2).toInt(), rideTime.cap(3).toInt()), QTime(rideTime.cap(4).toInt(), rideTime.cap(5).toInt(), rideTime.cap(6).toInt())); rideFile->setStartTime(datetime); } else { // is it in poweragent format "name yyyy-mm-dd hh-mm-ss.csv" rideTime.setPattern("(\\d\\d\\d\\d)-(\\d\\d)-(\\d\\d) (\\d\\d)-(\\d\\d)-(\\d\\d)\\.csv$"); if (rideTime.indexIn(file.fileName()) >=0) { QDateTime datetime(QDate(rideTime.cap(1).toInt(), rideTime.cap(2).toInt(), rideTime.cap(3).toInt()), QTime(rideTime.cap(4).toInt(), rideTime.cap(5).toInt(), rideTime.cap(6).toInt())); rideFile->setStartTime(datetime); } else { // NO DICE // Note: qWarning("Failed to set start time"); // console messages are no use, so commented out // this problem will ONLY occur during the import // process which traps these and corrects them // so no need to do anything here } } } // did we actually read any samples? if (rideFile->dataPoints().count() > 0) { return rideFile; } else { errors << "No samples present."; delete rideFile; return NULL; } }
int confOption::setValueFromFile(QString line) { // Used to set values in confOptions from a file line QString rval = line.section("=",1).trimmed(); qDebug() << "setting " << realName << " to " << rval << " (from file)"; if (type == BOOL) { if (rval == "true" || rval == "on" || rval == "yes") { value = true; return 0; } else if (rval == "false" || rval == "off" || rval == "no") { value = false; return 0; } qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } else if (type == INTEGER) { bool ok; qlonglong rvalToNmbr = rval.toLongLong(&ok); if (ok && rvalToNmbr >= minVal && rvalToNmbr <= maxVal) { value = rvalToNmbr; return 0; } qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } else if (type == STRING) { value = rval; return 0; } else if (type == LIST) { if (realName == "ShowStatus") // ShowStatus needs special treatment { if (rval.toLower() == "true" || rval.toLower() == "on") rval = "yes"; else if (rval.toLower() == "false" || rval.toLower() == "off") rval = "no"; } if (possibleVals.contains(rval)) { value = rval.toLower(); return 0; } qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; value = defVal; return -1; } else if (type == MULTILIST) { QVariantMap map; QStringList readList = rval.split(" ", QString::SkipEmptyParts); for (int i = 0; i < readList.size(); ++i) { if (!possibleVals.contains(readList.at(i))) { qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } } for (int i = 0; i < possibleVals.size(); ++i) { if (readList.contains(possibleVals.at(i))) map[possibleVals.at(i)] = true; else map[possibleVals.at(i)] = false; } value = map; return 0; } else if (type == TIME) { int pos = 0; QRegExp rxValid; // These regex check whether rval is a valid time interval if (hasNsec) rxValid = QRegExp("^(?:\\d*\\.?\\d *(ns|nsec|us|usec|ms|msec|s|sec|second|seconds|m|min|minute|minutes|h|hr|hour|hours|d|day|days|w|week|weeks|month|months|y|year|years)? *)+$"); else rxValid = QRegExp("^(?:\\d*\\.?\\d *(us|usec|ms|msec|s|sec|second|seconds|m|min|minute|minutes|h|hr|hour|hours|d|day|days|w|week|weeks|month|months|y|year|years)? *)+$"); pos = rxValid.indexIn(rval); if (pos > -1) { pos = 0; seconds secs(0); // This regex parses individual elements of the time interval QRegExp rxTimeParse = QRegExp("(\\d*\\.?\\d+) *([a-z]*)"); while ((pos = rxTimeParse.indexIn(rval, pos)) != -1) { if (rxTimeParse.cap(2) == "ns" || rxTimeParse.cap(2) == "nsec" ) { nanoseconds ns(rxTimeParse.cap(1).trimmed().toDouble()); secs += ns; } else if (rxTimeParse.cap(2) == "us" || rxTimeParse.cap(2) == "usec" ) { microseconds us(rxTimeParse.cap(1).trimmed().toDouble()); secs += us; } else if (rxTimeParse.cap(2) == "ms" || rxTimeParse.cap(2) == "msec" ) { milliseconds ms(rxTimeParse.cap(1).trimmed().toDouble()); secs += ms; } else if (rxTimeParse.cap(2) == "s" || rxTimeParse.cap(2) == "sec" || rxTimeParse.cap(2) == "second" || rxTimeParse.cap(2) == "seconds" ) { seconds s(rxTimeParse.cap(1).trimmed().toDouble()); secs += s; } else if (rxTimeParse.cap(2) == "m" || rxTimeParse.cap(2) == "min" || rxTimeParse.cap(2) == "minute" || rxTimeParse.cap(2) == "minutes" ) { minutes min(rxTimeParse.cap(1).trimmed().toDouble()); secs += min; } else if (rxTimeParse.cap(2) == "h" || rxTimeParse.cap(2) == "hr" || rxTimeParse.cap(2) == "hour" || rxTimeParse.cap(2) == "hours" ) { hours hr(rxTimeParse.cap(1).trimmed().toDouble()); secs += hr; } else if (rxTimeParse.cap(2) == "d" || rxTimeParse.cap(2) == "day" || rxTimeParse.cap(2) == "days") { days dy(rxTimeParse.cap(1).trimmed().toDouble()); secs += dy; } else if (rxTimeParse.cap(2) == "w" || rxTimeParse.cap(2) == "week" || rxTimeParse.cap(2) == "weeks") { weeks w(rxTimeParse.cap(1).trimmed().toDouble()); secs += w; } else if (rxTimeParse.cap(2) == "month" || rxTimeParse.cap(2) == "months") { months m(rxTimeParse.cap(1).trimmed().toDouble()); secs += m; } else if (rxTimeParse.cap(2) == "y" || rxTimeParse.cap(2) == "year" || rxTimeParse.cap(2) == "years") { years y(rxTimeParse.cap(1).trimmed().toDouble()); secs += y; } else if (rxTimeParse.cap(2).isEmpty()) { // unitless number, convert it from defReadUnit to seconds seconds tmpSeconds(convertTimeUnit(rxTimeParse.cap(1).trimmed().toDouble(), defReadUnit, timeUnit::s).toDouble()); secs += tmpSeconds; } pos += rxTimeParse.matchedLength(); } // Convert the read value in seconds to defUnit if (defUnit == ns) value = nanoseconds(secs).count(); else if (defUnit == us) value = microseconds(secs).count(); else if (defUnit == ms) value = milliseconds(secs).count(); else if (defUnit == s) value = secs.count(); else if (defUnit == min) value = minutes(secs).count(); else if (defUnit == h) value = hours(secs).count(); else if (defUnit == d) value = days(secs).count(); else if (defUnit == w) value = weeks(secs).count(); else if (defUnit == month) value = months(secs).count(); else if (defUnit == year) value = years(secs).count(); value = value.toULongLong(); // Convert to ulonglong (we don't support float in ui) return 0; } else { qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } } else if (type == RESLIMIT) { bool ok; int nmbr = rval.toUInt(&ok); if (ok) { value = nmbr; return 0; } else if (rval.toLower().trimmed() == "infinity" || rval.trimmed().isEmpty()) { value = -1; return 0; } qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } else if (type == SIZE) { // RegExp to match a number (possibly with decimals) followed by a size unit (or no unit for byte) QRegExp rxSize = QRegExp("(\\b\\d+\\.?\\d*(K|M|G|T|P|E)?\\b)"); int pos = 0; pos = rxSize.indexIn(rval); if (pos > -1 && rxSize.cap(0) == rval.trimmed()) { // convert the specified size unit to megabytes if (rxSize.cap(0).contains("K")) value = rxSize.cap(0).remove("K").toDouble() / 1024; else if (rxSize.cap(0).contains("M")) value = rxSize.cap(0).remove("M").toDouble(); else if (rxSize.cap(0).contains("G")) value = rxSize.cap(0).remove("G").toDouble() * 1024; else if (rxSize.cap(0).contains("T")) value = rxSize.cap(0).remove("T").toDouble() * 1024 * 1024; else if (rxSize.cap(0).contains("P")) value = rxSize.cap(0).remove("P").toDouble() * 1024 * 1024 * 1024; else if (rxSize.cap(0).contains("E")) value = rxSize.cap(0).remove("E").toDouble() * 1024 * 1024 * 1024 * 1024; else value = rxSize.cap(0).toDouble() / 1024 / 1024; // Convert from double to ulonglong (we don't support float in ui) value = value.toULongLong(); return 0; } else { qDebug() << rval << "is not a valid value for setting" << realName << ". Ignoring..."; return -1; } } return -1; }
RideFile *Computrainer3dpFileReader::openRideFile(QFile & file, QStringList & errors) const { if (!file.open(QFile::ReadOnly)) { errors << ("Could not open ride file: \"" + file.fileName() + "\""); return NULL; } RideFile *rideFile = new RideFile(); QDataStream is(&file); is.setByteOrder(QDataStream::LittleEndian); // looks like the first part is a header... ignore it. is.skipRawData(4); char perfStr[5]; is.readRawData(perfStr, 4); perfStr[4] = NULL; is.skipRawData(0x8); char userName[65]; is.readRawData(userName, 65); ubyte age; is >> age; is.skipRawData(6); float weight; is >> weight; int upperHR; is >> upperHR; int lowerHR; is >> lowerHR; int year; is >> year; ubyte month; is >> month; ubyte day; is >> day; ubyte hour; is >> hour; ubyte minute; is >> minute; int numberSamples; is >> numberSamples; // go back to the start, and go to the start of the data samples file.seek(0); is.skipRawData(0xf8); for (; numberSamples; numberSamples--) { ubyte hr; is >> hr; ubyte cad; is >> cad; unsigned short watts; is >> watts; float speed; is >> speed; speed = speed * KM_PER_MILE * 100; int ms; is >> ms; is.skipRawData(4); float miles; is >> miles; float km = miles * KM_PER_MILE; is.skipRawData(0x1c); rideFile->appendPoint((double) ms / 1000, (double) cad, (double) hr, km, speed, 0.0, watts, 0, 0, 0); } QDateTime dateTime; QDate date; QTime time; date.setDate(year, month, day); time.setHMS(hour, minute, 0, 0); dateTime.setDate(date); dateTime.setTime(time); rideFile->setStartTime(dateTime); int n = rideFile->dataPoints().size(); n = qMin(n, 1000); if (n >= 2) { QVector < double >secs(n - 1); for (int i = 0; i < n - 1; ++i) { double now = rideFile->dataPoints()[i]->secs; double then = rideFile->dataPoints()[i + 1]->secs; secs[i] = then - now; } std::sort(secs.begin(), secs.end()); int mid = n / 2 - 1; double recint = round(secs[mid] * 1000.0) / 1000.0; rideFile->setRecIntSecs(recint); } rideFile->setDeviceType("Computrainer 3DP"); file.close(); return rideFile; }
int test_mid_clt(int ctlSocket, char tests, char* host, int conn_options, int buf_size, char* tmpstr2) { char buff[BUFFSIZE+1]; int msgLen, msgType; int midport = 3003; I2Addr sec_addr = NULL; int ret, one=1, i, inlth; int in2Socket; double t, spdin; uint32_t bytes; struct timeval sel_tv; fd_set rfd; if (tests & TEST_MID) { log_println(1, " <-- Middlebox test -->"); msgLen = sizeof(buff); if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) { log_println(0, "Protocol error - missed prepare message!"); return 1; } if (check_msg_type("Middlebox test", TEST_PREPARE, msgType, buff, msgLen)) { return 2; } if (msgLen <= 0) { log_println(0, "Improper message"); return 3; } buff[msgLen] = 0; if (check_int(buff, &midport)) { log_println(0, "Invalid port number"); return 4; } log_println(1, " -- port: %d", midport); if ((sec_addr = I2AddrByNode(get_errhandle(), host)) == NULL) { log_println(0, "Unable to resolve server address: %s", strerror(errno)); return -3; } I2AddrSetPort(sec_addr, midport); if (get_debuglvl() > 4) { char tmpbuff[200]; size_t tmpBufLen = 199; memset(tmpbuff, 0, 200); I2AddrNodeName(sec_addr, tmpbuff, &tmpBufLen); log_println(5, "connecting to %s:%d", tmpbuff, I2AddrPort(sec_addr)); } if ((ret = CreateConnectSocket(&in2Socket, NULL, sec_addr, conn_options, buf_size))) { log_println(0, "Connect() for middlebox failed: %s", strerror(errno)); return -10; } printf("Checking for Middleboxes . . . . . . . . . . . . . . . . . . "); fflush(stdout); tmpstr2[0] = '\0'; i = 0; bytes = 0; t = secs() + 5.0; sel_tv.tv_sec = 6; sel_tv.tv_usec = 5; FD_ZERO(&rfd); FD_SET(in2Socket, &rfd); for (;;) { if (secs() > t) break; ret = select(in2Socket+1, &rfd, NULL, NULL, &sel_tv); if (ret > 0) { inlth = read(in2Socket, buff, sizeof(buff)); if (inlth == 0) break; bytes += inlth; continue; } if (ret < 0) { printf("nothing to read, exiting read loop\n"); break; } if (ret == 0) { printf("timer expired, exiting read loop\n"); break; } } t = secs() - t + 5.0; spdin = ((8.0 * bytes) / 1000) / t; msgLen = sizeof(buff); if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) { log_println(0, "Protocol error - missed text message!"); return 1; } if (check_msg_type("Middlebox test results", TEST_MSG, msgType, buff, msgLen)) { return 2; } strncat(tmpstr2, buff, msgLen); memset(buff, 0, 128); sprintf(buff, "%0.0f", spdin); log_println(4, "CWND limited speed = %0.2f kbps", spdin); send_msg(ctlSocket, TEST_MSG, buff, strlen(buff)); printf("Done\n"); I2AddrFree(sec_addr); msgLen = sizeof(buff); if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) { log_println(0, "Protocol error - missed finalize message!"); return 1; } if (check_msg_type("Middlebox test", TEST_FINALIZE, msgType, buff, msgLen)) { return 2; } log_println(1, " <-------------------->"); } return 0; }
void coverQuantisationCornerCases() { // origin at lower end of the time range FixedFrameQuantiser case1 (1, Time::MIN); CHECK (secs(0) == case1.gridAlign(Time::MIN )); CHECK (secs(0) == case1.gridAlign(Time::MIN +TimeValue(1) )); CHECK (secs(1) == case1.gridAlign(Time::MIN +secs(1) )); CHECK (Time::MAX -secs(1) > case1.gridAlign( secs(-1) )); CHECK (Time::MAX -secs(1) <= case1.gridAlign( secs (0) )); CHECK (Time::MAX > case1.gridAlign( secs (0) )); CHECK (Time::MAX == case1.gridAlign( secs(+1) )); CHECK (Time::MAX == case1.gridAlign( secs(+2) )); // origin at upper end of the time range FixedFrameQuantiser case2 (1, Time::MAX); CHECK (secs( 0) == case2.gridAlign(Time::MAX )); CHECK (secs(-1) == case2.gridAlign(Time::MAX -TimeValue(1) )); // note: next lower frame CHECK (secs(-1) == case2.gridAlign(Time::MAX -secs(1) )); // i.e. the same as a whole frame down CHECK (Time::MIN +secs(1) < case2.gridAlign( secs(+2) )); CHECK (Time::MIN +secs(1) >= case2.gridAlign( secs(+1) )); CHECK (Time::MIN < case2.gridAlign( secs(+1) )); CHECK (Time::MIN == case2.gridAlign( secs( 0) )); // note: because of downward truncating, CHECK (Time::MIN == case2.gridAlign( secs(-1) )); // resulting values will already exceed CHECK (Time::MIN == case2.gridAlign( secs(-2) )); // allowed range and thus will be clipped // maximum frame size is half the time range Duration hugeFrame(Time::MAX); FixedFrameQuantiser case3 (hugeFrame); CHECK (Time::MIN == case3.gridAlign(Time::MIN )); CHECK (Time::MIN == case3.gridAlign(Time::MIN +TimeValue(1) )); CHECK (Time::MIN == case3.gridAlign( secs(-1) )); CHECK (TimeValue(0) == case3.gridAlign( secs( 0) )); CHECK (TimeValue(0) == case3.gridAlign( secs(+1) )); CHECK (TimeValue(0) == case3.gridAlign(Time::MAX -TimeValue(1) )); CHECK (Time::MAX == case3.gridAlign(Time::MAX )); // now displacing this grid by +1sec.... FixedFrameQuantiser case4 (hugeFrame, secs(1)); CHECK (Time::MIN == case4.gridAlign(Time::MIN )); CHECK (Time::MIN == case4.gridAlign(Time::MIN +TimeValue(1) )); // clipped... CHECK (Time::MIN == case4.gridAlign(Time::MIN +secs(1) )); // but now exact (unclipped) CHECK (Time::MIN == case4.gridAlign( secs(-1) )); CHECK (Time::MIN == case4.gridAlign( secs( 0) )); CHECK (TimeValue(0) == case4.gridAlign( secs(+1) )); //.....now exactly the frame number zero CHECK (TimeValue(0) == case4.gridAlign(Time::MAX -TimeValue(1) )); CHECK (TimeValue(0) == case4.gridAlign(Time::MAX )); //.......still truncated down to frame #0 // larger frames aren't possible Duration not_really_larger(secs(10000) + hugeFrame); CHECK (hugeFrame == not_really_larger); // frame sizes below the time micro grid get trapped long subAtomic = 2*GAVL_TIME_SCALE; // too small for this universe... VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(subAtomic) ); VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(Duration (FSecs (1,subAtomic))) ); }
bool ServerAgent::ParseENums (const char *data, const char *sWord) { int num (atoi (sWord)); switch (num) { case ZERO: // 0 { // wasn't a numeric, or the server is playing tricks on us } return false; case ERR_UNKNOWNCOMMAND: // 421 { BString tempString (RestOfString (data, 4)), badCmd (GetWord (data, 4)); if (badCmd == "VISION_LAG_CHECK") { int32 difference (system_time() - fLagCheck); if (difference > 0) { int32 secs (difference / 1000000); int32 milli (difference / 1000 - secs * 1000); char lag[15] = ""; sprintf (lag, "%0" B_PRId32 ".%03" B_PRId32, secs, milli); fMyLag = lag; fLagCount = 0; fCheckingLag = false; fMsgr.SendMessage (M_LAG_CHANGED); } } else { tempString.RemoveFirst (":"); tempString.Append ("\n"); Display (tempString.String()); } } return true; case RPL_WELCOME: // 001 case RPL_YOURHOST: // 002 case RPL_CREATED: // 003 case RPL_MYINFO: // 004 { fConnected = true; fIsConnecting = false; fInitialMotd = true; fRetry = 0; if (num == RPL_WELCOME) { BString message = B_TRANSLATE("Established"); message.Prepend("[@] ").Append("\n"); Display(message.String(), C_ERROR, C_BACKGROUND, F_SERVER); } if (fNetworkData.FindBool ("lagCheck")) { fMyLag = "0.000"; fMsgr.SendMessage (M_LAG_CHANGED); } BString theNick (GetWord (data, 3)); fMyNick = theNick; if (!IsHidden()) vision_app->pClientWin()->pStatusView()->SetItemValue (STATUS_NICK, theNick.String()); BString theMsg (RestOfString (data, 4)); theMsg.RemoveFirst (":"); theMsg.Prepend ("* "); theMsg.Append ("\n"); Display (theMsg.String()); if (num == RPL_MYINFO) { // set "real" hostname fServerHostName = (GetWord (data, 1)); fServerHostName.RemoveFirst (":"); BString hostName (fId.String()); hostName += " - ["; hostName += fServerHostName.String(); hostName += "]"; fAgentWinItem->SetName (hostName.String()); // detect IRCd fIrcdtype = IRCD_STANDARD; if (theMsg.FindFirst("hybrid") > 0) fIrcdtype = IRCD_HYBRID; // ultimate and unreal share the same numerics, so treat them with the same // identifier for now else if ((theMsg.FindFirst("UltimateIRCd") > 0) || (theMsg.FindFirst("Unreal") > 0)) fIrcdtype = IRCD_ULTIMATE; else if (theMsg.FindFirst("comstud") > 0) fIrcdtype = IRCD_COMSTUD; else if (theMsg.FindFirst("u2.") > 0) fIrcdtype = IRCD_UNDERNET; else if (theMsg.FindFirst("PTlink") > 0) fIrcdtype = IRCD_PTLINK; else if (theMsg.FindFirst ("CR") > 0) fIrcdtype = IRCD_CONFERENCEROOM; else if (theMsg.FindFirst ("nn-") > 0) fIrcdtype = IRCD_NEWNET; } } return true; case RPL_PROTOCTL: // 005 { // this numeric also serves as RPL_NNMAP on Newnet BString theMsg (RestOfString (data, 4)); theMsg.RemoveFirst (":"); theMsg.Append ("\n"); switch (fIrcdtype) { case IRCD_NEWNET: { // RPL_NNMAP Display (theMsg.String()); } break; default: { // RPL_PROTOCTL theMsg.Prepend ("* "); Display (theMsg.String()); } } } return true; case RPL_LUSERHIGHESTCONN: // 250 case RPL_LUSERCLIENT: // 251 case RPL_LUSEROP: // 252 case RPL_LUSERUNKNOWN: // 253 case RPL_LUSERCHANNELS: // 254 case RPL_LUSERME: // 255 case RPL_LUSERLOCAL: // 265 case RPL_LUSERGLOBAL: // 266 { BString theMsg (RestOfString (data, 4)); theMsg.RemoveFirst (":"); theMsg.Prepend ("* "); theMsg.Append ("\n"); Display (theMsg.String()); } return true; /// strip and send to server agent /// case RPL_ULMAP: // 006 case RPL_ULMAPEND: // 007 case RPL_U2MAP: // 015 case RPL_U2MAPEND: // 017 case RPL_TRACELINK: // 200 case RPL_TRACECONNECTING: // 201 case RPL_TRACEHANDSHAKE: // 202 case RPL_TRACEUNKNOWN: // 203 case RPL_TRACEOPERATOR: // 204 case RPL_TRACEUSER: // 205 case RPL_TRACESERVER: // 206 case RPL_TRACENEWTYPE: // 208 case RPL_TRACECLASS: // 209 case RPL_STATSLINKINFO: // 211 case RPL_STATSCOMMANDS: // 212 case RPL_STATSCLINE: // 213 case RPL_STATSNLINE: // 214 case RPL_STATSILINE: // 215 case RPL_STATSKLINE: // 216 case RPL_STATSQLINE: // 217 case RPL_STATSYLINE: // 218 case RPL_ENDOFSTATS: // 219 case RPL_STATSBLINE: // 220 case RPL_DALSTATSE: // 223 case RPL_DALSTATSF: // 224 case RPL_DALSTATSZ: // 225 case RPL_DALSTATSN: // 226 case RPL_DALSTATSG: // 227 case RPL_STATSLLINE: // 241 case RPL_STATSUPTIME: // 242 case RPL_STATSOLINE: // 243 case RPL_STATSHLINE: // 244 case RPL_STATSSLINE: // 245 case RPL_DALSTATSX: // 246 case RPL_STATSXLINE: // 247 case RPL_STATSPLINE: // 249 case RPL_ADMINME: // 256 case RPL_ADMINLOC1: // 257 case RPL_ADMINLOC2: // 258 case RPL_ADMINEMAIL: // 259 case RPL_TRACELOG: // 261 case RPL_ENDOFTRACE: // 262 case RPL_SILELIST: // 271 case RPL_ENDOFSILELIST: // 272 case RPL_ENDOFWHO: // 315 case RPL_CHANSERVURL: // 328 case RPL_COMMANDSYNTAX: // 334 case RPL_VERSION: // 351 case RPL_WHOREPLY: // 352 case RPL_BANLIST: // 367 case RPL_ENDOFBANLIST: // 368 case RPL_INFO: // 371 case RPL_ENDOFINFO: // 374 case RPL_YOUREOPER: // 381 case RPL_REHASHING: // 382 case RPL_TIME: // 391 case ERR_NOORIGIN: // 409 case ERR_NOTEXTTOSEND: // 412 case ERR_TOOMANYAWAY: // 429 case ERR_NICKCHANGETOOFAST: // 438 case ERR_TARGETCHANGETOOFAST: // 439 case ERR_SUMMONDISABLED: // 445 case ERR_USERSDISABLED: // 446 case ERR_NOTREGISTERED: // 451 case ERR_NEEDMOREPARMS: // 461 case ERR_PASSWDMISMATCH: // 464 case ERR_YOUREBANNEDCREEP: // 465 case ERR_NOPRIVILEGES: // 481 case ERR_NOOPERHOST: // 491 case ERR_USERSDONTMATCH: // 502 case ERR_SILELISTFULL: // 511 case ERR_TOOMANYWATCH: // 512 case ERR_TOOMANYDCC: // 514 case ERR_CANTINVITE: // 518 case ERR_LISTSYNTAX: // 521 case ERR_WHOSYNTAX: // 522 case ERR_WHOLIMEXCEED: // 523 case RPL_LOGON: // 600 case RPL_LOGOFF: // 601 case RPL_WATCHOFF: // 602 case RPL_WATCHSTAT: // 603 case RPL_NOWON: // 604 case RPL_NOWOFF: // 605 case RPL_WATCHLIST: // 606 case RPL_ENDOFWATCHLIST: // 607 case RPL_DCCALLOWLIST: // 618 case RPL_DCCALLOWEND: // 619 case RPL_DCCALLOW: // 620 { BString tempString (RestOfString (data, 4)); tempString.RemoveFirst (":"); tempString.Append ("\n"); Display (tempString.String()); } return true; case RPL_UMODEIS: // 221 { BString theMode (GetWord (data, 4)); BString tempString = B_TRANSLATE("Your current mode is %1"); tempString.ReplaceFirst("%1", theMode); tempString += '\n'; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_WHOIS); PostActive (&msg); } return true; /// strip and send to active agent /// case RPL_TRYAGAIN: // 263 case RPL_UNAWAY: // 305 case RPL_NOWAWAY: // 306 case ERR_NOSUCHNICK: // 401 case ERR_NOSUCHSERVER: // 402 case ERR_NOSUCHCHANNEL: // 403 case ERR_CANNOTSENDTOCHAN: // 404 case ERR_TOOMANYCHANNELS: // 405 case ERR_WASNOSUCHNICK: // 406 case ERR_TOOMANYTARGETS: // 407 case ERR_NOCOLORSONCHAN: // 408 case ERR_YOUCANTDOTHAT: // 460 case ERR_CHANOPRIVSNEEDED: // 482 { BString tempString ("[x] "); if (num == ERR_CHANOPRIVSNEEDED) tempString += RestOfString (data, 5); else tempString += RestOfString (data, 4); tempString.RemoveFirst (":"); tempString.Append ("\n"); BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&msg); } return true; case RPL_AWAY: // 301 { BString theNick (GetWord(data, 4)); BString tempString ("[x] "), theReason (RestOfString(data, 5)); theReason.RemoveFirst(":"); tempString += "Away: "; tempString += theReason; tempString += '\n'; if (fRemoteAwayMessages.find(theNick) != fRemoteAwayMessages.end()) { if (fRemoteAwayMessages[theNick] == theReason) { return true; } } fRemoteAwayMessages[theNick] = theReason; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&msg); } return true; case RPL_USERHOST: // 302 { BString theHost (GetWord (data, 4)), theHostname (GetAddress (theHost.String())); theHost.RemoveFirst (":"); BString tempString (RestOfString (data, 4)); tempString.RemoveFirst (":"); tempString.Append ("\n"); Display (tempString.String()); if (fGetLocalIP && (tempString.IFindFirst (fMyNick.String()) == 0)) { fGetLocalIP = false; struct addrinfo *info; struct addrinfo hints; memset(&hints, 0, sizeof(addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; int result = getaddrinfo(theHostname.String(), NULL, &hints, &info); if (result == 0) { char addr_buf[INET6_ADDRSTRLEN]; getnameinfo(info->ai_addr, info->ai_addrlen, addr_buf, sizeof(addr_buf), NULL, 0, NI_NUMERICHOST); fLocalip = addr_buf; printf("Got address: %s\n", fLocalip.String()); freeaddrinfo(info); return true; } } } return true; case RPL_ISON: // 303 { BString nicks (RestOfString (data, 4)); BString onlined, offlined; nicks.RemoveFirst (":"); int hasChanged (0); BMessage msg (M_NOTIFYLIST_UPDATE); for (int32 i = 0; i < fNotifyNicks.CountItems(); i++) { NotifyListItem *item (((NotifyListItem *)fNotifyNicks.ItemAt(i))); int32 nickidx (nicks.IFindFirst(item->Text())); // make sure that the nick isn't a partial match. if ((nickidx >= 0) && ((nicks[nickidx + strlen(item->Text())] == ' ') || (nicks[nickidx + strlen(item->Text())] == '\0'))) { if (item->GetState() != true) { item->SetState (true); hasChanged = 1; if (onlined.Length()) onlined << ", "; onlined << item->Text(); #ifdef USE_INFOPOPPER if (be_roster->IsRunning(InfoPopperAppSig) == true) { entry_ref ref = vision_app->AppRef(); BMessage infoMsg(InfoPopper::AddMessage); infoMsg.AddString("appTitle", S_INFOPOPPER_TITLE); infoMsg.AddString("title", fId.String()); infoMsg.AddInt8("type", (int8)InfoPopper::Information); infoMsg.AddInt32("iconType", InfoPopper::Attribute); infoMsg.AddRef("iconRef", &ref); BString content; content << item->Text() << " is online"; infoMsg.AddString("content", content); BMessenger(InfoPopperAppSig).SendMessage(&infoMsg); }; #endif } } else { if (item->GetState() == true) { item->SetState (false); hasChanged = 2; if (offlined.Length()) offlined << ", "; offlined << item->Text(); #ifdef USE_INFOPOPPER if (be_roster->IsRunning(InfoPopperAppSig) == true) { entry_ref ref = vision_app->AppRef(); BMessage infoMsg(InfoPopper::AddMessage); infoMsg.AddString("appTitle", S_INFOPOPPER_TITLE); infoMsg.AddString("title", fId.String()); infoMsg.AddInt8("type", (int8)InfoPopper::Information); infoMsg.AddInt32("iconType", InfoPopper::Attribute); infoMsg.AddRef("iconRef", &ref); BString content; content << item->Text() << " is offline"; infoMsg.AddString("content", content); BMessenger(InfoPopperAppSig).SendMessage(&infoMsg); }; #endif } } #ifdef __HAIKU__ if (offlined.Length()) { BNotification notification(B_INFORMATION_NOTIFICATION); notification.SetGroup(BString("Vision")); entry_ref ref = vision_app->AppRef(); notification.SetOnClickFile(&ref); notification.SetTitle(fServerName.String()); BString content; content << offlined; if (offlined.FindFirst(' ') > -1) content << " are offline"; else content << " is offline"; notification.SetContent(content); notification.Send(); } if (onlined.Length()) { BNotification notification(B_INFORMATION_NOTIFICATION); notification.SetGroup(BString("Vision")); entry_ref ref = vision_app->AppRef(); notification.SetOnClickFile(&ref); notification.SetTitle(fServerName.String()); BString content; content << onlined; if (onlined.FindFirst(' ') > -1) content << " are online"; else content << " is online"; notification.SetContent(content); notification.Send(); } #endif } fNotifyNicks.SortItems(SortNotifyItems); msg.AddPointer ("list", &fNotifyNicks); msg.AddPointer ("source", this); msg.AddInt32 ("change", hasChanged); Window()->PostMessage (&msg); } return true; case RPL_WHOISIDENTIFIED: // 307 { BString theInfo (RestOfString (data, 5)); theInfo.RemoveFirst (":"); if (theInfo == "-9z99") { // USERIP reply? (RPL_U2USERIP) BString tempString (RestOfString (data, 4)); tempString.RemoveFirst (":"); tempString.Append ("\n"); Display (tempString.String()); return true; } BMessage display (M_DISPLAY); BString buffer; buffer += "[x] "; buffer += theInfo; buffer += "\n"; PackDisplay (&display, buffer.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&display); } return true; case RPL_WHOISADMIN: // 308 case RPL_WHOISSERVICESADMIN: // 309 case RPL_WHOISHELPOP: // 310 case RPL_WHOISOPERATOR: // 313 case RPL_WHOISREGNICK: // 320 case RPL_WHOISACTUALLY: // 338 case RPL_WHOISMASK: // 550 case RPL_WHOWASIP: // 612 case RPL_WHOISUSERMODESALT: // 614 case RPL_WHOISUSERMODES: // 615 case RPL_WHOISREALHOSTNAME: // 616 { BString theInfo (RestOfString (data, 5)); theInfo.RemoveFirst (":"); BMessage display (M_DISPLAY); BString buffer; buffer += "[x] "; buffer += theInfo; buffer += "\n"; PackDisplay (&display, buffer.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&display); } return true; case RPL_WHOISUSER: // 311 { BString theNick (GetWord (data, 4)), theIdent (GetWord (data, 5)), theAddress (GetWord (data, 6)), theName (RestOfString (data, 8)); theName.RemoveFirst (":"); BMessage display (M_DISPLAY); BString buffer; buffer += "[x] "; buffer += theNick; buffer += " ("; buffer += theIdent; buffer += "@"; buffer += theAddress; buffer += ")\n"; buffer += "[x] "; buffer += theName; buffer += "\n"; PackDisplay (&display, buffer.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&display); } return true; case RPL_WHOISSERVER: // 312 { BString theNick (GetWord (data, 4)), theServer (GetWord (data, 5)), theInfo (RestOfString (data, 6)); theInfo.RemoveFirst (":"); BMessage display (M_DISPLAY); BString buffer; buffer += "[x] Server: "; buffer += theServer; buffer += " ("; buffer += theInfo; buffer += ")\n"; PackDisplay (&display, buffer.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&display); } return true; case RPL_WHOWASUSER: // 314 { BString theNick (GetWord (data, 4)), theIdent (GetWord (data, 5)), theAddress (GetWord (data, 6)), theName (RestOfString (data, 8)), tempString ("[x] "); theName.RemoveFirst (":"); tempString += B_TRANSLATE("%1 was (%2)"); tempString.ReplaceFirst("%1", theNick); BString nickString = theIdent << "@" << theAddress; tempString.ReplaceFirst("%2", nickString.String()); tempString += "\n"; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&msg); } return true; case RPL_WHOISIDLE: // 317 { BString theNick (GetWord (data, 4)), tempString ("[x] "), tempString2 ("[x] "), theTime (GetWord (data, 5)), signOnTime (GetWord (data, 6)); int64 idleTime (strtoul(theTime.String(), NULL, 0)); tempString += B_TRANSLATE("Idle"); tempString += ": "; tempString += DurationString(idleTime * 1000 * 1000); tempString += "\n"; int32 serverTime = strtoul(signOnTime.String(), NULL, 0); struct tm ptr; time_t st; char str[80]; st = serverTime; localtime_r (&st, &ptr); strftime (str,80,"%A %b %d %Y %I:%M %p %Z", &ptr); BString signOnTimeParsed (str); signOnTimeParsed.RemoveAll ("\n"); tempString2 += B_TRANSLATE("Signon"); tempString2 += ": "; tempString2 += signOnTimeParsed; tempString2 += "\n"; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&msg); PackDisplay (&msg, tempString2.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&msg); } return true; case RPL_ENDOFWHOIS: // 318 case RPL_ENDOFNAMES: // 366 case RPL_ENDOFWHOWAS: // 369 { // nothing } return true; case RPL_WHOISCHANNELS: // 319 { BString theChannels (RestOfString (data, 5)); theChannels.RemoveFirst(":"); BMessage display (M_DISPLAY); BString buffer = "[x] "; buffer += B_TRANSLATE("Channels"); buffer += ": "; buffer += theChannels; buffer += "\n"; PackDisplay (&display, buffer.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&display); } return true; case RPL_LISTSTART: // 321 { BMessage msg (M_LIST_BEGIN); if (fListAgent) vision_app->pClientWin()->DispatchMessage(&msg, (BView *)fListAgent); } return true; case RPL_LIST: // 322 { BMessage msg (M_LIST_EVENT); BString channel (GetWord (data, 4)), users (GetWord (data, 5)), topic (RestOfString (data, 6)); topic.RemoveFirst (":"); msg.AddString ("channel", channel.String()); msg.AddString ("users", users.String()); msg.AddString ("topic", topic.String()); if (fListAgent) vision_app->pClientWin()->DispatchMessage(&msg, (BView *)fListAgent); } return true; case RPL_LISTEND: // 323 { BMessage msg (M_LIST_DONE); if (fListAgent) vision_app->pClientWin()->DispatchMessage(&msg, (BView *)fListAgent); } return true; case RPL_CHANNELMODEIS: // 324 { BString theChan (GetWord (data, 4)), theMode (GetWord (data, 5)), tempStuff (RestOfString (data, 6)); if (tempStuff != "-9z99") { theMode.Append(" "); theMode.Append(tempStuff); // avoid extra space w/o params } ClientAgent *aClient (ActiveClient()), *theClient (Client (theChan.String())); BString tempString("*** "); tempString += B_TRANSLATE("Channel mode for %1: %2"); tempString.ReplaceFirst("%1", theChan.String()); tempString.ReplaceFirst("%2", theMode.String()); tempString += '\n'; BMessage msg (M_CHANNEL_MODES); msg.AddString ("msgz", tempString.String()); msg.AddString ("chan", theChan.String()); msg.AddString ("mode", theMode.String()); if (theClient) theClient->fMsgr.SendMessage (&msg); else if (aClient) aClient->fMsgr.SendMessage (&msg); else Display (tempString.String(), C_OP); } return true; case RPL_CHANNELMLOCK: // 325 { BString theChan (GetWord (data, 4)), mLock (GetWord (data, 8)), lockMessage ("*** "); lockMessage += B_TRANSLATE("Channel mode lock for %1: %2"); lockMessage.ReplaceFirst("%1", theChan); lockMessage.ReplaceFirst("%2", mLock); lockMessage += "\n"; BMessage display (M_DISPLAY); PackDisplay (&display, lockMessage.String(), C_OP, C_BACKGROUND, F_TEXT); ClientAgent *theClient (Client (theChan.String())); if (theClient) theClient->fMsgr.SendMessage (&display); else fMsgr.SendMessage (&display); } return true; case RPL_CHANNELCREATED: // 329 { BString theChan (GetWord (data, 4)), theTime (GetWord (data, 5)), tempString; int32 serverTime (strtoul(theTime.String(), NULL, 0)); struct tm ptr; time_t st; char str[80]; st = serverTime; localtime_r (&st, &ptr); strftime (str,80,"%a %b %d %Y %I:%M %p %Z",&ptr); BString theTimeParsed (str); theTimeParsed.RemoveAll ("\n"); tempString = B_TRANSLATE("Channel %1 was created at %2"); tempString.ReplaceFirst("%1", theChan); tempString.ReplaceFirst("%2", theTimeParsed); tempString += '\n'; Display (tempString.String()); } return true; case RPL_NOTOPIC: // 331 { BString theChan (GetWord (data, 4)), tempString ("[x] "); tempString += B_TRANSLATE("No topic set in %1"); tempString.ReplaceFirst("%1", theChan); tempString += '\n'; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_ERROR); PostActive (&msg); } return true; case RPL_TOPIC: // 332 { BString theChannel (GetWord (data, 4)), theTopic (RestOfString (data, 5)); ClientAgent *client (Client (theChannel.String())); theTopic.RemoveFirst (":"); if (client) { BMessage display (M_DISPLAY); BString buffer; buffer += "*** "; buffer += B_TRANSLATE("Topic: %1"); buffer.ReplaceFirst("%1", theTopic); buffer += '\n'; PackDisplay (&display, buffer.String(), C_WHOIS); BMessage msg (M_CHANNEL_TOPIC); msg.AddString ("topic", theTopic.String()); msg.AddMessage ("display", &display); if (client->fMsgr.IsValid()) client->fMsgr.SendMessage (&msg); } } return true; case RPL_TOPICSET: // 333 { BString channel (GetWord (data, 4)), user (GetWord (data, 5)), theTime (GetWord (data, 6)); int32 serverTime (strtoul(theTime.String(), NULL, 0)); struct tm ptr; time_t st; char str[80]; st = serverTime; localtime_r (&st, &ptr); strftime (str,80,"%A %b %d %Y %I:%M %p %Z",&ptr); BString theTimeParsed (str); theTimeParsed.RemoveAll ("\n"); ClientAgent *client (Client (channel.String())); if (client) { BMessage display (M_DISPLAY); BString buffer = "*** "; buffer += B_TRANSLATE("Topic set by %1 at %2"); buffer.ReplaceFirst("%1", user); buffer.ReplaceFirst("%2", theTimeParsed); buffer += '\n'; PackDisplay (&display, buffer.String(), C_WHOIS); if (client->fMsgr.IsValid()) client->fMsgr.SendMessage (&display); } } return true; case RPL_INVITING: // 341 { BString channel (GetWord (data, 5)), theNick (GetWord (data, 4)), tempString; tempString += "*** "; tempString += B_TRANSLATE("%1 has been invited to %2."); tempString.ReplaceFirst("%1", theNick); tempString.ReplaceFirst("%2", channel); tempString += "\n"; BMessage display (M_DISPLAY); PackDisplay (&display, tempString.String(), C_WHOIS); PostActive (&display); } return true; case RPL_NAMEREPLY: // 353 { BString channel (GetWord (data, 5)), names (RestOfString (data, 6)); ClientAgent *client (Client (channel.String())); names.RemoveFirst (":"); BString tempString ("*** "); tempString += B_TRANSLATE("Users in %1: %2"); tempString.ReplaceFirst("%1", channel); tempString.ReplaceFirst("%2", names); tempString += '\n'; Display (tempString.String(), C_TEXT); if (client) // in the channel { BMessage msg (M_CHANNEL_NAMES); BString nick; int32 place (1); while ((nick = GetWord (names.String(), place)) != "-9z99") { const char *sNick (nick.String()); bool founder (false), protect (false), op (false), voice (false), helper (false), ignored; if (nick[0] == '*') { ++sNick; founder = true; } else if (nick[0] == '!') { ++sNick; protect = true; } else if (nick[0] == '@') { ++sNick; op = true; } else if (nick[0] == '+') { ++sNick; voice = true; } else if (nick[0] == '%') { ++sNick; helper = true; } ignored = false; // BMessage aMsg (M_IS_IGNORED), reply; // aMsg.AddString ("server", fServerName.String()); // aMsg.AddString ("nick", sNick); // be_app_messenger.SendMessage (&aMsg, &reply); // reply.FindBool ("ignored", &ignored); msg.AddString ("nick", nick.String()); msg.AddBool ("founder", founder); msg.AddBool ("protect", protect); msg.AddBool ("op", op); msg.AddBool ("voice", voice); msg.AddBool ("helper", helper); msg.AddBool ("ignored", ignored); ++place; } if (client->fMsgr.IsValid()) client->fMsgr.SendMessage (&msg); } } return true; case RPL_MOTD: // 372 case RPL_MOTDALT: // 378 case RPL_OPERMOTDSTART: // 609 case RPL_OPERMOTD: // 610 case RPL_OPERENDOFMOTD: // 611 { BString tempString (RestOfString(data, 4)); tempString.RemoveFirst (":"); tempString.Append ("\n"); Display (tempString.String(), C_SERVER, C_BACKGROUND, F_SERVER); } return true; case RPL_MOTDSTART: // 375 { BString tempString ("- "); tempString += B_TRANSLATE("Server Message Of the Day"); tempString += ":\n"; Display (tempString.String(), C_SERVER, C_BACKGROUND, F_SERVER); } return true; case RPL_ENDOFMOTD: // 376 case ERR_NOMOTD: // 422 { BString tempString (RestOfString (data, 4)); tempString.RemoveFirst (":"); tempString.Append ("\n"); Display (tempString.String(), C_SERVER, C_BACKGROUND, F_SERVER); if (fInitialMotd && fCmds.Length()) { BMessage msg (M_SUBMIT_INPUT); const char *place (fCmds.String()), *eol; msg.AddInt32 ("which", PASTE_MULTI_NODELAY); while ((eol = strchr (place, '\n')) != 0) { BString line; line.Append (place, eol - place); msg.AddString ("data", line.String()); ParseAutoexecChans (line); place = eol + 1; } if (*place) { // check in case this was the only line ParseAutoexecChans (BString(place)); msg.AddString ("data", place); } msg.AddInt32 ("which", 3); msg.AddBool ("autoexec", true); fMsgr.SendMessage (&msg); } BString IPCommand ("/userhost "); IPCommand += fMyNick; ParseCmd (IPCommand.String()); if (fReconnecting) { BString reString = "[@] "; reString += B_TRANSLATE("Successful reconnect"); reString += "\n"; Display (reString.String(), C_ERROR); DisplayAll (reString.String(), C_ERROR, C_BACKGROUND, F_SERVER); fMsgr.SendMessage (M_REJOIN_ALL); fReconnecting = false; } fInitialMotd = false; } return true; case RPL_USERSSTART: // 392 { // empty for now } return true; case RPL_USERS: // 393 { // empty for now } return true; case ERR_ERRONEOUSNICKNAME: // 432 case ERR_NICKNAMEINUSE: // 433 case ERR_RESOURCEUNAVAILABLE: // 437 { BString theNick (GetWord (data, 4)); if (fIsConnecting) { BString nextNick (GetNextNick()); if (nextNick != "") { BString tempString = "* "; tempString += B_TRANSLATE("Nickname \"%1\" in use or unavailable, trying \"%2\""); tempString.ReplaceFirst("%1", theNick.String()); tempString.ReplaceFirst("%2", nextNick.String()); tempString += "\n"; Display (tempString.String()); tempString = "NICK "; tempString += nextNick; SendData (tempString.String()); return true; } else { BString tempString = "* "; tempString += B_TRANSLATE("All your pre-selected nicknames are in use."); tempString += "\n"; Display (tempString.String()); tempString = "* "; tempString += B_TRANSLATE("Please type /NICK <NEWNICK> to try another."); tempString += "\n"; Display (tempString.String()); return true; } } BString tempString = "[x] "; tempString += B_TRANSLATE("Nickname/Channel \"%1\" is already in use or unavailable."); tempString.ReplaceFirst("%1", theNick); tempString += "\n"; BMessage display (M_DISPLAY); PackDisplay (&display, tempString.String(), C_NICK); PostActive (&display); } return true; case ERR_USERNOTINCHANNEL: // 441 { BString theChannel (GetWord (data, 5)), theNick (GetWord (data, 4)), tempString ("[x] "); tempString += B_TRANSLATE("%1 not in %2."); tempString.ReplaceFirst("%1", theNick); tempString.ReplaceFirst("%2", theChannel); tempString += "\n"; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_ERROR); PostActive (&msg); } return true; case ERR_NOTONCHANNEL: // 442 { BString theChannel (GetWord (data, 4)), tempString ("[x] "); tempString += B_TRANSLATE("You're not in %1."); tempString.ReplaceFirst("%1", theChannel); tempString += "\n"; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_ERROR); PostActive (&msg); } return true; case ERR_USERONCHANNEL: // 443 { BString theChannel (GetWord (data, 5)), theNick (GetWord (data, 4)), tempString ("[x] "); tempString += B_TRANSLATE("%1 is already in %2."); tempString.ReplaceFirst("%1", theNick); tempString.ReplaceFirst("%2", theChannel); tempString += "\n"; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_ERROR); PostActive (&msg); } return true; case ERR_KEYSET: // 467 { BString theChannel (GetWord (data, 4)), tempString ("[x] "); tempString += B_TRANSLATE("Channel key already set in %1."); tempString.ReplaceFirst("%1", theChannel); tempString += "\n"; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_ERROR); PostActive (&msg); } return true; case ERR_UNKNOWNMODE: // 472 { BString theMode (GetWord (data, 4)), tempString ("[x] "); tempString += B_TRANSLATE("Unknown channel mode: '%1'."); tempString.ReplaceFirst("%1", theMode); tempString += "\n"; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_QUIT); PostActive (&msg); } return true; case ERR_INVITEONLYCHAN: // 473 { BString theChan (GetWord (data, 4)), tempString ("[x] "), theReason (RestOfString (data, 5)); theReason.RemoveFirst(":"); theReason.ReplaceLast("channel", theChan.String()); tempString << theReason < " "; tempString += B_TRANSLATE("(invite only)"); tempString += "\n"; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_QUIT, C_BACKGROUND, F_SERVER); PostActive (&msg); RemoveAutoexecChan (theChan); } return true; case ERR_BANNEDFROMCHAN: // 474 { BString theChan (GetWord (data, 4)), tempString ("[x] "), theReason (RestOfString (data, 5)); theReason.RemoveFirst(":"); theReason.ReplaceLast("channel", theChan.String()); tempString << theReason < " "; tempString += B_TRANSLATE("(you're banned)"); tempString += "\n"; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_QUIT, C_BACKGROUND, F_SERVER); PostActive (&msg); RemoveAutoexecChan (theChan); } return true; case ERR_BADCHANNELKEY: // 475 { BString theChan (GetWord(data, 4)), theReason (RestOfString(data, 5)), tempString("[x] "); theReason.RemoveFirst(":"); theReason.ReplaceLast("channel", theChan.String()); tempString << theReason << " "; tempString += B_TRANSLATE("(bad channel key)"); tempString += "\n"; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_QUIT, C_BACKGROUND, F_SERVER); PostActive (&msg); RemoveAutoexecChan (theChan); } return true; case ERR_UMODEUNKNOWNFLAG: // 501 { BMessage msg (M_DISPLAY); BString buffer = "[x] "; buffer += B_TRANSLATE("Unknown mode flag."); buffer += "\n"; PackDisplay (&msg, buffer.String(), C_QUIT); PostActive (&msg); } return true; // not sure what these numerics are, // but they are usually on-connect messages case RPL_290: // 290 case RPL_291: // 291 case RPL_292: // 292 { BString tempString (RestOfString(data, 4)); tempString.RemoveFirst (":"); tempString.Append ("\n"); tempString.Prepend ("- "); Display (tempString.String()); } return true; case RPL_WHOISREGISTEREDBOT: // 617 { // conflicts with RPL_DCCALLOWCHANGE BString theNick (GetWord (data, 4)), theMessage (RestOfString (data, 5)), tempString; theNick.RemoveFirst (":"); theMessage.RemoveFirst (":"); theMessage.Append ("\n"); switch (fIrcdtype) { case IRCD_ULTIMATE: { tempString += "[@] "; tempString += theMessage; BMessage msg (M_DISPLAY); PackDisplay (&msg, tempString.String(), C_WHOIS, C_BACKGROUND, F_SERVER); PostActive (&msg); } break; default: { tempString += theNick; tempString += " "; tempString += theMessage; Display (tempString.String()); } } } return true; default: break; } return false; }
/*! Get tickval as struct timespec \return result */ struct timespec as_ts() const { const timespec ts = { secs(), static_cast<long>(nsecs()) }; return ts; }
RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors) const { QRegExp metricUnits("(km|kph|km/h)", Qt::CaseInsensitive); QRegExp englishUnits("(miles|mph|mp/h)", Qt::CaseInsensitive); bool metric; QDateTime startTime; // TODO: a more robust regex for ergomo files // i don't have an example with english headers // the ergomo CSV has two rows of headers. units are on the second row. /* ZEIT,STRECKE,POWER,RPM,SPEED,PULS,HÖHE,TEMP,INTERVAL,PAUSE L_SEC,KM,WATT,RPM,KM/H,BPM,METER,°C,NUM,SEC */ QRegExp ergomoCSV("(ZEIT|STRECKE)", Qt::CaseInsensitive); bool ergomo = false; int unitsHeader = 1; int total_pause = 0; int currentInterval = 0; int prevInterval = 0; // TODO: with all these formats, should the logic change to a switch/case structure? // The iBike format CSV file has five lines of headers (data begins on line 6) // starting with: /* iBike,8,english 2008,8,8,6,32,52 {Various configuration data, recording interval at line[4][4]} Speed (mph),Wind Speed (mph),Power (W),Distance (miles),Cadence (RPM),Heartrate (BPM),Elevation (feet),Hill slope (%),Internal,Internal,Internal,DFPM Power,Latitude,Longitude */ // Modified the regExp string to allow for 2-digit version numbers - 23 Mar 2009, thm QRegExp iBikeCSV("iBike,\\d\\d?,[a-z]+", Qt::CaseInsensitive); bool iBike = false; int recInterval; if (!file.open(QFile::ReadOnly)) { errors << ("Could not open ride file: \"" + file.fileName() + "\""); return NULL; } int lineno = 1; QTextStream is(&file); RideFile *rideFile = new RideFile(); int iBikeInterval = 0; bool dfpmExists = false; int iBikeVersion = 0; while (!is.atEnd()) { // the readLine() method doesn't handle old Macintosh CR line endings // this workaround will load the the entire file if it has CR endings // then split and loop through each line // otherwise, there will be nothing to split and it will read each line as expected. QString linesIn = is.readLine(); QStringList lines = linesIn.split('\r'); // workaround for empty lines if(lines.isEmpty()) { lineno++; continue; } for (int li = 0; li < lines.size(); ++li) { QString line = lines[li]; if (lineno == 1) { if (ergomoCSV.indexIn(line) != -1) { ergomo = true; rideFile->setDeviceType("Ergomo CSV"); unitsHeader = 2; ++lineno; continue; } else { if(iBikeCSV.indexIn(line) != -1) { iBike = true; rideFile->setDeviceType("iBike CSV"); unitsHeader = 5; iBikeVersion = line.section( ',', 1, 1 ).toInt(); ++lineno; continue; } rideFile->setDeviceType("PowerTap CSV"); } } if (iBike && lineno == 2) { QStringList f = line.split(","); if (f.size() == 6) { startTime = QDateTime( QDate(f[0].toInt(), f[1].toInt(), f[2].toInt()), QTime(f[3].toInt(), f[4].toInt(), f[5].toInt())); } } if (iBike && lineno == 4) { // this is the line with the iBike configuration data // recording interval is in the [4] location (zero-based array) // the trailing zeroes in the configuration area seem to be causing an error // the number is in the format 5.000000 recInterval = (int)line.section(',',4,4).toDouble(); } if (lineno == unitsHeader) { if (metricUnits.indexIn(line) != -1) metric = true; else if (englishUnits.indexIn(line) != -1) metric = false; else { errors << "Can't find units in first line: \"" + line + "\" of file \"" + file.fileName() + "\"."; delete rideFile; file.close(); return NULL; } } else if (lineno > unitsHeader) { double minutes,nm,kph,watts,km,cad,alt,hr,dfpm; double lat = 0.0, lon = 0.0; double headwind = 0.0; int interval; int pause; if (!ergomo && !iBike) { minutes = line.section(',', 0, 0).toDouble(); nm = line.section(',', 1, 1).toDouble(); kph = line.section(',', 2, 2).toDouble(); watts = line.section(',', 3, 3).toDouble(); km = line.section(',', 4, 4).toDouble(); cad = line.section(',', 5, 5).toDouble(); hr = line.section(',', 6, 6).toDouble(); interval = line.section(',', 7, 7).toInt(); alt = line.section(',', 8, 8).toDouble(); if (!metric) { km *= KM_PER_MILE; kph *= KM_PER_MILE; alt *= METERS_PER_FOOT; } } else if (iBike) { // this must be iBike // can't find time as a column. // will we have to extrapolate based on the recording interval? // reading recording interval from config data in ibike csv file // // For iBike software version 11 or higher: // use "power" field until a the "dfpm" field becomes non-zero. minutes = (recInterval * lineno - unitsHeader)/60.0; nm = NULL; //no torque kph = line.section(',', 0, 0).toDouble(); dfpm = line.section( ',', 11, 11).toDouble(); if( iBikeVersion >= 11 && ( dfpm > 0.0 || dfpmExists ) ) { dfpmExists = true; watts = dfpm; headwind = line.section(',', 1, 1).toDouble(); } else { watts = line.section(',', 2, 2).toDouble(); } km = line.section(',', 3, 3).toDouble(); cad = line.section(',', 4, 4).toDouble(); hr = line.section(',', 5, 5).toDouble(); alt = line.section(',', 6, 6).toDouble(); lat = line.section(',', 12, 12).toDouble(); lon = line.section(',', 13, 13).toDouble(); int lap = line.section(',', 9, 9).toInt(); if (lap > 0) { iBikeInterval += 1; interval = iBikeInterval; } if (!metric) { km *= KM_PER_MILE; kph *= KM_PER_MILE; alt *= METERS_PER_FOOT; headwind *= KM_PER_MILE; } } else { // for ergomo formatted CSV files minutes = line.section(',', 0, 0).toDouble() + total_pause; km = line.section(',', 1, 1).toDouble(); watts = line.section(',', 2, 2).toDouble(); cad = line.section(',', 3, 3).toDouble(); kph = line.section(',', 4, 4).toDouble(); hr = line.section(',', 5, 5).toDouble(); alt = line.section(',', 6, 6).toDouble(); interval = line.section(',', 8, 8).toInt(); if (interval != prevInterval) { prevInterval = interval; if (interval != 0) currentInterval++; } if (interval != 0) interval = currentInterval; pause = line.section(',', 9, 9).toInt(); total_pause += pause; nm = NULL; // torque is not provided in the Ergomo file // the ergomo records the time in whole seconds // RECORDING INT. 1, 2, 5, 10, 15 or 30 per sec // Time is *always* perfectly sequential. To find pauses, // you need to read the PAUSE column. minutes = minutes/60.0; if (!metric) { km *= KM_PER_MILE; kph *= KM_PER_MILE; alt *= METERS_PER_FOOT; } } // PT reports no data as watts == -1. if (watts == -1) watts = 0; rideFile->appendPoint(minutes * 60.0, cad, hr, km, kph, nm, watts, alt, lat, lon, headwind, interval); } ++lineno; } } file.close(); // To estimate the recording interval, take the median of the // first 1000 samples and round to nearest millisecond. int n = rideFile->dataPoints().size(); n = qMin(n, 1000); if (n >= 2) { QVector<double> secs(n-1); for (int i = 0; i < n-1; ++i) { double now = rideFile->dataPoints()[i]->secs; double then = rideFile->dataPoints()[i+1]->secs; secs[i] = then - now; } std::sort(secs.begin(), secs.end()); int mid = n / 2 - 1; double recint = round(secs[mid] * 1000.0) / 1000.0; rideFile->setRecIntSecs(recint); } // less than 2 data points is not a valid ride file else { errors << "Insufficient valid data in file \"" + file.fileName() + "\"."; delete rideFile; file.close(); return NULL; } QRegExp rideTime("^.*/(\\d\\d\\d\\d)_(\\d\\d)_(\\d\\d)_" "(\\d\\d)_(\\d\\d)_(\\d\\d)\\.csv$"); rideTime.setCaseSensitivity(Qt::CaseInsensitive); if (startTime != QDateTime()) { rideFile->setStartTime(startTime); } else if (rideTime.indexIn(file.fileName()) >= 0) { QDateTime datetime(QDate(rideTime.cap(1).toInt(), rideTime.cap(2).toInt(), rideTime.cap(3).toInt()), QTime(rideTime.cap(4).toInt(), rideTime.cap(5).toInt(), rideTime.cap(6).toInt())); rideFile->setStartTime(datetime); } else { // Could be yyyyddmm_hhmmss_NAME.csv (case insensitive) rideTime.setPattern("(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)_(\\d\\d)(\\d\\d)(\\d\\d)[^\\.]*\\.csv$"); if (rideTime.indexIn(file.fileName()) >= 0) { QDateTime datetime(QDate(rideTime.cap(1).toInt(), rideTime.cap(2).toInt(), rideTime.cap(3).toInt()), QTime(rideTime.cap(4).toInt(), rideTime.cap(5).toInt(), rideTime.cap(6).toInt())); rideFile->setStartTime(datetime); } else { qWarning("Failed to set start time"); } } return rideFile; }
/** * Perform the C2S Throughput test. This test intends to measure throughput * from the client to the server by performing a 10 seconds memory-to-memory * data transfer. * * Protocol messages are exchanged between the Client and the Server using the * same connection and message format as the NDTP-Control protocol.Throughput * packets are sent on the new connection and do not follow the NDTP-Control * protocol message format. * * When the Client stops streaming the test data (or the server test routine * times out), the Server sends the Client its calculated throughput value. * * @param ctl Client control Connection * @param agent Web100 agent used to track the connection * @param testOptions Test options * @param conn_options connection options * @param c2sspd In-out parameter to store C2S throughput value * @param set_buff enable setting TCP send/recv buffer size to be used (seems * unused in file) * @param window value of TCP send/rcv buffer size intended to be used. * @param autotune autotuning option. Deprecated. * @param device string device name inout parameter * @param options Test Option variables * @param record_reverse integer indicating whether receiver-side statistics * have to be logged * @param count_vars count of web100 variables * @param spds[] [] speed check array * @param spd_index index used for speed check array * @param conn_options Connection options * @param ctx The SSL context (possibly NULL) * @param c2s_ThroughputSnapshots Variable used to set c2s throughput snapshots * @param extended indicates if extended c2s test should be performed * @return 0 on success, an error code otherwise * Error codes: * -1 - Listener socket creation failed * -100 - Timeout while waiting for client to connect to server's * ephemeral port * -101 - Retries exceeded while waiting for client to connect * -102 - Retries exceeded while waiting for data from connected * client * -errno - Other specific socket error numbers */ int test_c2s(Connection *ctl, tcp_stat_agent *agent, TestOptions *testOptions, int conn_options, double *c2sspd, int set_buff, int window, int autotune, char *device, Options *options, int record_reverse, int count_vars, char spds[4][256], int *spd_index, SSL_CTX *ctx, struct throughputSnapshot **c2s_ThroughputSnapshots, int extended) { tcp_stat_connection conn; tcp_stat_group *group = NULL; /* The pipe that will return packet pair results */ int mon_pipe[2]; int packet_trace_running = 0; pid_t c2s_childpid = 0; // child process pids int msgretvalue, read_error; // used during the "read"/"write" process int i; // used as loop iterator int conn_index, attempts; int retvalue = 0; int streamsNum = 1; int activeStreams = 1; int local_errno; struct sockaddr_storage cli_addr[MAX_STREAMS]; Connection c2s_conns[MAX_STREAMS]; struct throughputSnapshot *lastThroughputSnapshot; socklen_t clilen; char tmpstr[256]; // string array used for all sorts of temp storage purposes double start_time, measured_test_duration; double throughputSnapshotTime; // specify the next snapshot time double testDuration = 10; // default test duration double bytes_read = 0; // number of bytes read during the throughput tests struct timeval sel_tv; // time fd_set rfd; // receive file descriptors int max_fd; char buff[BUFFSIZE + 1]; // message "payload" buffer PortPair pair; // socket ports I2Addr c2ssrv_addr = NULL; // c2s test's server address // I2Addr src_addr=NULL; // c2s test source address char listenc2sport[10]; // listening port pthread_t workerThreadId; // snap related variables SnapArgs snapArgs; snapArgs.snap = NULL; #if USE_WEB100 snapArgs.log = NULL; #endif snapArgs.delay = options->snapDelay; // Test ID and status descriptors enum TEST_ID testids = extended ? C2S_EXT : C2S; enum TEST_STATUS_INT teststatuses = TEST_NOT_STARTED; char namesuffix[256] = "c2s_snaplog"; for (i = 0; i < MAX_STREAMS; i++) { c2s_conns[i].socket = 0; c2s_conns[i].ssl = NULL; } if (!extended && testOptions->c2sopt) { setCurrentTest(TEST_C2S); } else if (extended && testOptions->c2sextopt) { setCurrentTest(TEST_C2S_EXT); } else { return 0; } log_println(1, " <-- %d - C2S throughput test -->", testOptions->child0); strlcpy(listenc2sport, PORT2, sizeof(listenc2sport)); // log protocol validation logs teststatuses = TEST_STARTED; protolog_status(testOptions->child0, testids, teststatuses, ctl->socket); // Determine port to be used. Compute based on options set earlier // by reading from config file, or use default port2 (3002). if (testOptions->c2ssockport) { snprintf(listenc2sport, sizeof(listenc2sport), "%d", testOptions->c2ssockport); } else if (testOptions->mainport) { snprintf(listenc2sport, sizeof(listenc2sport), "%d", testOptions->mainport + 1); } if (testOptions->multiple) { strlcpy(listenc2sport, "0", sizeof(listenc2sport)); } // attempt to bind to a new port and obtain address structure with details // of listening port while (c2ssrv_addr == NULL) { c2ssrv_addr = CreateListenSocket( NULL, (testOptions->multiple ? mrange_next(listenc2sport, sizeof(listenc2sport)) : listenc2sport), conn_options, 0); if (strcmp(listenc2sport, "0") == 0) { log_println(1, "WARNING: ephemeral port number was bound"); break; } if (testOptions->multiple == 0) { break; } } if (c2ssrv_addr == NULL) { log_println(0, "Server (C2S throughput test): CreateListenSocket failed: %s", strerror(errno)); snprintf(buff, sizeof(buff), "Server (C2S throughput test): CreateListenSocket failed: %s", strerror(errno)); send_json_message_any(ctl, MSG_ERROR, buff, strlen(buff), testOptions->connection_flags, JSON_SINGLE_VALUE); return -1; } // get socket FD and the ephemeral port number that client will connect to // run tests testOptions->c2ssockfd = I2AddrFD(c2ssrv_addr); testOptions->c2ssockport = I2AddrPort(c2ssrv_addr); log_println(1, " -- c2s %d port: %d", testOptions->child0, testOptions->c2ssockport); if (extended) { log_println(1, " -- c2s ext -- duration = %d", options->c2s_duration); log_println(1, " -- c2s ext -- throughput snapshots: enabled = %s, " "delay = %d, offset = %d", options->c2s_throughputsnaps ? "true" : "false", options->c2s_snapsdelay, options->c2s_snapsoffset); log_println(1, " -- c2s ext -- number of streams: %d", options->c2s_streamsnum); } pair.port1 = testOptions->c2ssockport; pair.port2 = -1; log_println( 1, "listening for Inet connection on testOptions->c2ssockfd, fd=%d", testOptions->c2ssockfd); log_println( 1, "Sending 'GO' signal, to tell client %d to head for the next test", testOptions->child0); snprintf(buff, sizeof(buff), "%d", testOptions->c2ssockport); if (extended) { snprintf(buff, sizeof(buff), "%d %d %d %d %d %d", testOptions->c2ssockport, options->c2s_duration, options->c2s_throughputsnaps, options->c2s_snapsdelay, options->c2s_snapsoffset, options->c2s_streamsnum); lastThroughputSnapshot = NULL; } // send TEST_PREPARE message with ephemeral port detail, indicating start // of tests if ((msgretvalue = send_json_message_any( ctl, TEST_PREPARE, buff, strlen(buff), testOptions->connection_flags, JSON_SINGLE_VALUE)) < 0) { log_println(2, "Child %d could not send details about ephemeral port", getpid()); return msgretvalue; } // Wait on listening socket and read data once ready. // Retry 5 times, waiting for activity on the socket clilen = sizeof(cli_addr); log_println(6, "child %d - sent c2s prepare to client", testOptions->child0); FD_ZERO(&rfd); FD_SET(testOptions->c2ssockfd, &rfd); sel_tv.tv_sec = 5; sel_tv.tv_usec = 0; if (extended) { streamsNum = options->c2s_streamsnum; testDuration = options->c2s_duration / 1000.0; } conn_index = 0; for (attempts = 0; attempts < RETRY_COUNT * streamsNum && conn_index < streamsNum; attempts++) { msgretvalue = select((testOptions->c2ssockfd) + 1, &rfd, NULL, NULL, &sel_tv); // TODO // socket interrupted. continue waiting for activity on socket if ((msgretvalue == -1) && (errno == EINTR)) { continue; } if (msgretvalue == 0) // timeout retvalue = -SOCKET_CONNECT_TIMEOUT; if (msgretvalue < 0) // other socket errors. exit retvalue = -errno; if (!retvalue) { // If a valid connection request is received, client has connected. // Proceed. c2s_conns[conn_index].socket = accept( testOptions->c2ssockfd, (struct sockaddr *)&cli_addr[conn_index], &clilen); // socket interrupted, wait some more if ((c2s_conns[conn_index].socket == -1) && (errno == EINTR)) { log_println( 6, "Child %d interrupted while waiting for accept() to complete", testOptions->child0); continue; } if (c2s_conns[conn_index].socket <= 0) { continue; } log_println(6, "accept(%d/%d) for %d completed", conn_index + 1, streamsNum, testOptions->child0); // log protocol validation indicating client accept protolog_procstatus(testOptions->child0, testids, CONNECT_TYPE, PROCESS_STARTED, c2s_conns[conn_index].socket); if (testOptions->connection_flags & TLS_SUPPORT) { errno = setup_SSL_connection(&c2s_conns[conn_index], ctx); if (errno != 0) return -errno; } // To preserve user privacy, make sure that the HTTP header // processing is done prior to the start of packet capture, as many // browsers have headers that uniquely identify a single user. if (testOptions->connection_flags & WEBSOCKET_SUPPORT) { if (initialize_websocket_connection(&c2s_conns[conn_index], 0, "c2s") != 0) { close_all_connections(c2s_conns, streamsNum); return -EIO; } } conn_index++; } if (retvalue) { log_println( 6, "------- C2S connection setup for %d returned because (%d)", testOptions->child0, retvalue); close_all_connections(c2s_conns, streamsNum); return retvalue; } } // If we haven't created enough streams after the loop is over, quit. if (conn_index != streamsNum) { log_println( 6, "c2s child %d, unable to open connection, return from test", testOptions->child0); close_all_connections(c2s_conns, streamsNum); return RETRY_EXCEEDED_WAITING_DATA; } // Get address associated with the throughput test. Used for packet tracing log_println(6, "child %d - c2s ready for test with fd=%d", testOptions->child0, c2s_conns[0].socket); // commenting out below to move to init_pkttrace function I2Addr src_addr = I2AddrByLocalSockFD(get_errhandle(), c2s_conns[0].socket, 0); // Get tcp_stat connection. Used to collect tcp_stat variable statistics conn = tcp_stat_connection_from_socket(agent, c2s_conns[0].socket); // set up packet tracing. Collected data is used for bottleneck link // calculations if (getuid() == 0) { if (pipe(mon_pipe) != 0) { log_println(0, "C2S test error: can't create pipe."); } else { if ((c2s_childpid = fork()) == 0) { close(testOptions->c2ssockfd); close_all_connections(c2s_conns, streamsNum); // Don't capture more than 14 seconds of packet traces: // 2 seconds of sleep + 10 seconds of test + 2 seconds of slop alarm(testDuration + RACE_CONDITION_WAIT_TIME + 2); log_println( 5, "C2S test Child %d thinks pipe() returned fd0=%d, fd1=%d", testOptions->child0, mon_pipe[0], mon_pipe[1]); log_println(2, "C2S test calling init_pkttrace() with pd=%p", &cli_addr[0]); init_pkttrace(src_addr, cli_addr, streamsNum, clilen, mon_pipe, device, &pair, "c2s", options->c2s_duration / 1000.0); log_println(1, "c2s is exiting gracefully"); /* Close the pipe */ close(mon_pipe[0]); close(mon_pipe[1]); exit(0); /* Packet trace finished, terminate gracefully */ } else if (c2s_childpid < 0) { log_println(0, "C2S test error: can't create child process."); } } packet_trace_running = wait_for_readable_fd(mon_pipe[0]); if (packet_trace_running) { // Get data collected from packet tracing into the C2S "ndttrace" file memset(tmpstr, 0, 256); for (i = 0; i < 5; i++) { msgretvalue = read(mon_pipe[0], tmpstr, 128); if ((msgretvalue == -1) && (errno == EINTR)) continue; break; } if (strlen(tmpstr) > 5) memcpy(meta.c2s_ndttrace, tmpstr, strlen(tmpstr)); // name of nettrace file passed back from pcap child log_println(3, "--tracefile after packet_trace %s", meta.c2s_ndttrace); } else { log_println(0, "Packet trace was unable to be created"); packet_trace_emergency_shutdown(mon_pipe); } } log_println(5, "C2S test Parent thinks pipe() returned fd0=%d, fd1=%d", mon_pipe[0], mon_pipe[1]); // experimental code, delete when finished setCwndlimit(conn, group, agent, options); // Create C->S snaplog directories, and perform some initialization based on // options create_client_logdir((struct sockaddr *) &cli_addr[0], clilen, options->c2s_logname, sizeof(options->c2s_logname), namesuffix, sizeof(namesuffix)); sleep(RACE_CONDITION_WAIT_TIME); // Reset alarm() again. This 10 sec test should finish before this signal is // generated, but sleep() can render existing alarm()s invalid, and alarm() is // our watchdog timer. alarm(30); // send empty TEST_START indicating start of the test send_json_message_any(ctl, TEST_START, "", 0, testOptions->connection_flags, JSON_SINGLE_VALUE); // If snaplog recording is enabled, update meta file to indicate the same // and proceed to get snapshot and log it. // This block is needed here since the meta file stores names without the // full directory but fopen needs full path. Else, it could have gone into // the "start_snap_worker" method if (options->snapshots && options->snaplog) { memcpy(meta.c2s_snaplog, namesuffix, strlen(namesuffix)); /*start_snap_worker(&snapArgs, agent, options->snaplog, &workerLoop, &workerThreadId, meta.c2s_snaplog, options->c2s_logname, conn, group); */ } if (options->snapshots) start_snap_worker(&snapArgs, agent, NULL, options->snaplog, &workerThreadId, options->c2s_logname, conn, group); // Wait on listening socket and read data once ready. start_time = secs(); throughputSnapshotTime = start_time + (options->c2s_snapsoffset / 1000.0); activeStreams = connections_to_fd_set(c2s_conns, streamsNum, &rfd, &max_fd); while (activeStreams > 0 && (secs() - start_time) < testDuration) { // POSIX says "Upon successful completion, the select() function may // modify the object pointed to by the timeout argument." // Therefore sel_tv is undefined afterwards and we must set it every time. sel_tv.tv_sec = testDuration + 1; // time out after test duration + 1sec sel_tv.tv_usec = 0; msgretvalue = select(max_fd + 1, &rfd, NULL, NULL, &sel_tv); if (msgretvalue == -1) { if (errno == EINTR) { // select interrupted. Continue waiting for activity on socket continue; } else { log_println(1, "Error while trying to wait for incoming data in c2s: %s", strerror(errno)); break; } } if (extended && options->c2s_throughputsnaps && secs() > throughputSnapshotTime) { if (lastThroughputSnapshot != NULL) { lastThroughputSnapshot->next = (struct throughputSnapshot*) malloc(sizeof(struct throughputSnapshot)); lastThroughputSnapshot = lastThroughputSnapshot->next; } else { *c2s_ThroughputSnapshots = lastThroughputSnapshot = (struct throughputSnapshot*) malloc(sizeof(struct throughputSnapshot)); } lastThroughputSnapshot->next = NULL; lastThroughputSnapshot->time = secs() - start_time; lastThroughputSnapshot->throughput = (8.e-3 * bytes_read) / (lastThroughputSnapshot->time); // kbps log_println(6, " ---C->S: Throughput at %0.2f secs: Received %0.0f bytes, Spdin= %f", lastThroughputSnapshot->time, bytes_read, lastThroughputSnapshot->throughput); throughputSnapshotTime += options->c2s_snapsdelay / 1000.0; } if (msgretvalue > 0) { read_error = read_ready_streams(&rfd, c2s_conns, streamsNum, buff, sizeof(buff), &bytes_read); if (read_error != 0 && read_error != EINTR) { // EINTR is expected, but all other errors are actually errors log_println(1, "Error while trying to read incoming data in c2s: %s", strerror(read_error)); break; } } // Set up the FD_SET and activeStreams for the next select. activeStreams = connections_to_fd_set(c2s_conns, streamsNum, &rfd, &max_fd); } measured_test_duration = secs() - start_time; // From the NDT spec: // throughput in kilo bits per sec = // (transmitted_byte_count * 8) / (time_duration)*(1000) *c2sspd = (8.0e-3 * bytes_read) / measured_test_duration; // As a kindness to old clients, drain their queues for a second or two. // TODO: Fix web100clt code to eliminate the need for this. In general, // clients that need this line should be removed from their respective // gene pools and this code should be deleted. drain_old_clients(c2s_conns, streamsNum, buff, sizeof(buff)); // c->s throuput value calculated and assigned ! Release resources, conclude // snap writing. if (options->snapshots) stop_snap_worker(&workerThreadId, options->snaplog, &snapArgs); // send the server calculated value of C->S throughput as result to client snprintf(buff, sizeof(buff), "%6.0f kbps outbound for child %d", *c2sspd, testOptions->child0); log_println(1, "%s", buff); snprintf(buff, sizeof(buff), "%0.0f", *c2sspd); if (extended && options->c2s_throughputsnaps && *c2s_ThroughputSnapshots != NULL) { struct throughputSnapshot *snapshotsPtr = *c2s_ThroughputSnapshots; while (snapshotsPtr != NULL) { int currBuffLength = strlen(buff); snprintf(&buff[currBuffLength], sizeof(buff)-currBuffLength, " %0.2f %0.2f", snapshotsPtr->time, snapshotsPtr->throughput); snapshotsPtr = snapshotsPtr->next; } } send_json_message_any(ctl, TEST_MSG, buff, strlen(buff), testOptions->connection_flags, JSON_SINGLE_VALUE); // get receiver side Web100 stats and write them to the log file. close // sockets if (record_reverse == 1) tcp_stat_get_data_recv(c2s_conns[0].socket, agent, conn, count_vars); close_all_connections(c2s_conns, streamsNum); close(testOptions->c2ssockfd); if (packet_trace_running) { log_println(1, "Signal USR1(%d) sent to child [%d]", SIGUSR1, c2s_childpid); testOptions->child1 = c2s_childpid; kill(c2s_childpid, SIGUSR1); i = 0; for (;;) { FD_ZERO(&rfd); FD_SET(mon_pipe[0], &rfd); sel_tv.tv_sec = 1; sel_tv.tv_usec = 100000; msgretvalue = select(mon_pipe[0] + 1, &rfd, NULL, NULL, &sel_tv); if (msgretvalue <= 0) { local_errno = (msgretvalue == -1) ? errno : 0; if (local_errno == EINTR) continue; // Either a timeout or an error that wasn't EINTR... log_println(4, "Failed to read pkt-pair data from C2S flow, " "retcode=%d, reason=%d", msgretvalue, local_errno); snprintf(spds[(*spd_index)++], sizeof(spds[*spd_index]), " -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0.0 0 0 0 0 0 -1"); snprintf(spds[(*spd_index)++], sizeof(spds[*spd_index]), " -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0.0 0 0 0 0 0 -1"); break; } else { /* There is something to read, so get it from the pktpair child. If an * interrupt occurs, just skip the read and go on * RAC 2/8/10 */ if ((msgretvalue = read(mon_pipe[0], spds[*spd_index], sizeof(spds[*spd_index]))) < 0) { snprintf( spds[*spd_index], sizeof(spds[*spd_index]), " -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 0.0 0 0 0 0 0 -1"); } log_println(1, "%d bytes read '%s' from C2S monitor pipe", msgretvalue, spds[*spd_index]); (*spd_index)++; if (i++ == 1) break; } } } // An empty TEST_FINALIZE message is sent to conclude the test send_json_message_any(ctl, TEST_FINALIZE, "", 0, testOptions->connection_flags, JSON_SINGLE_VALUE); // Close opened resources for packet capture if (packet_trace_running) { // TODO: Determine whether this shutdown can be performed in a non-blocking // manner, and if so then refactor packet_trace_emergency_shutdown to have // better error handling and use that refactored and renamed function here. stop_packet_trace(mon_pipe); packet_trace_running = 0; } // log end of C->S test log_println(1, " <----------- %d -------------->", testOptions->child0); // protocol logs teststatuses = TEST_ENDED; protolog_status(testOptions->child0, testids, teststatuses, ctl->socket); // set current test status and free address setCurrentTest(TEST_NONE); return 0; }
int test_s2c_clt(int ctlSocket, char tests, char* host, int conn_options, int buf_size, char* tmpstr) { char buff[BUFFSIZE+1]; int msgLen, msgType; int s2cport = 3003; I2Addr sec_addr = NULL; int inlth, ret, one=1, set_size; int inSocket; socklen_t optlen; uint32_t bytes; double t; struct timeval sel_tv; fd_set rfd; char* ptr; if (tests & TEST_S2C) { log_println(1, " <-- S2C throughput test -->"); msgLen = sizeof(buff); if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) { log_println(0, "Protocol error - missed prepare message!"); return 1; } if (check_msg_type("S2C throughput test", TEST_PREPARE, msgType, buff, msgLen)) { return 2; } if (msgLen <= 0) { log_println(0, "Improper message"); return 3; } buff[msgLen] = 0; if (check_int(buff, &s2cport)) { log_println(0, "Invalid port number"); return 4; } log_println(1, " -- port: %d", s2cport); /* Cygwin seems to want/need this extra getsockopt() function * call. It certainly doesn't do anything, but the S2C test fails * at the connect() call if it's not there. 4/14/05 RAC */ optlen = sizeof(set_size); getsockopt(ctlSocket, SOL_SOCKET, SO_SNDBUF, &set_size, &optlen); if ((sec_addr = I2AddrByNode(get_errhandle(), host)) == NULL) { log_println(0, "Unable to resolve server address: %s", strerror(errno)); return -3; } I2AddrSetPort(sec_addr, s2cport); if ((ret = CreateConnectSocket(&inSocket, NULL, sec_addr, conn_options, buf_size))) { log_println(0, "Connect() for Server to Client failed", strerror(errno)); return -15; } setsockopt(inSocket, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); /* Linux updates the sel_tv time values everytime select returns. This * means that eventually the timer will reach 0 seconds and select will * exit with a timeout signal. Other OS's don't do that so they need * another method for detecting a long-running process. The check below * will cause the loop to terminate if select says there is something * to read and the loop has been active for over 14 seconds. This usually * happens when there is a problem (duplex mismatch) and there is data * queued up on the server. */ msgLen = sizeof(buff); if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) { log_println(0, "Protocol error - missed start message!"); return 1; } if (check_msg_type("S2C throughput test", TEST_START, msgType, buff, msgLen)) { return 2; } printf("running 10s inbound test (server to client) . . . . . . "); fflush(stdout); bytes = 0; t = secs() + 15.0; sel_tv.tv_sec = 15; sel_tv.tv_usec = 5; FD_ZERO(&rfd); FD_SET(inSocket, &rfd); for (;;) { ret = select(inSocket+1, &rfd, NULL, NULL, &sel_tv); if (secs() > t) { log_println(5, "Receive test running long, break out of read loop"); break; } if (ret > 0) { inlth = read(inSocket, buff, sizeof(buff)); if (inlth == 0) break; bytes += inlth; continue; } if (get_debuglvl() > 5) { log_println(0, "s2c read loop exiting:", strerror(errno)); } break; } t = secs() - t + 15.0; spdin = ((8.0 * bytes) / 1000) / t; /* receive the s2cspd from the server */ msgLen = sizeof(buff); if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) { log_println(0, "Protocol error - missed text message!"); return 1; } if (check_msg_type("S2C throughput test", TEST_MSG, msgType, buff, msgLen)) { return 2; } if (msgLen <= 0) { log_println(0, "Improper message"); return 3; } buff[msgLen] = 0; ptr = strtok(buff, " "); if (ptr == NULL) { log_println(0, "S2C: Improper message"); return 4; } s2cspd = atoi(ptr); ptr = strtok(NULL, " "); if (ptr == NULL) { log_println(0, "S2C: Improper message"); return 4; } ssndqueue = atoi(ptr); ptr = strtok(NULL, " "); if (ptr == NULL) { log_println(0, "S2C: Improper message"); return 4; } sbytes = atoi(ptr); if (spdin < 1000) printf("%0.2f kb/s\n", spdin); else printf("%0.2f Mb/s\n", spdin/1000); I2AddrFree(sec_addr); sprintf(buff, "%0.0f", spdin); send_msg(ctlSocket, TEST_MSG, buff, strlen(buff)); /* get web100 variables from server */ tmpstr[0] = '\0'; for (;;) { msgLen = sizeof(buff); if (recv_msg(ctlSocket, &msgType, buff, &msgLen)) { log_println(0, "Protocol error - missed text/finalize message!"); return 1; } if (msgType == TEST_FINALIZE) { break; } if (check_msg_type("S2C throughput test", TEST_MSG, msgType, buff, msgLen)) { return 2; } strncat(tmpstr, buff, msgLen); log_println(6, "tmpstr = '%s'", tmpstr); } log_println(1, " <------------------------->"); } return 0; }
// ------------------------------------------------------------------------ // CDRMConsume:: ActivateL // // Calculate the smallest end time based on interval, end time, // accumulated time & timed count. // ------------------------------------------------------------------------ // void CDRMConsume::ActivateL( TBool aSecureTime, const TTime& aTrustedTime ) { DRMLOG( _L( "CDRMConsume::ActivateL" ) ); __ASSERT_DEBUG( iChild && iCombined, User::Invariant() ); TTime endTime( Time::MaxTTime() ); TTimeIntervalSeconds timed( KMaxTInt32 ); TBool timeUsed( EFalse ); TBool endTimeUsed( EFalse ); iCurrentDelay = 0; if ( iCombined->iActiveConstraints & EConstraintTimedCounter ) { // Take this, even if timed counts have been updated. // This might cause unnecessary RunL's to be called, but it // ensures both child & parent will be consumed when needed. // If e.g. it would be checked that iTimedCounts == 0xf, // either one (child or parent) might not get updated in case of // "Child expired, but parent didn't -> find new child". PickSmaller( timed, iCombined->iTimedInterval ); timeUsed = ETrue; } if ( iCombined->iActiveConstraints & EConstraintAccumulated ) { PickSmaller( timed, iCombined->iAccumulatedTime ); timeUsed = ETrue; } if ( iCombined->iActiveConstraints & EConstraintInterval ) { if ( iCombined->iIntervalStart != Time::NullTTime() ) { endTime = iCombined->iIntervalStart; endTime += iCombined->iInterval; endTimeUsed = ETrue; } else { TInt64 tmp( iCombined->iInterval.Int() ); PickSmaller( timed, tmp ); timeUsed = ETrue; } } if ( iCombined->iActiveConstraints & EConstraintEndTime ) { PickSmaller( endTime, iCombined->iEndTime ); endTimeUsed = ETrue; } // Put the "smallest time" information to "endTime". if ( timeUsed ) { TTime current( aTrustedTime ); current += timed; PickSmaller( endTime, current ); endTimeUsed = ETrue; } // Interval gets initialised immediately, and so do count constraints. // Timed/accumulated won't: those are consumed after the // interval if secure time exists. Consume( ETrue, ETrue, EFalse, 0, aSecureTime, aTrustedTime ); // In case something was modified, update the db also. UpdateDBL(); if ( endTimeUsed ) { // Something exists. TTimeIntervalSeconds secs( 0 ); TTime current( aTrustedTime ); TInt err( KErrNone ); // SecondsFrom returns an error if the difference is too great. err = endTime.SecondsFrom( current, secs ); if ( err ) { iCurrentDelay = KConsumeDefaultTimer; } else if ( secs.Int() < 0 ) { iCurrentDelay = 0; // Already expired. } else if ( secs.Int() < KConsumeDefaultTimer ) { iCurrentDelay = secs.Int(); } else { iCurrentDelay = KConsumeDefaultTimer; } if ( !IsAdded() ) { CActiveScheduler::Add( this ); } DRMLOG2( _L( "CDRMConsume::ActivateL: using interval %d" ), ( TInt )iCurrentDelay ); // secs -> microsecs. The method sets the AO active. After( TTimeIntervalMicroSeconds32( iCurrentDelay * 1000000 ) ); iTime = current; // If we see timed things here, we also have secure time. //SETBIT( iMask, KConsumeHasSecureTime ); } else // For metering we always need to have this: { iCurrentDelay = KConsumeDefaultTimer; iTime = aTrustedTime; if ( !IsAdded() ) { CActiveScheduler::Add( this ); } DRMLOG2( _L( "CDRMConsume::ActivateL: using interval %d" ), ( TInt )iCurrentDelay ); // secs -> microsecs. The method sets the AO active. After( TTimeIntervalMicroSeconds32( iCurrentDelay * 1000000 ) ); } // If we see timed things here, we also have secure time. if( aTrustedTime != Time::NullTTime()) { SETBIT( iMask, KConsumeHasSecureTime ); } DRMLOG( _L( "CDRMConsume::ActivateL ok" ) ); }
namespace antares { static const int kCursorBoundsSize = 16; static const usecs kTimeout = secs(1); Cursor::Cursor(): _sprite(500, GRAY) { } void Cursor::draw() const { draw_at(sys.video->get_mouse()); } void Cursor::draw_at(Point where) const { if (world().contains(where)) { where.offset(-_sprite.at(0).center().h, -_sprite.at(0).center().v); _sprite.at(0).texture().draw(where.h, where.v); } } GameCursor::GameCursor(): show(true), _show_crosshairs_until(now() + kTimeout) { } bool GameCursor::active() const { return show && (_show_crosshairs_until > now()); } Point GameCursor::clamped_location() { return clamp(sys.video->get_mouse()); } Point GameCursor::clamp(Point p) { // Do the cursor, too, unless this is a replay. if (p.h > (viewport().right - kCursorBoundsSize - 1)) { p.h = viewport().right - kCursorBoundsSize - 1; } if (p.v < (viewport().top + kCursorBoundsSize)) { p.v = viewport().top + kCursorBoundsSize; } else if (p.v > (play_screen().bottom - kCursorBoundsSize - 1)) { p.v = play_screen().bottom - kCursorBoundsSize - 1; } return p; } void GameCursor::mouse_down(const MouseDownEvent& event) { if (event.where().h >= viewport().left) { wake(); } } void GameCursor::mouse_up(const MouseUpEvent& event) { if (event.where().h >= viewport().left) { wake(); } } void GameCursor::mouse_move(const MouseMoveEvent& event) { if (event.where().h >= viewport().left) { wake(); } } void GameCursor::wake() { _show_crosshairs_until = now() + kTimeout; } ANTARES_GLOBAL bool HintLine::show_hint_line = false; ANTARES_GLOBAL Point HintLine::hint_line_start; ANTARES_GLOBAL Point HintLine::hint_line_end; ANTARES_GLOBAL RgbColor HintLine::hint_line_color; ANTARES_GLOBAL RgbColor HintLine::hint_line_color_dark; void HintLine::show(Point fromWhere, Point toWhere, uint8_t color, uint8_t brightness) { hint_line_start = fromWhere; hint_line_end = toWhere; show_hint_line = true; hint_line_color = GetRGBTranslateColorShade(color, brightness); hint_line_color_dark = GetRGBTranslateColorShade(color, VERY_DARK); } void HintLine::hide() { show_hint_line = false; } void HintLine::reset() { show_hint_line = false; hint_line_start.h = hint_line_start.v = -1; hint_line_end.h = hint_line_end.v = -1; hint_line_color = hint_line_color_dark = RgbColor::black(); } void GameCursor::draw() const { if (!show) { return; } Point where = sys.video->get_mouse(); where = clamp(where); if (active()) { const Rect clip_rect = viewport(); const RgbColor color = GetRGBTranslateColorShade(SKY_BLUE, MEDIUM); Point top_a = Point(where.h, clip_rect.top); Point top_b = Point(where.h, (where.v - kCursorBoundsSize)); Point bottom_a = Point(where.h, (where.v + kCursorBoundsSize)); Point bottom_b = Point(where.h, clip_rect.bottom - 1); Point left_a = Point(clip_rect.left, where.v); Point left_b = Point((where.h - kCursorBoundsSize), where.v); Point right_a = Point(std::max(viewport().left, where.h + kCursorBoundsSize), where.v); Point right_b = Point(clip_rect.right - 1, where.v); Rects rects; if (top_a.h >= viewport().left) { rects.fill({top_a.h, top_a.v, top_b.h + 1, top_b.v + 1}, color); rects.fill({bottom_a.h, bottom_a.v, bottom_b.h + 1, bottom_b.v + 1}, color); } rects.fill({right_a.h, right_a.v, right_b.h + 1, right_b.v + 1}, color); if (left_b.h >= viewport().left) { rects.fill({left_a.h, left_a.v, left_b.h + 1, left_b.v + 1}, color); } } if (where.h < viewport().left) { draw_at(where); } } void HintLine::draw() { if (show_hint_line) { Lines lines; Point start = hint_line_start; Point end = hint_line_end; start.offset(0, 2); end.offset(0, 2); lines.draw(start, end, hint_line_color_dark); start.offset(0, -1); end.offset(0, -1); lines.draw(start, end, hint_line_color); start.offset(0, -1); end.offset(0, -1); lines.draw(start, end, hint_line_color); } } } // namespace antares
void RunKMedoids(const leveldb::Slice& begin, const leveldb::Slice& end, int K, leveldb::DB* db, leveldb::DB* work_db, int concurrency, std::ostream& ivar_out, std::ostream& cent_out) { auto very_start = std::chrono::system_clock::now(); auto key_centroids = uniform_init(begin, end, K); std::vector<GDELTMini> val_centroids(K); { auto it = iter(db); for (int i = 0; i < K; ++i) { it->Seek(key_centroids[i]); CHECK(it->Valid()); read(it->value(), val_centroids[i]); } } std::cout << "Divying up range among threads... " << std::flush; auto parvec = get_par_ranges(uniform_init(begin, end, concurrency), db, end); std::cout << "DONE" << std::endl; int i = 0; bool centers_changed = true; vuad totals(K); vuai cluster_sizes(K); for (int i = 0; i < K; ++i) { cluster_sizes[i].reset(new std::atomic<int>); totals[i].reset(new std::atomic<double>); } while (centers_changed) { auto start = std::chrono::system_clock::now(); assign_closest(parvec, totals, K, work_db, val_centroids, concurrency, cluster_sizes); auto tot = std::accumulate(totals.begin(), totals.end(), 0.0, [](double sum, typename vuad::value_type& d) { return sum + d->load(); }); auto end = std::chrono::system_clock::now(); std::cout << "Iteration " << ++i << " total intravariance " << tot; std::cout << "\n Assigning medoids took " << secs(start, end) << "s" << std::endl; start = std::chrono::system_clock::now(); for (auto& d : totals) { ivar_out << d->load() << " "; } ivar_out << std::endl; cent_out << key_centroids << std::endl; end = std::chrono::system_clock::now(); std::cout << " Saving medoids took " << secs(start, end) << " s" << std::endl; start = std::chrono::system_clock::now(); centers_changed = update_medoids(concurrency, K, db, work_db, val_centroids, key_centroids, totals, cluster_sizes); end = std::chrono::system_clock::now(); std::cout << " Medoid update took " << secs(start, end) << " s" << std::endl; start = end; } auto very_end = std::chrono::system_clock::now(); std::cout << "K-medoid clustering COMPLETE in " << secs(very_start, very_end) << " s" << std::endl; }