[darwinbuild-changes] [705] branches/PR-7489777/darwinup

source_changes at macosforge.org source_changes at macosforge.org
Thu Feb 18 13:34:36 PST 2010


Revision: 705
          http://trac.macosforge.org/projects/darwinbuild/changeset/705
Author:   wsiegrist at apple.com
Date:     2010-02-18 13:34:36 -0800 (Thu, 18 Feb 2010)
Log Message:
-----------
Some support for reading rows and columns

Modified Paths:
--------------
    branches/PR-7489777/darwinup/Column.cpp
    branches/PR-7489777/darwinup/Column.h
    branches/PR-7489777/darwinup/DB.cpp
    branches/PR-7489777/darwinup/DB.h
    branches/PR-7489777/darwinup/Database.cpp
    branches/PR-7489777/darwinup/Database.h
    branches/PR-7489777/darwinup/Depot.cpp
    branches/PR-7489777/darwinup/Table.cpp
    branches/PR-7489777/darwinup/Table.h
    branches/PR-7489777/darwinup/main.cpp

Modified: branches/PR-7489777/darwinup/Column.cpp
===================================================================
--- branches/PR-7489777/darwinup/Column.cpp	2010-02-12 05:17:03 UTC (rev 704)
+++ branches/PR-7489777/darwinup/Column.cpp	2010-02-18 21:34:36 UTC (rev 705)
@@ -53,7 +53,8 @@
 	m_is_unique  = false;
 }
 
-Column::Column(const char* name, uint32_t type, bool is_index, bool is_pk, bool is_unique) {
+Column::Column(const char* name, uint32_t type, 
+			   bool is_index, bool is_pk, bool is_unique) {
 	m_name       = strdup(name);
 	m_create_sql = NULL;
 	m_type       = type;
@@ -71,7 +72,7 @@
 	return m_name;
 }
 
-const int Column::type() {
+uint32_t Column::type() {
 	return m_type;
 }
 
@@ -92,6 +93,13 @@
 	}
 }
 
+uint32_t Column::size() {
+	// integers are stored inband in the record
+	if (m_type == SQLITE_INTEGER) return sizeof(uint64_t);
+	// everything else is stored out of band
+	return sizeof(void*);
+}
+
 const bool Column::is_index() {
 	return m_is_index;
 }

Modified: branches/PR-7489777/darwinup/Column.h
===================================================================
--- branches/PR-7489777/darwinup/Column.h	2010-02-12 05:17:03 UTC (rev 704)
+++ branches/PR-7489777/darwinup/Column.h	2010-02-18 21:34:36 UTC (rev 705)
@@ -40,12 +40,14 @@
 struct Column {
 	Column();
 	Column(const char* name, uint32_t type);
-	Column(const char* name, uint32_t type, bool is_index, bool is_pk, bool is_unique);
+	Column(const char* name, uint32_t type,
+		   bool is_index, bool is_pk, bool is_unique);
 	virtual ~Column();
 	
 	const char*    name();
-	const int      type();
+	uint32_t       type();
 	const char*    typestr();
+	uint32_t       size();
 	const char*    create();
 	const char*    index();
 	
@@ -60,7 +62,6 @@
 	bool           m_is_index;
 	bool           m_is_pk;
 	bool           m_is_unique;
-	
 };
 
 #endif

Modified: branches/PR-7489777/darwinup/DB.cpp
===================================================================
--- branches/PR-7489777/darwinup/DB.cpp	2010-02-12 05:17:03 UTC (rev 704)
+++ branches/PR-7489777/darwinup/DB.cpp	2010-02-18 21:34:36 UTC (rev 705)
@@ -67,7 +67,7 @@
 	assert(m_files_table->add_column(new Column("uid",     TYPE_INTEGER))==0);
 	assert(m_files_table->add_column(new Column("gid",     TYPE_INTEGER))==0);
 	assert(m_files_table->add_column(new Column("size",    TYPE_INTEGER))==0);
-	assert(m_files_table->add_column(new Column("digest",  TYPE_BLOB))==0);
+	assert(m_files_table->add_column(new Column("digest",  TYPE_BLOB))==0); 
 	assert(m_files_table->add_column(new Column("path",    TYPE_TEXT,            true,  false, false))==0);
 	assert(this->add_table(this->m_files_table)==0);	
 }
@@ -87,9 +87,9 @@
 							  this->m_archives_table,
 							  this->m_archives_table->column(4), // active
 							  (void**)active,
-							  1,
+							  1,                                 // number of where conditions
 							  this->m_archives_table->column(0), // serial
-							  serial); // convert from bool to int	
+							  serial);
 }
 
 int DarwinupDatabase::update_archive(uint64_t serial, uuid_t uuid, const char* name,
@@ -122,18 +122,16 @@
 	return this->last_insert_id();
 }
 
-uint64_t DarwinupDatabase::get_file_serial_from_archive(Archive* archive, const char* path) {
-	uint64_t serial = 0;
-	this->get_value("file_serial__archive_path",
-					(void**)&serial,
-					this->m_files_table,
-					this->m_files_table->column(0), // serial
-					2,                              // number of where conditions
-					this->m_files_table->column(1), // archive
-					(uint64_t)archive->serial(),
-					this->m_files_table->column(8), // path
-					path);
-	return serial;
+int DarwinupDatabase::get_file_serial_from_archive(Archive* archive, const char* path, uint64_t** serial) {
+	return this->get_value("file_serial__archive_path",
+						   (void**)serial,
+						   this->m_files_table,
+						   this->m_files_table->column(0), // serial
+						   2,                              // number of where conditions
+						   this->m_files_table->column(1), // archive
+						   (uint64_t)archive->serial(),
+						   this->m_files_table->column(8), // path
+						   path);
 }
 
 int DarwinupDatabase::update_file(uint64_t serial, Archive* archive, uint32_t info, mode_t mode, 
@@ -186,12 +184,12 @@
 uint64_t DarwinupDatabase::count_files(Archive* archive, const char* path) {
 
 	int res = SQLITE_OK;
-	uint64_t* c = (uint64_t*)malloc(sizeof(uint64_t));
+	uint64_t* c;
 	if (!c) fprintf(stderr, "Error: ran out of memory in DarwinupDatabase::count_files().\n");
 	res = this->count("count_files",
-					  (void**)c,
+					  (void**)&c,
 					  this->m_files_table,
-					  2, // number of where conditions
+					  2,                              // number of where conditions
 					  this->m_files_table->column(1), // archive
 					  (uint64_t)archive->serial(),
 					  this->m_files_table->column(8), // path
@@ -228,9 +226,92 @@
 int DarwinupDatabase::delete_files(Archive* archive) {
 	return this->del("delete_files__archive",
 					 this->m_files_table,
-					 1,
+					 1,                               // number of where conditions
 					 this->m_files_table->column(1),  // archive
 					 (uint64_t)archive->serial());
 }
 
 
+int DarwinupDatabase::get_inactive_archive_serials(uint64_t** serials, uint32_t* count) {
+	int res = this->get_column("inactive_archive_serials",
+							   (void**)serials, count,
+							   this->m_archives_table,
+							   this->m_archives_table->column(0), // serial
+							   1,
+							   this->m_archives_table->column(4), // active
+							   (uint64_t)0);
+	return res;
+}
+
+int DarwinupDatabase::get_file_serials(uint64_t** serials, uint32_t* count) {
+	return this->get_column("file_serials", (void**)serials, count, 
+							this->m_files_table,
+							this->m_files_table->column(0),
+							0);
+}
+
+
+// serial uuid name date_added active info
+
+/*
+int DarwinupDatabase::process_archive_results() {
+	const unsigned char* name = sqlite3_column_text(stmt, 1);
+	uuid_t uuid;
+	const void* blob = sqlite3_column_blob(stmt, 1);
+	int blobsize = sqlite3_column_bytes(stmt, 1);
+	if (blobsize > 0) {
+		assert(blobsize == sizeof(uuid_t));
+		memcpy(uuid, blob, sizeof(uuid_t));
+	} else {
+		uuid_clear(uuid);
+	}
+	uint64_t serial = sqlite3_column_int64(stmt, 0);
+	uint64_t info = sqlite3_column_int64(stmt, 2);
+	time_t date_added = sqlite3_column_int(stmt, 3);	
+	return 0;
+}
+*/
+
+int DarwinupDatabase::get_archive(uint8_t** data, uuid_t uuid) {
+	return this->get_row("archive__uuid",
+						 data,
+						 this->m_archives_table,
+						 1,
+						 this->m_archives_table->column(1), // uuid
+						 uuid, sizeof(uuid_t));
+}
+
+int DarwinupDatabase::get_archive(uint8_t** data, uint64_t serial) {
+	return this->get_row("archive__serial",
+						 data,
+						 this->m_archives_table,
+						 1,
+						 this->m_archives_table->column(0), // serial
+						 serial);
+}
+
+int DarwinupDatabase::get_archive(uint8_t** data, const char* name) {
+	return this->get_row("archive__name",
+						 data,
+						 this->m_archives_table,
+						 1,
+						 this->m_archives_table->column(2), // name
+						 name);
+}
+
+int DarwinupDatabase::archive_offset(int column) {
+	return column*8;
+}
+
+
+/*
+get_all_archives(include_rollbacks?)
+
+count_archives(include_rollbacks?)
+ 
+get_files(archive)
+
+
+*/
+
+

Modified: branches/PR-7489777/darwinup/DB.h
===================================================================
--- branches/PR-7489777/darwinup/DB.h	2010-02-12 05:17:03 UTC (rev 704)
+++ branches/PR-7489777/darwinup/DB.h	2010-02-18 21:34:36 UTC (rev 705)
@@ -60,7 +60,12 @@
 	
 	uint64_t count_files(Archive* archive, const char* path);
 	
-	// Archives table modifications
+	// Archives
+	int      get_archive(uint8_t** data, uuid_t uuid);
+	int      get_archive(uint8_t** data, uint64_t serial);
+	int      get_archive(uint8_t** data, const char* name);
+	int      get_inactive_archive_serials(uint64_t** serials, uint32_t* count);
+	int      archive_offset(int column);
 	int      activate_archive(uint64_t serial);
 	int      deactivate_archive(uint64_t serial);
 	int      update_archive(uint64_t serial, uuid_t uuid, const char* name,
@@ -70,8 +75,9 @@
 	int      delete_archive(Archive* archive);
 	int      delete_archive(uint64_t serial);
 
-	// Files table modifications
-	uint64_t get_file_serial_from_archive(Archive* archive, const char* path);
+	// Files
+	int      get_file_serials(uint64_t** serials, uint32_t* count);
+	int      get_file_serial_from_archive(Archive* archive, const char* path, uint64_t** serial);
 	int      update_file(uint64_t serial, Archive* archive, uint32_t info, mode_t mode, 
 						 uid_t uid, gid_t gid, Digest* digest, const char* path);
 	uint64_t insert_file(uint32_t info, mode_t mode, uid_t uid, gid_t gid, 

Modified: branches/PR-7489777/darwinup/Database.cpp
===================================================================
--- branches/PR-7489777/darwinup/Database.cpp	2010-02-12 05:17:03 UTC (rev 704)
+++ branches/PR-7489777/darwinup/Database.cpp	2010-02-18 21:34:36 UTC (rev 705)
@@ -32,6 +32,13 @@
 
 #include "Database.h"
 
+// initial number of rows we allocate for when querying
+#define INITIAL_ROWS   8
+
+// how much we grow by when we need more space
+#define REALLOC_FACTOR 4
+#define ERROR_BUF_SIZE 1024
+
 /**
  * sqlite3_trace callback for debugging
  */
@@ -56,7 +63,7 @@
 	this->init_cache();
 	m_db = NULL;	
 	m_path = NULL;
-	m_error_size = 1024;
+	m_error_size = ERROR_BUF_SIZE;
 	m_error = (char*)malloc(m_error_size);
 }
 
@@ -70,7 +77,7 @@
 	if (!m_path) {
 		fprintf(stderr, "Error: ran out of memory when constructing database object.\n");
 	}
-	m_error_size = 1024;
+	m_error_size = ERROR_BUF_SIZE;
 	m_error = (char*)malloc(m_error_size);
 }
 
@@ -186,12 +193,12 @@
 
 int Database::add_table(Table* t) {
 	if (m_table_count >= m_table_max) {
-		m_tables = (Table**)realloc(m_tables, m_table_max * sizeof(Table*) * 4);
+		m_tables = (Table**)realloc(m_tables, m_table_max * sizeof(Table*) * REALLOC_FACTOR);
 		if (!m_tables) {
 			fprintf(stderr, "Error: unable to reallocate memory to add a table\n");
 			return 1;
 		}
-		m_table_max *= 4;
+		m_table_max *= REALLOC_FACTOR;
 	}
 	m_tables[m_table_count++] = t;
 	
@@ -274,11 +281,9 @@
 		if (col->is_pk()) continue; \
 		uint8_t* bdata = NULL; \
 		uint32_t bsize = 0; \
-        uint64_t val = 1234; \
 		switch(col->type()) { \
 			case TYPE_INTEGER: \
-                val = va_arg(args, uint64_t); \
-				res = sqlite3_bind_int64(stmt, param++, val); \
+				res = sqlite3_bind_int64(stmt, param++, va_arg(args, uint64_t)); \
 				break; \
 			case TYPE_TEXT: \
 				res = sqlite3_bind_text(stmt, param++, va_arg(args, char*), -1, SQLITE_STATIC); \
@@ -304,16 +309,21 @@
 #define __bind_va_columns(_lastarg) \
     va_list args; \
     va_start(args, _lastarg); \
+    fprintf(stderr, "DEBUG: sql: %s \n", sqlite3_sql(stmt)); \
     for (uint32_t i=0; i<count; i++) { \
         Column* col = va_arg(args, Column*); \
         uint8_t* bdata = NULL; \
         uint32_t bsize = 0; \
+        uint64_t val; \
         switch(col->type()) { \
             case TYPE_INTEGER: \
-                res = sqlite3_bind_int64(stmt, param++, va_arg(args, uint64_t)); \
+                val = va_arg(args, uint64_t); \
+                res = sqlite3_bind_int64(stmt, param++, val); \
+                fprintf(stderr, "DEBUG: bind int: %llu \n", val); \
                 break; \
             case TYPE_TEXT: \
                 res = sqlite3_bind_text(stmt, param++, va_arg(args, char*), -1, SQLITE_STATIC); \
+                fprintf(stderr, "DEBUG: bind text \n"); \
                 break; \
             case TYPE_BLOB: \
                 bdata = va_arg(args, uint8_t*); \
@@ -322,12 +332,13 @@
                                         bdata, \
 										bsize, \
                                         SQLITE_STATIC); \
+                fprintf(stderr, "DEBUG: bind blob \n"); \
                 break; \
 		} \
         if (res != SQLITE_OK) { \
             fprintf(stderr, "Error: failed to bind parameter #%d with column #%d of type %d " \
-                            "table %s \n", \
-							param, i, col->type(), table->name()); \
+                            "table %s res %d: %s  \n", \
+							param-1, i, col->type(), table->name(), res, sqlite3_errmsg(m_db)); \
             return res; \
         } \
     } \
@@ -346,27 +357,153 @@
 	} \
 	free(key);
 
-#define __step_and_store(_stmt, _type, _output) \
-    res = sqlite3_step(_stmt); \
-    if (res == SQLITE_ROW) { \
-	    switch(_type) { \
-		    case TYPE_INTEGER: \
-			    *(uint64_t*)_output = (uint64_t)sqlite3_column_int64(_stmt, 0); \
-			    break; \
-		    case TYPE_TEXT: \
-			    *(const unsigned char**)_output = sqlite3_column_text(_stmt, 0); \
-			    break; \
-    		case TYPE_BLOB: \
-	    		*(const void**)_output = sqlite3_column_blob(_stmt, 0); \
-		    	break; \
-    	} \
-    } else { \
-        fprintf(stderr, "ERROR: __step_and_store(_stmt, _type_output) = %d \n", res); \
-		return res; \
-    } \
-    sqlite3_reset(_stmt); \
-    cache_release_value(m_statement_cache, &_stmt);
+size_t Database::store_column(sqlite3_stmt* stmt, int column, uint8_t* output) {
+	IF_DEBUG("store_column: column = %d  output = %p \n", column, output);
+	size_t used;
+	int type = sqlite3_column_type(stmt, column);
+	const void* blob;
+	int blobsize;
+	IF_DEBUG("column type = %d \n", type);
+	switch(type) {
+		case SQLITE_INTEGER:
+			*(uint64_t*)output = (uint64_t)sqlite3_column_int64(stmt, column);
+			used = sizeof(uint64_t);
+			IF_DEBUG("store_column used=%u output(%p) = %llu \n", 
+					 (uint32_t)used, output, *(uint64_t*)output);
+			break;
+		case SQLITE_TEXT:
+			*(const char**)output = strdup((const char*)sqlite3_column_text(stmt, column));
+			IF_DEBUG("store text: %p %s \n", (char*)output, (char*)output);
+			used = sizeof(char*);
+			IF_DEBUG("store_column used=%u output(%p) = %s \n", 
+					 (uint32_t)used, output, *(char**)output);
+			break;
+		case SQLITE_BLOB:
+			blob = sqlite3_column_blob(stmt, column);
+			blobsize = sqlite3_column_bytes(stmt, column);
+			IF_DEBUG("blob(%p) size=%d \n", blob, blobsize);
+			*(void**)output = malloc(blobsize);
+			if (*output && blobsize) memcpy(*(void**)output, blob, blobsize);
+			used = sizeof(void*);
+			IF_DEBUG("store_column used=%u output(%p) = %s \n", 
+					 (uint32_t)used, output, *(char**)output);
+			break;
+		default:
+			fprintf(stderr, "Error: unhandled column type in Database::store_column(): %d \n", 
+					type);
+			return 0;
+	}
 
+	return used;
+}
+
+/**
+ *
+ *
+ *   will not realloc memory for output since caller should know how
+ *   much to alloc in the first place. Sets used to be how many bytes
+ *   were written to output
+ */
+int Database::step_once(sqlite3_stmt* stmt, uint8_t* output, uint32_t* used) {
+	int res = sqlite3_step(stmt);
+	uint8_t* current = output;
+	IF_DEBUG("output = %p current = %p \n", output, current);
+	if (used) *used = 0;
+	if (used) IF_DEBUG("step_once used(%p) = %u \n", used, *used);
+
+	if (res == SQLITE_ROW) {
+		int count = sqlite3_column_count(stmt);
+		for (int i = 0; i < count; i++) {
+			IF_DEBUG("loop current ptr before = %p \n", current);
+			current += this->store_column(stmt, i, current);
+			IF_DEBUG("loop current ptr after = %p \n", current);
+		}
+		if (used) {
+			*used = current - output;
+			IF_DEBUG("step_once after store used(%p) = %u \n", used, *used);
+		}
+		res = SQLITE_OK;
+	}
+
+	return res;
+}
+
+int Database::step_column(sqlite3_stmt* stmt, void** output, uint32_t size, uint32_t* count) {
+	uint32_t used = 0;
+	uint32_t total_used = used;
+	uint32_t rowsize = size / INITIAL_ROWS;
+	uint8_t* current = *(uint8_t**)output;
+	*count = 0;
+	IF_DEBUG("rowsize = %u \n", rowsize);
+	int res = SQLITE_OK;
+	while (res == SQLITE_OK) {
+		current = *(uint8_t**)output + total_used;
+		IF_DEBUG("calling step_once with current(%p) \n", current);
+		res = this->step_once(stmt, current, &used);
+		if (res == SQLITE_OK) (*count)++;
+		total_used += used;
+		IF_DEBUG("stepped: used = %u total_used = %u size = %u \n", used, total_used, size);
+		if (total_used >= (size - rowsize)) {
+			size *= REALLOC_FACTOR;
+			*output = realloc(*output, size);
+			IF_DEBUG("reallocating: output = %p  size = %u \n", *output, size);
+			if (!*output) {
+				fprintf(stderr, "Error: ran out of memory in Database::step_once \n");
+				return SQLITE_ERROR;
+			}
+		}		
+	}
+    sqlite3_reset(stmt);
+	return res;
+}
+
+int Database::get_value(const char* name, void** output, Table* table, Column* value_column, 
+						uint32_t count, ...) {
+	__get_stmt(table->get_column(m_db, value_column, count, args));
+	int res = SQLITE_OK;
+	uint32_t param = 1;
+	__bind_va_columns(count);
+	uint32_t size = value_column->size();
+	*output = malloc(size);
+	res = this->step_once(stmt, (uint8_t*)*output, NULL);
+	IF_DEBUG("get_value output(%p) = %llu \n", *output, **(uint64_t**)output);
+	sqlite3_reset(stmt);
+	cache_release_value(m_statement_cache, &stmt);
+	return res;
+}
+
+int Database::get_column(const char* name, void** output, uint32_t* result_count, 
+						 Table* table, Column* column, uint32_t count, ...) {
+	__get_stmt(table->get_column(m_db, column, count, args));
+	IF_DEBUG("stmt = %s \n", sqlite3_sql(stmt));
+	int res = SQLITE_OK;
+	uint32_t param = 1;
+	__bind_va_columns(count);
+	uint32_t size = INITIAL_ROWS * column->size();
+	*output = malloc(size);
+	IF_DEBUG("get_column output = %p  size = %u \n", *output, size);
+	res = this->step_column(stmt, output, size, result_count);
+	IF_DEBUG("get_colu output(%p) = %llu \n", *output, **(uint64_t**)output);
+	sqlite3_reset(stmt);
+	cache_release_value(m_statement_cache, &stmt);
+	return res;
+}
+
+int Database::get_row(const char* name, uint8_t** output, Table* table, uint32_t count, ...) {
+	__get_stmt(table->get_row(m_db, count, args));
+	IF_DEBUG("stmt = %s \n", sqlite3_sql(stmt));
+	int res = SQLITE_OK;
+	uint32_t param = 1;
+	__bind_va_columns(count);
+	*output = table->alloc_result();
+	IF_DEBUG("Table::alloc_result = %p \n", *output);
+	res = this->step_once(stmt, *output, NULL);
+	IF_DEBUG("get_row output(%p) = %llu \n", *output, **(uint64_t**)output);
+	sqlite3_reset(stmt);
+	cache_release_value(m_statement_cache, &stmt);
+	return output == NULL;
+}
+
 int Database::sql(const char* name, const char* fmt, ...) {
 	sqlite3_stmt* stmt;
 	char* key = strdup(name);
@@ -394,20 +531,13 @@
 	int res = SQLITE_OK;
 	uint32_t param = 1;
 	__bind_va_columns(count);
-	__step_and_store(stmt, TYPE_INTEGER, output);
+	*output = malloc(sizeof(uint64_t));
+	res = this->step_once(stmt, *(uint8_t**)output, NULL);
+	sqlite3_reset(stmt);
+	cache_release_value(m_statement_cache, &stmt);	
 	return output == NULL;
 }
 
-int Database::get_value(const char* name, void** output, Table* table, Column* value_column, 
-						 uint32_t count, ...) {
-	__get_stmt(table->get_value(m_db, value_column, count, args));
-	int res = SQLITE_OK;
-	uint32_t param = 1;
-	__bind_va_columns(count);
-	__step_and_store(stmt, value_column->type(), output);
-	return output == NULL;
-}
-
 /**
  * Given a table and an arg list in the same order as Table::add_column() calls,
  * binds and executes a sql update. The Table is responsible for preparing the
@@ -521,7 +651,6 @@
 
 #undef __bind_all_columns
 #undef __get_stmt
-#undef __step_and_store
 
 uint64_t Database::last_insert_id() {
 	return (uint64_t)sqlite3_last_insert_rowid(m_db);

Modified: branches/PR-7489777/darwinup/Database.h
===================================================================
--- branches/PR-7489777/darwinup/Database.h	2010-02-12 05:17:03 UTC (rev 704)
+++ branches/PR-7489777/darwinup/Database.h	2010-02-18 21:34:36 UTC (rev 705)
@@ -93,6 +93,9 @@
 	int  count(const char* name, void** output, Table* table, uint32_t count, ...);
 	int  get_value(const char* name, void** output, Table* table, Column* value_column, 
 				   uint32_t count, ...);
+	int  get_column(const char* name, void** output, uint32_t* result_count, 
+					Table* table, Column* column, uint32_t count, ...);
+	int  get_row(const char* name, uint8_t** output, Table* table, uint32_t count, ...);
 	int  update_value(const char* name, Table* table, Column* value_column, void** value, 
 					  uint32_t count, ...);
 	int  update(Table* table, uint64_t pkvalue, ...);
@@ -115,6 +118,10 @@
 	
 	int execute(sqlite3_stmt* stmt);
 	
+	size_t store_column(sqlite3_stmt* stmt, int column, uint8_t* output);
+	int step_once(sqlite3_stmt* stmt, uint8_t* output, uint32_t* used);
+	int step_column(sqlite3_stmt* stmt, void** output, uint32_t size, uint32_t* count);
+	
 	// libcache
 	void init_cache();
 	void destroy_cache();

Modified: branches/PR-7489777/darwinup/Depot.cpp
===================================================================
--- branches/PR-7489777/darwinup/Depot.cpp	2010-02-12 05:17:03 UTC (rev 704)
+++ branches/PR-7489777/darwinup/Depot.cpp	2010-02-18 21:34:36 UTC (rev 705)
@@ -75,6 +75,10 @@
 }
 
 Depot::~Depot() {
+	
+	// XXX: this is expensive, but is it necessary?
+	//this->check_consistency();
+
 	if (m_lock_fd != -1)	this->unlock();
 	delete m_db2;
 	if (m_db)		sqlite3_close(m_db);
@@ -126,7 +130,7 @@
 	}
 	
 	m_db2 = new DarwinupDatabase(m_database_path);
-	
+		
 	return res;
 }
 
@@ -689,11 +693,6 @@
 	assert(rollback != NULL);
 	assert(archive != NULL);
 
-	// Check the consistency of the database before proceeding with the installation
-	// If this fails, abort the installation.
-	// res = this->check_consistency();
-	// if (res != 0) return res;
-
 	res = this->lock(LOCK_EX);
 	if (res != 0) return res;
 
@@ -896,9 +895,6 @@
 		return -1;
 	}
 
-//	res = this->check_consistency();
-//	if (res != 0) return res;
-
 	res = this->lock(LOCK_EX);
 	if (res != 0) return res;
 
@@ -1110,34 +1106,22 @@
 	SerialSet* inactive = new SerialSet();
 	assert(inactive != NULL);
 	
-	static sqlite3_stmt* stmt = NULL;
-	if (stmt == NULL && m_db) {
-		const char* query = "SELECT serial FROM archives WHERE active=0 ORDER BY serial DESC";
-		res = sqlite3_prepare(m_db, query, -1, &stmt, NULL);
-		if (res != 0) fprintf(stderr, "%s:%d: sqlite3_prepare: %s: %s (%d)\n", __FILE__, __LINE__, query, sqlite3_errmsg(m_db), res);
+	// get inactive archives serials from the database
+	uint64_t* serials;
+	uint32_t  count;
+	this->m_db2->get_inactive_archive_serials(&serials, &count);
+	for (uint32_t i=0; i < count; i++) {
+		inactive->add(serials[i]);
 	}
-	if (stmt && res == 0) {
-		while (res == 0) {
-			res = sqlite3_step(stmt);
-			if (res == SQLITE_ROW) {
-				res = 0;
-				uint64_t serial = sqlite3_column_int64(stmt, 0);
-				inactive->add(serial);
-			} else if (res == SQLITE_DONE) {
-				res = 0;
-				break;
-			} else {
-				fprintf(stderr, "%s:%d: unexpected SQL error: %d\n", __FILE__, __LINE__, res);
-			}
-		}
-		sqlite3_reset(stmt);
-	}
+	free(serials);
 	
+	// print a list of inactive archives
 	if (res == 0 && inactive && inactive->count > 0) {
-		fprintf(stderr, "The following archive%s in an inconsistent state and must be uninstalled before proceeding:\n\n", inactive->count > 1 ? "s are" : " is");
+		fprintf(stderr, "The following archive%s in an inconsistent state and must be uninstalled "
+						"before proceeding:\n\n", inactive->count > 1 ? "s are" : " is");
 		uint32_t i;
-		fprintf(stderr, "%-36s %-23s %s\n", "UUID", "Date Installed", "Name");
-		fprintf(stderr, "====================================  =======================  =================\n");
+		fprintf(stderr, "%-6s %-36s  %-23s  %s\n", "Serial", "UUID", "Date Installed", "Name");
+		fprintf(stderr, "====== ====================================  =======================  =================\n");
 		for (i = 0; i < inactive->count; ++i) {
 			Archive* archive = this->archive(inactive->values[i]);
 			if (archive) {
@@ -1219,7 +1203,8 @@
 int Depot::insert(Archive* archive, File* file) {
 	int res = 0;
 	int do_update = 0;
-
+	uint64_t* serial;
+	
 	// check for the destination prefix in file's path, remove if found
 	char *path, *relpath;
 	size_t prefixlen = strlen(this->prefix());
@@ -1231,14 +1216,16 @@
 
 	if (this->has_file(archive, file)) {
 		do_update = 1;
-		uint64_t serial = this->m_db2->get_file_serial_from_archive(archive, relpath);
+		res = this->m_db2->get_file_serial_from_archive(archive, relpath, &serial);
 		if (!serial) {
 			fprintf(stderr, "Error: unable to find file from archive %llu at path %s \n", 
 					archive->serial(), relpath);
 			return 1;
 		}
-		res = m_db2->update_file(serial, archive, file->info(), file->mode(), file->uid(), file->gid(),
-								 file->digest(), relpath);		
+		if (res == SQLITE_OK) {
+			res = m_db2->update_file(*serial, archive, file->info(), file->mode(), file->uid(), file->gid(),
+									 file->digest(), relpath);
+		}
 	} else {
 		file->m_serial = m_db2->insert_file(file->info(), file->mode(), file->uid(), file->gid(), 
 											file->digest(), archive, relpath);

Modified: branches/PR-7489777/darwinup/Table.cpp
===================================================================
--- branches/PR-7489777/darwinup/Table.cpp	2010-02-12 05:17:03 UTC (rev 704)
+++ branches/PR-7489777/darwinup/Table.cpp	2010-02-18 21:34:36 UTC (rev 705)
@@ -51,6 +51,9 @@
 	m_column_max    = 1;
 	m_column_count  = 0;
 	m_columns       = (Column**)malloc(sizeof(Column*) * m_column_max);
+	m_result_max    = 1;
+	m_result_count  = 0;
+	m_results       = (uint8_t**)malloc(sizeof(uint8_t*) * m_result_max);
 	m_name          = strdup("unnamed_table");
 	m_create_sql    = NULL;
 	m_insert_sql    = NULL;
@@ -66,6 +69,9 @@
 	m_column_max    = 1;
 	m_column_count  = 0;
 	m_columns       = (Column**)malloc(sizeof(Column*) * m_column_max);
+	m_result_max    = 1;
+	m_result_count  = 0;
+	m_results       = (uint8_t**)malloc(sizeof(uint8_t*) * m_result_max);
 	m_name          = strdup(name);
 	m_create_sql    = NULL;
 	m_insert_sql    = NULL;
@@ -80,8 +86,14 @@
 	for (uint32_t i = 0; i < m_column_count; i++) {
 		delete m_columns[i];
 	}
-
 	free(m_columns);
+	
+	for (uint32_t i=0; i < m_result_count; i++) {
+		this->free_row(m_results[i]);
+		free(m_results[i]);
+	}
+	free(m_results);
+	
 	free(m_name);
 
 	free(m_create_sql);
@@ -100,6 +112,10 @@
 	return m_name;
 }
 
+uint32_t Table::row_size() {
+	return m_column_count*8;
+}
+
 const Column** Table::columns() {
 	return (const Column**)m_columns;
 }
@@ -120,6 +136,54 @@
 }
 
 
+uint8_t* Table::alloc_result() {
+	if (m_result_count >= m_result_max) {
+		m_results = (uint8_t**)realloc(m_results, m_result_max * sizeof(uint8_t*) * 4);
+		if (!m_results) {
+			fprintf(stderr, "Error: unable to reallocate memory to add a result row\n");
+			return NULL;
+		}
+		m_result_max *= 4;
+	}
+	m_result_count++;
+	m_results[m_result_count-1] = (uint8_t*)calloc(1, this->row_size());
+	return m_results[m_result_count-1];
+}
+
+int Table::free_row(uint8_t* row) {
+	uint8_t* current = row;
+	for (uint32_t i=0; i < m_column_count; i++) {
+		switch (m_columns[i]->type()) {
+			case SQLITE_INTEGER:
+				current += sizeof(uint64_t);
+				// nothing to free
+				break;
+			default:
+				free(current);
+				current += sizeof(void*);
+		}
+	}
+	return 0;
+}
+
+int Table::free_result(uint8_t* result) {
+	for (uint32_t i=0; i < m_result_count; i++) {
+		// look for matching result
+		if (result == m_results[i]) {
+			this->free_row((uint8_t*)m_results[i]);
+			free(m_results[i]);
+			// if we did not free the last result,
+			// move last result to the empty slot
+			if (i != (m_result_count - 1)) {
+				m_results[i] = m_results[m_column_count-1];
+				m_results[m_column_count-1] = NULL;
+			}
+		}
+	}
+	return 0;
+}
+
+
 char* Table::create() {
 	if (!m_create_sql) {
 		uint32_t i = 0;
@@ -234,7 +298,7 @@
 	return stmt;	
 }
 
-sqlite3_stmt* Table::get_value(sqlite3* db, Column* value_column, uint32_t count, va_list args) {
+sqlite3_stmt* Table::get_column(sqlite3* db, Column* value_column, uint32_t count, va_list args) {
 	__alloc_stmt_query;
 	strlcpy(query, "SELECT ", size);
 	__check_and_cat(value_column->name());
@@ -243,12 +307,25 @@
 	__check_and_cat(" WHERE 1");
 	__where_va_columns;
 	strlcat(query, ";", size);
-	IF_DEBUG("[TABLE] get_value query: %s \n", query);
+	IF_DEBUG("[TABLE] get_column query: %s \n", query);
 	__prepare_stmt;
 	
 	return stmt;
 }
 
+sqlite3_stmt* Table::get_row(sqlite3* db, uint32_t count, va_list args) {
+	__alloc_stmt_query;
+	strlcpy(query, "SELECT * FROM ", size);
+	__check_and_cat(m_name);
+	__check_and_cat(" WHERE 1");
+	__where_va_columns;
+	strlcat(query, ";", size);
+	IF_DEBUG("[TABLE] get_row query: %s \n", query);
+	__prepare_stmt;
+	
+	return stmt;	
+}
+
 sqlite3_stmt* Table::update_value(sqlite3* db, Column* value_column, uint32_t count, va_list args) {
 	__alloc_stmt_query;
 	strlcpy(query, "UPDATE ", size);

Modified: branches/PR-7489777/darwinup/Table.h
===================================================================
--- branches/PR-7489777/darwinup/Table.h	2010-02-12 05:17:03 UTC (rev 704)
+++ branches/PR-7489777/darwinup/Table.h	2010-02-18 21:34:36 UTC (rev 705)
@@ -38,6 +38,7 @@
 #include <sqlite3.h>
 #include "Column.h"
 
+
 struct Table {	
 	Table();
 	Table(const char* name);
@@ -47,19 +48,22 @@
 	const Column** columns();
 	Column*        column(uint32_t index);
 	uint32_t       column_count();
+
+	uint8_t*       alloc_result();
+	int            free_result(uint8_t* result);
+
 	int            add_column(Column*);
-		
+	uint32_t       row_size();	
+	
 	// return SQL statements for this table
 	char*    create();  
-	char*    drop();    
-	char*    select(const char* where);
-	char*    select_column(const char* column, const char* where);		
+	char*    drop();   // XXX: implement this 
 
-
 	sqlite3_stmt*    count(sqlite3* db);
 	sqlite3_stmt*    count(sqlite3* db, uint32_t count, va_list args);
-	sqlite3_stmt*    get_value(sqlite3* db, Column* value_column, uint32_t count, 
-							   va_list args);
+	sqlite3_stmt*    get_column(sqlite3* db, Column* value_column, uint32_t count, 
+								va_list args);
+	sqlite3_stmt*    get_row(sqlite3* db, uint32_t count, va_list args);
 	sqlite3_stmt*    update_value(sqlite3* db, Column* value_column, uint32_t count,
 								  va_list args);
 	sqlite3_stmt*    insert(sqlite3* db);
@@ -69,6 +73,8 @@
 	
 protected:
 		
+	int            free_row(uint8_t* row);
+	
 	char*          m_name;
 	
 	char*          m_create_sql;
@@ -84,6 +90,10 @@
 	sqlite3_stmt*  m_prepared_update;
 	sqlite3_stmt*  m_prepared_delete;
 	
+	uint8_t**      m_results;
+	uint32_t       m_result_count;
+	uint32_t       m_result_max;
+
 };
 
 #endif

Modified: branches/PR-7489777/darwinup/main.cpp
===================================================================
--- branches/PR-7489777/darwinup/main.cpp	2010-02-12 05:17:03 UTC (rev 704)
+++ branches/PR-7489777/darwinup/main.cpp	2010-02-18 21:34:36 UTC (rev 705)
@@ -46,6 +46,32 @@
 #include <unistd.h>
 #include <limits.h>
 
+void __data_hex(uint8_t* data, uint32_t size) {
+	if (!size) return;
+	for (uint32_t i=0; i < size; i++) {
+		if (!(i%8)) {
+			if (i<10) fprintf(stderr, " ");
+			fprintf(stderr, "%d", i);
+		} else {
+			fprintf(stderr, "  ");
+		}
+	}
+	fprintf(stderr, "\n");
+	for (uint32_t i=0; i < size; i++) {
+		fprintf(stderr, "%02x", data[i]);
+	}
+	fprintf(stderr, "\n");
+}
+
+void __str_hex(const char* str) {
+	int i = 0;
+	while (str[i]) {
+		fprintf(stderr, "%02x", str[i++]);
+	}
+	fprintf(stderr, "\n");
+}
+
+
 void usage(char* progname) {
 	fprintf(stderr, "usage:    %s [-v] [-p DIR] [command] [args]          \n", progname);
 	fprintf(stderr, "version: 15                                                    \n");
@@ -145,12 +171,72 @@
 		exit(2);
 	}
 	
-	/*
+	
 	// XXX: test area for new database... remove me
 	DarwinupDatabase* testdb = depot->get_db2();
 
+	uuid_t uuid;
+	uuid_parse("5A41995B-CA3F-4BF3-84AC-2F5A42357769", uuid);
+	uint8_t* data;
+	fprintf(stderr, "main: data %p uuid %14s \n", &data, uuid);
+	testdb->get_archive(&data, uuid);
+	fprintf(stderr, "RESULT: %llu \n", (uint64_t)data[0]);
+	free(data);
+	uuid_clear(uuid);
+
+	testdb->get_archive(&data, 42);
+	fprintf(stderr, "DATA: %p \n", data);
+	__data_hex(data, 48);
+	char* p;
+	memcpy(&p, &data[16], 8);
+	uint64_t ss = 0;
+	memcpy(&ss, &data[0], 8);
+	time_t t = 0;
+	memcpy(&t, &data[24], 8);
+
+	fprintf(stderr, "RESULT: %llu \n", ss);
+	fprintf(stderr, "RESULT: %p -> %s \n", p, p);
+	fprintf(stderr, "RESULT: %llu \n", (uint64_t)t);
+	
+
+	
+	testdb->get_archive(&data, "root2");
+	char ustr[37];
+	uuid_t* up;
+	memcpy(&up, &data[8], sizeof(uuid_t*));
+	uuid_unparse_upper(*up, ustr);
+	fprintf(stderr, "RESULT: %s \n", ustr);
+
+	
+	
+	
+	uint64_t* s;
+	uint64_t a_serial = 3;
+	Archive* a = depot->archive(a_serial);
+	res = testdb->get_file_serial_from_archive(a, "/e/ee/e_data.txt", &s);
+	if (!res) {
+		IF_DEBUG("s = %llu \n", *s);
+	} else {
+		IF_DEBUG("DID NOT FIND SERIAL\n");
+	}
+	
+	uint64_t* serials;
+	uint32_t sc;
+	testdb->get_file_serials(&serials, &sc);
+	IF_DEBUG("serials(%p) = %llu sc = %u \n", serials, serials[0], sc);
+	for (uint32_t i=0; i < sc; i++) {
+		fprintf(stderr, "TEST: %d = %llu \n", i, serials[i]);
+	}
+
+	testdb->get_inactive_archive_serials(&serials, &sc);
+	IF_DEBUG("serials(%p) = %llu sc = %u \n", serials, serials[0], sc);
+	for (uint32_t i=0; i < sc; i++) {
+		fprintf(stderr, "INACTIVE: %d = %llu \n", i, serials[i]);
+	}
+
+	/*
 	Archive* a = new Archive("/.DarwinDepot/Archives/21BDC360-726B-436E-B426-B06B57F8A0CC.tar.bz2");
-	//uint64_t s = testdb->insert_archive(a->uuid(), a->info(), a->name(), a->date_installed());
+	uint64_t s = testdb->insert_archive(a->uuid(), a->info(), a->name(), a->date_installed());
 	
 	const char* mypath = "/etc/services";
 	File* f = FileFactory(mypath);	
@@ -167,10 +253,10 @@
 	if (depot->has_file(a, f)) {
 		fprintf(stderr, "HASFILE: true\n");
 	}
+	*/
 	
 	exit(0);
 	// XXX
-	*/
 	
 	if (argc == 2 && strcmp(argv[0], "install") == 0) {
 		char uuid[37];
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20100218/f204d2d5/attachment-0001.html>


More information about the darwinbuild-changes mailing list