Beispiel #1
0
static char *vacuum1_thread_writer(int iTid, void *pArg){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  opendb(&err, &db, "test.db", 0);
  i64 i = 0;

  while( !timetostop(&err) ){
    i++;

    /* Insert lots of rows. Then delete some. */
    execsql(&err, &db, 
        "WITH loop(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM loop WHERE i<100) "
        "INSERT INTO t1 SELECT randomblob(50), randomblob(2500) FROM loop"
    );

    /* Delete lots of rows */
    execsql(&err, &db, "DELETE FROM t1 WHERE rowid = :i", &i);
    clear_error(&err, SQLITE_LOCKED);

    /* Select the rows */
    execsql(&err, &db, "SELECT * FROM t1 ORDER BY x");
    clear_error(&err, SQLITE_LOCKED);
  }

  closedb(&err, &db);
  print_and_free_err(&err);
  return sqlite3_mprintf("ok");
}
Beispiel #2
0
frmBoxes::~frmBoxes()
{
    try
    {
        closeimgdb();
        closedb();
    }
    catch(...){}
    delete ui;
}
Beispiel #3
0
// Checks cache consistency
void LdbCache::check(bool force)
{
	try {
		if (!m_db) opendb();
	} catch (const std::exception &ex) {
		PDEBUG << "Exception while opening database: " << ex.what() << endl;
		Logger::info() << "LdbCache: Database can't be opened, trying to repair it" << endl;
	}

	if (force || !m_db) {
		std::string path = cacheDir() + "/ldb";
		leveldb::Status status = leveldb::RepairDB(path, leveldb::Options());
		if (!status.ok()) {
			Logger::err() << "Error repairing database: " << status.ToString() << endl;
		} else {
			Logger::info() << "LdbCache: Database repaired" << endl;
		}
		closedb();
		opendb();
	}

	// Simply try to read all revisions
	Logger::info() << "LdbCache: Checking revisions..." << endl;
	std::vector<std::string> corrupted;
	size_t n = 0;
	leveldb::Iterator* it = m_db->NewIterator(leveldb::ReadOptions());
	for (it->SeekToFirst(); it->Valid(); it->Next()) {
		Revision rev(it->key().ToString());
		std::string value = it->value().ToString();
		MIStream rin(value.c_str(), value.length());
		if (!rev.load(rin)) {
			PDEBUG << "Revision " << it->key().ToString() << " corrupted!" << endl;
			corrupted.push_back(it->key().ToString());
		}
		++n;
	}
	if (!it->status().ok()) {
		Logger::err() << "Error iterating over cached revisions: " << it->status().ToString() << endl;
		Logger::err() << "Please re-run with --force to repair the database (might cause data loss)" << endl;
		return;
	}
	Logger::info() << "LdbCache: Checked " << n << " revisions, found " << corrupted.size() << " to be corrupted" << endl;

	for (size_t i = 0; i < corrupted.size(); i++) {
		Logger::err() << "LdbCache: Revision " << corrupted[i] << " is corrupted, removing from index file" << endl;
		leveldb::Status status = m_db->Delete(leveldb::WriteOptions(), corrupted[i]);
		if (!status.ok()) {
			Logger::err() << "Error: Can't remove from revision " << corrupted[i] << " from database: " << status.ToString() << endl;
			return;
		}
	}
}
Beispiel #4
0
static char *vacuum1_thread_vacuumer(int iTid, void *pArg){
  Error err = {0};                /* Error code and message */
  Sqlite db = {0};                /* SQLite database connection */
  opendb(&err, &db, "test.db", 0);

  do{
    sql_script(&err, &db, "VACUUM");
    clear_error(&err, SQLITE_LOCKED);
  }while( !timetostop(&err) );

  closedb(&err, &db);
  print_and_free_err(&err);
  return sqlite3_mprintf("ok");
}
Beispiel #5
0
static char *checkpoint_starvation_reader(int iTid, void *pArg){
  Error err = {0};
  Sqlite db = {0};

  opendb(&err, &db, "test.db", 0);
  while( !timetostop(&err) ){
    i64 iCount1, iCount2;
    sql_script(&err, &db, "BEGIN");
    iCount1 = execsql_i64(&err, &db, "SELECT count(x) FROM t1");
    usleep(CHECKPOINT_STARVATION_READMS*1000);
    iCount2 = execsql_i64(&err, &db, "SELECT count(x) FROM t1");
    sql_script(&err, &db, "COMMIT");

    if( iCount1!=iCount2 ){
      test_error(&err, "Isolation failure - %lld %lld", iCount1, iCount2);
    }
  }
  closedb(&err, &db);

  print_and_free_err(&err);
  return 0;
}
Beispiel #6
0
static void checkpoint_starvation_main(int nMs, CheckpointStarvationCtx *p){
  Error err = {0};
  Sqlite db = {0};
  Threadset threads = {0};
  int nInsert = 0;
  int i;

  opendb(&err, &db, "test.db", 1);
  sql_script(&err, &db, 
      "PRAGMA page_size = 1024;"
      "PRAGMA journal_mode = WAL;"
      "CREATE TABLE t1(x);"
  );

  setstoptime(&err, nMs);

  for(i=0; i<4; i++){
    launch_thread(&err, &threads, checkpoint_starvation_reader, 0);
    usleep(CHECKPOINT_STARVATION_READMS*1000/4);
  }

  sqlite3_wal_hook(db.db, checkpoint_starvation_walhook, (void *)p);
  while( !timetostop(&err) ){
    sql_script(&err, &db, "INSERT INTO t1 VALUES(randomblob(1200))");
    nInsert++;
  }

  printf(" Checkpoint mode  : %s\n",
      p->eMode==SQLITE_CHECKPOINT_PASSIVE ? "PASSIVE" : "RESTART"
  );
  printf(" Peak WAL         : %d frames\n", p->nMaxFrame);
  printf(" Transaction count: %d transactions\n", nInsert);

  join_all_threads(&err, &threads);
  closedb(&err, &db);
  print_and_free_err(&err);
}
Beispiel #7
0
static void vacuum1(int nMs){
  Error err = {0};
  Sqlite db = {0};
  Threadset threads = {0};

  opendb(&err, &db, "test.db", 1);
  sql_script(&err, &db, 
     "CREATE TABLE t1(x PRIMARY KEY, y BLOB);"
     "CREATE INDEX i1 ON t1(y);"
  );
  closedb(&err, &db);

  setstoptime(&err, nMs);

  sqlite3_enable_shared_cache(1);
  launch_thread(&err, &threads, vacuum1_thread_writer, 0);
  launch_thread(&err, &threads, vacuum1_thread_writer, 0);
  launch_thread(&err, &threads, vacuum1_thread_writer, 0);
  launch_thread(&err, &threads, vacuum1_thread_vacuumer, 0);
  join_all_threads(&err, &threads);
  sqlite3_enable_shared_cache(0);

  print_and_free_err(&err);
}
int main(int argc, char** argv) {
	/// Serial port full path to open
	char *serialport = NULL;

	/// Database file to open
	char *databasename = NULL;

	/// List of columsn to log
	char *log_columns = NULL;

	/// Number of samples to take
	int samplecount = -1;

	/// Number of samples per second
	int samplespersecond = 1;

	/// Ask to show the capabilities of the OBD device then exit
	int showcapabilities = 0;

	/// Set if the user wishes to upgrade the baudrate
	long baudrate_upgrade = -1;

	/// Time between samples, measured in microseconds
	long frametime = 0;

	/// Spam all readings to stdout
	int spam_stdout = 0;

	/// Enable elm optimisations
	int enable_optimisations = 0;

	/// Enable serial logging
	int enable_seriallog = 0;

	/// Serial log filename
	char *seriallogname = NULL;

#ifdef OBDPLATFORM_POSIX
	/// Daemonise
	int daemonise = 0;
#endif //OBDPLATFORM_POSIX

	/// Requested baudrate
	long requested_baud = -1;

	// Config File
	struct OBDGPSConfig *obd_config = obd_loadConfig(0);

	if(NULL != obd_config) {
		samplespersecond = obd_config->samplerate;
		enable_optimisations = obd_config->optimisations;
		requested_baud = obd_config->baudrate;
		baudrate_upgrade = obd_config->baudrate_upgrade;
	}

	// Do not attempt to buffer stdout at all
	setvbuf(stdout, (char *)NULL, _IONBF, 0);

	int optc;
	int mustexit = 0;
	while ((optc = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1) {
		switch (optc) {
			case 'h':
				printhelp(argv[0]);
				mustexit = 1;
				break;
			case 'v':
				printversion();
				mustexit = 1;
				break;
			case 's':
				if(NULL != serialport) {
					free(serialport);
				}
				serialport = strdup(optarg);
				break;
			case 'o':
				enable_optimisations = 1;
				break;
			case 't':
				spam_stdout = 1;
				break;
			case 'u':
				{
					int newout = open(optarg, O_CREAT|O_RDWR|O_APPEND,
						S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
					if(-1 == newout) {
						perror(optarg);
					} else {
						printf("Redirecting output to %s\n", optarg);
						close(STDOUT_FILENO);
						close(STDERR_FILENO);
						dup2(newout, STDOUT_FILENO);
						dup2(newout, STDERR_FILENO);
					}
				}
				break;
#ifdef OBDPLATFORM_POSIX
			case 'm':
				daemonise = 1;
				break;
#endif //OBDPLATFORM_POSIX
			case 'c':
				samplecount = atoi(optarg);
				break;
			case 'b':
				requested_baud = strtol(optarg, (char **)NULL, 10);
				break;
			case 'B':
				baudrate_upgrade = strtol(optarg, (char **)NULL, 10);
				break;
			case 'd':
				if(NULL != databasename) {
					free(databasename);
				}
				databasename = strdup(optarg);
				break;
			case 'i':
				if(NULL != log_columns) {
					free(log_columns);
				}
				log_columns = strdup(optarg);
				break;
			case 'a':
				samplespersecond = atoi(optarg);
				break;
			case 'l':
				enable_seriallog = 1;
				if(NULL != seriallogname) {
					free(seriallogname);
				}
				seriallogname = strdup(optarg);
				break;
			case 'p':
				showcapabilities = 1;
				break;
			default:
				mustexit = 1;
				break;
		}
	}

	if(mustexit) exit(0);

	if(0 >= samplespersecond) {
		frametime = 0;
	} else {
		frametime = 1000000 / samplespersecond;
	}

	if(NULL == serialport) {
		if(NULL != obd_config && NULL != obd_config->obd_device) {
			serialport = strdup(obd_config->obd_device);
		} else {
			serialport = strdup(OBD_DEFAULT_SERIALPORT);
		}
	}
	if(NULL == databasename) {
		if(NULL != obd_config && NULL != obd_config->log_file) {
			databasename = strdup(obd_config->log_file);
		} else {
			databasename = strdup(OBD_DEFAULT_DATABASE);
		}
	}
	if(NULL == log_columns) {
		if(NULL != obd_config && NULL != obd_config->log_columns) {
			log_columns = strdup(obd_config->log_columns);
		} else {
			log_columns = strdup(OBD_DEFAULT_COLUMNS);
		}
	}


	if(enable_seriallog && NULL != seriallogname) {
		startseriallog(seriallogname);
	}


	// Open the serial port.
	int obd_serial_port = openserial(serialport, requested_baud, baudrate_upgrade);

	if(-1 == obd_serial_port) {
		fprintf(stderr, "Couldn't open obd serial port. Attempting to continue.\n");
	} else {
		fprintf(stderr, "Successfully connected to serial port. Will log obd data\n");
	}

	// Just figure out our car's OBD port capabilities and print them
	if(showcapabilities) {
		printobdcapabilities(obd_serial_port);
		
		printf("\n");

/*
		unsigned int retvals[50];
		int vals_returned;
		getobderrorcodes(obd_serial_port,
        		retvals, sizeof(retvals)/sizeof(retvals[0]), &vals_returned);

		int q = 0;
		int c = retvals[0];
		for(q=1;q<1+2*c && q+1<vals_returned;q+=2) {
			printf("Error: %s\n", obderrconvert(retvals[q], retvals[q+1]));
		}

*/

		closeserial(obd_serial_port);
		exit(0);
	}


#ifdef HAVE_GPSD
	// Open the gps device
	struct gps_data_t *gpsdata;
	gpsdata = opengps(GPSD_ADDR, GPSD_PORT);

	if(NULL == gpsdata) {
		fprintf(stderr, "Couldn't open gps port on startup.\n");
	} else {
		fprintf(stderr, "Successfully connected to gpsd. Will log gps data\n");
	}

#endif //HAVE_GPSD

	if(-1 == obd_serial_port
#ifdef HAVE_GPSD
		&& NULL == gpsdata
#endif //HAVE_GPSD
	) {
		fprintf(stderr, "Couldn't find either gps or obd to log. Exiting.\n");
		exit(1);
	}

#ifdef HAVE_DBUS
	obdinitialisedbus();
#endif //HAVE_DBUS

	// sqlite database
	sqlite3 *db;

	// sqlite statement
	sqlite3_stmt *obdinsert;

	// number of columns in the insert
	int obdnumcols;

	// sqlite return status
	int rc;

	// Open the database and create the obd table
	if(NULL == (db = opendb(databasename))) {
		closeserial(obd_serial_port);
		exit(1);
	}

	// Disable sqlite's synchronous pragma.
	/* char *zErrMsg;
	rc = sqlite3_exec(db, "PRAGMA synchronous=OFF",
					NULL, NULL, &zErrMsg);
	if(rc != SQLITE_OK) {
		printf("SQLite error %i: %s\n", rc, zErrMsg);
		sqlite3_free(zErrMsg);
	} */

	// Wishlist of commands from config file
	struct obdservicecmd **wishlist_cmds = NULL;
	obd_configCmds(log_columns, &wishlist_cmds);

	void *obdcaps = getobdcapabilities(obd_serial_port,wishlist_cmds);

	obd_freeConfigCmds(wishlist_cmds);
	wishlist_cmds=NULL;

	createobdtable(db,obdcaps);

	// Create the insert statement. On success, we'll have the number of columns
	if(0 == (obdnumcols = createobdinsertstmt(db,&obdinsert, obdcaps)) || NULL == obdinsert) {
		closedb(db);
		closeserial(obd_serial_port);
		exit(1);
	}

	createtriptable(db);

	createecutable(db);

	// All of these have obdnumcols-1 since the last column is time
	int cmdlist[obdnumcols-1]; // Commands to send [index into obdcmds_mode1]

	int i,j;
	for(i=0,j=0; i<sizeof(obdcmds_mode1)/sizeof(obdcmds_mode1[0]); i++) {
		if(NULL != obdcmds_mode1[i].db_column) {
			if(isobdcapabilitysupported(obdcaps,i)) {
				cmdlist[j] = i;
				j++;
			}
		}
	}

	freeobdcapabilities(obdcaps);
	// We create the gps table even if gps is disabled, so that other
	//  SQL commands expecting the table to at least exist will work.

	// sqlite statement
	sqlite3_stmt *gpsinsert;

	// number of columns in the insert
	int gpsnumcols;

	creategpstable(db);

	if(0 == (gpsnumcols = creategpsinsertstmt(db, &gpsinsert) || NULL == gpsinsert)) {
		closedb(db);
		closeserial(obd_serial_port);
		exit(1);
	}

#ifdef OBDPLATFORM_POSIX
	if(daemonise) {
		if(0 != obddaemonise()) {
			fprintf(stderr,"Couldn't daemonise, exiting\n");
			closeserial(obd_serial_port);
			exit(1);
		}
	}
#endif //OBDPLATFORM_POSIX

#ifdef HAVE_GPSD
	// Ping a message to stdout the first time we get
	//   enough of a satellite lock to begin logging
	int have_gps_lock = 0;
#endif //HAVE_GPSD


	install_signalhandlers();


	// The current thing returned by starttrip
	sqlite3_int64 currenttrip = 0;

	// Set when we're actually inside a trip
	int ontrip = 0;

	// The current time we're inserting
	double time_insert;

	// The last time we tried to check the gps daemon
	double time_lastgpscheck = 0;

	// Number of samples per transaction
	const int basetransactioncount = TRANSACTIONTIME * (0==samplespersecond?10:samplespersecond);

	// Store a few seconds worth of samples per transaction
	int transactioncount = 0;

	obdbegintransaction(db);

	while(samplecount == -1 || samplecount-- > 0) {

		struct timeval starttime; // start time through loop
		struct timeval endtime; // end time through loop
		struct timeval selecttime; // =endtime-starttime [for select()]

		if(0 != gettimeofday(&starttime,NULL)) {
			perror("Couldn't gettimeofday");
			break;
		}

#ifdef HAVE_DBUS
		enum obd_dbus_message msg_ret;
		while(OBD_DBUS_NOMESSAGE != (msg_ret = obdhandledbusmessages())) {
			switch(msg_ret) {
				case OBD_DBUS_STARTTRIP:
					if(!ontrip) {
						currenttrip = starttrip(db, time_insert);
						fprintf(stderr,"Created a new trip (%i)\n", (int)currenttrip);
						ontrip = 1;
					}
					break;
				case OBD_DBUS_NOMESSAGE:
				default:
					break;
			}
		}
#endif //HAVE_DBUS

		time_insert = (double)starttime.tv_sec+(double)starttime.tv_usec/1000000.0f;

		if(sig_starttrip) {
			if(ontrip) {
				fprintf(stderr,"Ending current trip\n");
				updatetrip(db, currenttrip, time_insert);
				ontrip = 0;
			}
			currenttrip = starttrip(db, time_insert);
			fprintf(stderr,"Created a new trip (%i)\n", (int)currenttrip);
			ontrip = 1;
			sig_starttrip = 0;
		}

		enum obd_serial_status obdstatus;
		if(-1 < obd_serial_port) {

			// Get all the OBD data
			for(i=0; i<obdnumcols-1; i++) {
				float val;
				unsigned int cmdid = obdcmds_mode1[cmdlist[i]].cmdid;
				int numbytes = enable_optimisations?obdcmds_mode1[cmdlist[i]].bytes_returned:0;
				OBDConvFunc conv = obdcmds_mode1[cmdlist[i]].conv;

				obdstatus = getobdvalue(obd_serial_port, cmdid, &val, numbytes, conv);
				if(OBD_SUCCESS == obdstatus) {
#ifdef HAVE_DBUS
					obddbussignalpid(&obdcmds_mode1[cmdlist[i]], val);
#endif //HAVE_DBUS
					if(spam_stdout) {
						printf("%s=%f\n", obdcmds_mode1[cmdlist[i]].db_column, val);
					}
					sqlite3_bind_double(obdinsert, i+1, (double)val);
					// printf("cmd: %02X, val: %f\n",obdcmds_mode1[cmdlist[i]].cmdid,val);
				} else {
					break;
				}
			}

			if(obdstatus == OBD_SUCCESS) {
				// If they're not on a trip but the engine is going, start a trip
				if(0 == ontrip) {
					printf("Creating a new trip\n");
					currenttrip = starttrip(db, time_insert);
					ontrip = 1;
				}
				sqlite3_bind_double(obdinsert, i+1, time_insert);
				sqlite3_bind_int64(obdinsert, i+2, currenttrip);

				// Do the OBD insert
				rc = sqlite3_step(obdinsert);
				if(SQLITE_DONE != rc) {
					printf("sqlite3 obd insert failed(%i): %s\n", rc, sqlite3_errmsg(db));
				}
			} else if(OBD_ERROR == obdstatus) {
				fprintf(stderr, "Received OBD_ERROR from serial read. Exiting\n");
				receive_exitsignal = 1;
			} else {
				// If they're on a trip, and the engine has desisted, stop the trip
				if(ontrip) {
					printf("Ending current trip\n");
					updatetrip(db, currenttrip, time_insert);
					ontrip = 0;
				}
			}
			sqlite3_reset(obdinsert);
		}

		// Constantly update the trip
		updatetrip(db, currenttrip, time_insert);

#ifdef HAVE_GPSD
		// Get the GPS data
		double lat,lon,alt,speed,course,gpstime;

		int gpsstatus = -1;
		if(NULL != gpsdata) {
			gpsstatus = getgpsposition(gpsdata, &lat, &lon, &alt, &speed, &course, &gpstime);
		} else {
			if(time_insert - time_lastgpscheck > 10) { // Try again once in a while
				gpsdata = opengps(GPSD_ADDR, GPSD_PORT);
				if(NULL != gpsdata) {
					printf("Delayed connection to gps achieved\n");
				} else {
					// fprintf(stderr, "Delayed connection to gps failed\n");
				}
				time_lastgpscheck = time_insert;
			}
		}
		if(gpsstatus < 0 || NULL == gpsdata) {
			// Nothing yet
		} else if(gpsstatus >= 0) {
			if(0 == have_gps_lock) {
				fprintf(stderr,"GPS acquisition complete\n");
				have_gps_lock = 1;
			}

			sqlite3_bind_double(gpsinsert, 1, lat);
			sqlite3_bind_double(gpsinsert, 2, lon);
			if(gpsstatus >= 1) {
				sqlite3_bind_double(gpsinsert, 3, alt);
			} else {
				sqlite3_bind_null(gpsinsert, 3);
			}
			sqlite3_bind_double(gpsinsert, 4, speed);
			sqlite3_bind_double(gpsinsert, 5, course);
			sqlite3_bind_double(gpsinsert, 6, gpstime);

			if(spam_stdout) {
				printf("gpspos=%f,%f,%f,%f,%f\n",
					lat, lon, (gpsstatus>=1?alt:-1000.0), speed, course);
			}

			// Use time worked out before.
			//  This makes table joins reliable, but the time itself may be wrong depending on gpsd lagginess
			sqlite3_bind_double(gpsinsert, 7, time_insert);

			sqlite3_bind_int64(gpsinsert, 8, currenttrip);

			// Do the GPS insert
			rc = sqlite3_step(gpsinsert);
			if(SQLITE_DONE != rc) {
				printf("sqlite3 gps insert failed(%i): %s\n", rc, sqlite3_errmsg(db));
			}
			sqlite3_reset(gpsinsert);
		}
#endif //HAVE_GPSD

		if(0 != gettimeofday(&endtime,NULL)) {
			perror("Couldn't gettimeofday");
			break;
		}

		// Set via the signal handler
		if(receive_exitsignal) {
			break;
		}


		// Commit this if we've done more than a certain number
		transactioncount++;
		transactioncount%=basetransactioncount;
		if(0 == transactioncount) {
			obdcommittransaction(db);
			obdbegintransaction(db);
		}

		
		// usleep() not as portable as select()

		if(0 < frametime) {
			selecttime.tv_sec = endtime.tv_sec - starttime.tv_sec;
			if (selecttime.tv_sec != 0) {
					endtime.tv_usec += 1000000*selecttime.tv_sec;
					selecttime.tv_sec = 0;
			}
			selecttime.tv_usec = (frametime) - 
					(endtime.tv_usec - starttime.tv_usec);
			if(selecttime.tv_usec < 0) {
					selecttime.tv_usec = 1;
			}
			select(0,NULL,NULL,NULL,&selecttime);
		}
	}

	obdcommittransaction(db);

	if(0 != ontrip) {
		updatetrip(db, currenttrip, time_insert);
		ontrip = 0;
	}

	sqlite3_finalize(obdinsert);
	sqlite3_finalize(gpsinsert);

	closeserial(obd_serial_port);
#ifdef HAVE_GPSD
	if(NULL != gpsdata) {
		gps_close(gpsdata);
	}
#endif //HAVE_GPSD
	closedb(db);

	if(enable_seriallog) {
		closeseriallog();
	}

	if(NULL != log_columns) free(log_columns);
	if(NULL != databasename) free(databasename);
	if(NULL != serialport) free(serialport);

	obd_freeConfig(obd_config);
	return 0;
}
Beispiel #9
0
// Destructor
LdbCache::~LdbCache()
{
	closedb();
}