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

source_changes at macosforge.org source_changes at macosforge.org
Fri Feb 19 15:07:41 PST 2010


Revision: 708
          http://trac.macosforge.org/projects/darwinbuild/changeset/708
Author:   wsiegrist at apple.com
Date:     2010-02-19 15:07:41 -0800 (Fri, 19 Feb 2010)
Log Message:
-----------
Implement ordered row queries, fix double free during Table destructor.

Modified Paths:
--------------
    branches/PR-7489777/darwinup/Archive.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/Depot.h
    branches/PR-7489777/darwinup/Table.cpp
    branches/PR-7489777/darwinup/Table.h

Modified: branches/PR-7489777/darwinup/Archive.h
===================================================================
--- branches/PR-7489777/darwinup/Archive.h	2010-02-19 00:40:07 UTC (rev 707)
+++ branches/PR-7489777/darwinup/Archive.h	2010-02-19 23:07:41 UTC (rev 708)
@@ -39,7 +39,14 @@
 #include <time.h>
 #include <uuid/uuid.h>
 
+typedef char* archive_name_t;
 
+enum archive_keyword_t {
+	DEPOT_ARCHIVE_NEWEST,
+	DEPOT_ARCHIVE_OLDEST
+};
+
+
 //
 // ARCHIVE_INFO flags stored in the database
 //

Modified: branches/PR-7489777/darwinup/DB.cpp
===================================================================
--- branches/PR-7489777/darwinup/DB.cpp	2010-02-19 00:40:07 UTC (rev 707)
+++ branches/PR-7489777/darwinup/DB.cpp	2010-02-19 23:07:41 UTC (rev 708)
@@ -185,7 +185,6 @@
 
 	int res = SQLITE_OK;
 	uint64_t* c;
-	if (!c) fprintf(stderr, "Error: ran out of memory in DarwinupDatabase::count_files().\n");
 	res = this->count("count_files",
 					  (void**)&c,
 					  this->m_files_table,
@@ -295,6 +294,26 @@
 						 name);
 }
 
+int DarwinupDatabase::get_archive(uint8_t** data, archive_keyword_t keyword) {
+	int res = SQLITE_OK;
+	int order = ORDER_BY_DESC;
+
+	if (keyword == DEPOT_ARCHIVE_OLDEST) {
+		order = ORDER_BY_ASC;
+	}
+	
+	res = this->get_row_ordered("archive__keyword",
+								data,
+								this->m_archives_table,
+								this->m_archives_table->column(3), // order by date_added
+								order,
+								1,
+								this->m_archives_table->column(2), // name
+								"!<Rollback>");
+	
+	return res;
+}
+
 int DarwinupDatabase::archive_offset(int column) {
 	return this->m_archives_table->offset(column);
 }

Modified: branches/PR-7489777/darwinup/DB.h
===================================================================
--- branches/PR-7489777/darwinup/DB.h	2010-02-19 00:40:07 UTC (rev 707)
+++ branches/PR-7489777/darwinup/DB.h	2010-02-19 23:07:41 UTC (rev 708)
@@ -44,6 +44,7 @@
 #include "File.h"
 
 
+
 /**
  *
  * Darwinup database abstraction. This class is responsible
@@ -65,6 +66,7 @@
 	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_archive(uint8_t** data, archive_keyword_t keyword);
 	int      get_inactive_archive_serials(uint64_t** serials, uint32_t* count);
 	int      archive_offset(int column);
 	int      activate_archive(uint64_t serial);

Modified: branches/PR-7489777/darwinup/Database.cpp
===================================================================
--- branches/PR-7489777/darwinup/Database.cpp	2010-02-19 00:40:07 UTC (rev 707)
+++ branches/PR-7489777/darwinup/Database.cpp	2010-02-19 23:07:41 UTC (rev 708)
@@ -32,13 +32,6 @@
 
 #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
  */
@@ -313,16 +306,15 @@
         Column* col = va_arg(args, Column*); \
         uint8_t* bdata = NULL; \
         uint32_t bsize = 0; \
-        uint64_t val; \
+        char* tval; \
         switch(col->type()) { \
             case TYPE_INTEGER: \
-                val = va_arg(args, uint64_t); \
-                res = sqlite3_bind_int64(stmt, param++, val); \
-                fprintf(stderr, "DEBUG: bind int: %llu \n", 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); \
-                fprintf(stderr, "DEBUG: bind text \n"); \
+                tval = va_arg(args, char*); \
+                if (tval[0] == '!' || tval[0] == '>' || tval[0] == '<') tval++; \
+                res = sqlite3_bind_text(stmt, param++, tval, -1, SQLITE_STATIC); \
                 break; \
             case TYPE_BLOB: \
                 bdata = va_arg(args, uint8_t*); \
@@ -331,7 +323,6 @@
                                         bdata, \
 										bsize, \
                                         SQLITE_STATIC); \
-                fprintf(stderr, "DEBUG: bind blob \n"); \
                 break; \
 		} \
         if (res != SQLITE_OK) { \
@@ -372,7 +363,7 @@
 			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);
+			IF_DEBUG("[ALLOC] 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);
@@ -382,6 +373,7 @@
 			blobsize = sqlite3_column_bytes(stmt, column);
 			IF_DEBUG("blob(%p) size=%d \n", blob, blobsize);
 			*(void**)output = malloc(blobsize);
+			IF_DEBUG("[ALLOC] blob %p \n", (void*)*output);
 			if (*output && blobsize) memcpy(*(void**)output, blob, blobsize);
 			used = sizeof(void*);
 			IF_DEBUG("store_column used=%u output(%p) = %s \n", 
@@ -503,6 +495,23 @@
 	return res;
 }
 
+int Database::get_row_ordered(const char* name, uint8_t** output, Table* table, Column* order_by,
+							  int order, uint32_t count, ...) {
+	__get_stmt(table->get_row_ordered(m_db, order_by, order, 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_ordered output(%p) = %llu \n", *output, **(uint64_t**)output);
+	sqlite3_reset(stmt);
+	cache_release_value(m_statement_cache, &stmt);
+	return res;
+}
+
+
 int Database::sql(const char* name, const char* fmt, ...) {
 	sqlite3_stmt* stmt;
 	char* key = strdup(name);

Modified: branches/PR-7489777/darwinup/Database.h
===================================================================
--- branches/PR-7489777/darwinup/Database.h	2010-02-19 00:40:07 UTC (rev 707)
+++ branches/PR-7489777/darwinup/Database.h	2010-02-19 23:07:41 UTC (rev 708)
@@ -47,6 +47,19 @@
 #include "Digest.h"
 #include "Archive.h"
 
+#define ORDER_BY_DESC 0
+#define ORDER_BY_ASC  1
+
+// 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
+
+
+
+
 // libcache callbacks
 bool cache_key_is_equal(void* key1, void* key2, void* user);
 void cache_key_retain(void* key_in, void** key_out, void* user_data);
@@ -96,6 +109,8 @@
 	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  get_row_ordered(const char* name, uint8_t** output, Table* table, Column* order_by, 
+						 int order, 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, ...);

Modified: branches/PR-7489777/darwinup/Depot.cpp
===================================================================
--- branches/PR-7489777/darwinup/Depot.cpp	2010-02-19 00:40:07 UTC (rev 707)
+++ branches/PR-7489777/darwinup/Depot.cpp	2010-02-19 23:07:41 UTC (rev 708)
@@ -35,7 +35,6 @@
 #include "File.h"
 #include "SerialSet.h"
 #include "Utils.h"
-
 #include <assert.h>
 #include <copyfile.h>
 #include <errno.h>
@@ -47,9 +46,9 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/stat.h>
-
 #include <sqlite3.h>
 
+
 Depot::Depot() {
 	m_prefix = NULL;
 	m_depot_path = NULL;
@@ -183,28 +182,10 @@
 Archive* Depot::archive(archive_keyword_t keyword) {
 	int res = 0;
 	Archive* archive = NULL;
-	static sqlite3_stmt* stmt = NULL;
-	const char* query = NULL;
-	if (stmt == NULL && m_db) {
-		if (keyword == DEPOT_ARCHIVE_NEWEST) {
-			query = "SELECT serial FROM archives WHERE name != '<Rollback>' ORDER BY date_added DESC LIMIT 1";
-		} else if (keyword == DEPOT_ARCHIVE_OLDEST) {
-			query = "SELECT serial FROM archives WHERE name != '<Rollback>' ORDER BY date_added ASC LIMIT 1";
-		} else {
-			fprintf(stderr, "Error: unknown archive keyword.\n");
-			res = -1;
-		}
-		if (res == 0) 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);
-	}
-	if (stmt && res == 0) {
-		res = sqlite3_step(stmt);
-		if (res == SQLITE_ROW) {
-			uint64_t serial = sqlite3_column_int64(stmt, 0);
-			archive = Depot::archive(serial);
-		}
-		sqlite3_reset(stmt);
-	}
+	uint8_t* data;
+	
+	res = this->m_db2->get_archive(&data, keyword);
+	if (res == 0) archive = this->m_db2->make_archive(data);	
 	return archive;	
 }
 

Modified: branches/PR-7489777/darwinup/Depot.h
===================================================================
--- branches/PR-7489777/darwinup/Depot.h	2010-02-19 00:40:07 UTC (rev 707)
+++ branches/PR-7489777/darwinup/Depot.h	2010-02-19 23:07:41 UTC (rev 708)
@@ -37,20 +37,15 @@
 #include <uuid/uuid.h>
 #include <sqlite3.h>
 #include "DB.h"
+#include "Archive.h"
 
 struct Archive;
 struct File;
+struct DarwinupDatabase;
 
 typedef int (*ArchiveIteratorFunc)(Archive* archive, void* context);
 typedef int (*FileIteratorFunc)(File* file, void* context);
 
-typedef char* archive_name_t;
-
-enum archive_keyword_t {
-		DEPOT_ARCHIVE_NEWEST,
-		DEPOT_ARCHIVE_OLDEST
-};
-
 struct Depot {
 	Depot();
 	Depot(const char* prefix);

Modified: branches/PR-7489777/darwinup/Table.cpp
===================================================================
--- branches/PR-7489777/darwinup/Table.cpp	2010-02-19 00:40:07 UTC (rev 707)
+++ branches/PR-7489777/darwinup/Table.cpp	2010-02-19 23:07:41 UTC (rev 708)
@@ -34,10 +34,13 @@
 #include <string.h>
 #include <stdlib.h>
 #include "Table.h"
+#include "Database.h"
 
+
 // how much we grow by when we need more space
 #define REALLOC_FACTOR 4
 
+
 // XXX
 void __hex_str(const char* s) {
 	int len = strlen(s);
@@ -56,6 +59,7 @@
 	m_result_max    = 1;
 	m_result_count  = 0;
 	m_results       = (uint8_t**)malloc(sizeof(uint8_t*) * m_result_max);
+	IF_DEBUG("[ALLOC] constructor %p \n", m_results);
 	m_name          = strdup("unnamed_table");
 	m_create_sql    = NULL;
 	m_insert_sql    = NULL;
@@ -74,6 +78,7 @@
 	m_result_max    = 1;
 	m_result_count  = 0;
 	m_results       = (uint8_t**)malloc(sizeof(uint8_t*) * m_result_max);
+	IF_DEBUG("[ALLOC] constructor %p \n", m_results);
 	m_name          = strdup(name);
 	m_create_sql    = NULL;
 	m_insert_sql    = NULL;
@@ -90,10 +95,14 @@
 	}
 	free(m_columns);
 	
+
 	for (uint32_t i=0; i < m_result_count; i++) {
-		this->free_row(m_results[i]);
-		free(m_results[i]);
+		if (m_results[i]) {
+			IF_DEBUG("[FREE] destructor loop %d %p \n", i, m_results[i]);
+			this->free_result(m_results[i]);
+		}
 	}
+	IF_DEBUG("[FREE] destructor free %p \n", m_results);
 	free(m_results);
 	
 	free(m_name);
@@ -150,6 +159,7 @@
 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*) * REALLOC_FACTOR);
+		IF_DEBUG("[ALLOC] realloc m_results %p \n", m_results);
 		if (!m_results) {
 			fprintf(stderr, "Error: unable to reallocate memory to add a result row\n");
 			return NULL;
@@ -158,6 +168,8 @@
 	}
 	m_result_count++;
 	m_results[m_result_count-1] = (uint8_t*)calloc(1, this->row_size());
+	IF_DEBUG("[ALLOC] calloc(%d) %d %p \n", this->row_size(), m_result_count-1, 
+			 m_results[m_result_count-1]);
 	return m_results[m_result_count-1];
 }
 
@@ -172,6 +184,7 @@
 				break;
 			default:
 				memcpy(&ptr, current, sizeof(void*));
+				IF_DEBUG("[FREE] %s: %p (type of %d: %d) \n", m_name, ptr, i, m_columns[i]->type());
 				free(ptr);
 				current += sizeof(void*);
 		}
@@ -184,7 +197,9 @@
 		// look for matching result
 		if (result == m_results[i]) {
 			this->free_row((uint8_t*)m_results[i]);
+			IF_DEBUG("[FREE] %s result %d %p \n", m_name, i, m_results[i]);
 			free(m_results[i]);
+			m_results[i] = NULL;
 			// if we did not free the last result,
 			// move last result to the empty slot
 			if (i != (m_result_count - 1)) {
@@ -259,11 +274,30 @@
 
 #define __where_va_columns \
 	char tmpstr[256]; \
+    char* val; \
+    const char* op = "="; \
 	int len; \
 	for (uint32_t i=0; i < count; i++) { \
+        fprintf(stderr, "DEBUG: __where_va i=%u \n", i); \
 		Column* col = va_arg(args, Column*); \
-		va_arg(args, void*); \
-		len = snprintf(tmpstr, 256, " AND %s=?", col->name()); \
+		fprintf(stderr, "DEBUG: __where_va col %p \n", col); \
+        if (col->type() == SQLITE_TEXT) { \
+            val = va_arg(args, char*); \
+            switch (val[0]) { \
+            case '!': \
+                op = "!="; \
+                break; \
+            case '>': \
+                op = ">"; \
+                break; \
+            case '<': \
+                op = "<"; \
+                break; \
+            } \
+		} else { \
+	        va_arg(args, void*); \
+        } \
+		len = snprintf(tmpstr, 256, " AND %s%s?", col->name(), op); \
 		if (len >= 255) { \
 			fprintf(stderr, "Error: column name is too big (limit: 248): %s\n", col->name()); \
 			return NULL; \
@@ -336,6 +370,24 @@
 	return stmt;	
 }
 
+sqlite3_stmt* Table::get_row_ordered(sqlite3* db, Column* order_by, int order, 
+									 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;
+	__check_and_cat(" ORDER BY ");
+	__check_and_cat(order_by->name());
+	__check_and_cat((order == ORDER_BY_DESC ? " DESC" : " ASC"));
+	strlcat(query, ";", size);
+	IF_DEBUG("[TABLE] get_row_ordered 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-19 00:40:07 UTC (rev 707)
+++ branches/PR-7489777/darwinup/Table.h	2010-02-19 23:07:41 UTC (rev 708)
@@ -33,11 +33,11 @@
 #ifndef _TABLE_H
 #define _TABLE_H
 
-
 #include <stdint.h>
 #include <sqlite3.h>
 #include "Column.h"
 
+
 struct Table {	
 	Table();
 	Table(const char* name);
@@ -63,6 +63,8 @@
 	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*    get_row_ordered(sqlite3* db, Column* order_by, int order, 
+							 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);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/darwinbuild-changes/attachments/20100219/d2ec0ec4/attachment-0001.html>


More information about the darwinbuild-changes mailing list