[78973] branches/gsoc11-rev-upgrade/base/src

cal at macports.org cal at macports.org
Sat May 28 09:39:41 PDT 2011


Revision: 78973
          http://trac.macports.org/changeset/78973
Author:   cal at macports.org
Date:     2011-05-28 09:39:40 -0700 (Sat, 28 May 2011)
Log Message:
-----------
rev-upgrade:

registry2.0/
	util.{h,c}:
		- today in your "alchemy for the 21st century"-lesson: Reducing O(n^2) to O(n)
		- removed unused function all_objects and it's dependency type set_object_function
	entry.c, file.c:
		- changes required by the interface change of unique_name
cregistry/
	entry.c, util.{h,c}, registry.h:
		- changes required by the interface change of unique_name
	registry.c:
		- changed reg->open_files Tcl HashMap to use string keys
	file.c:
		- changed adding entries to reg->open_files Tcl HashMap to use string keys
		- changes required by the interface change of unique_name
		- removed unused function reg_file_free

Modified Paths:
--------------
    branches/gsoc11-rev-upgrade/base/src/cregistry/entry.c
    branches/gsoc11-rev-upgrade/base/src/cregistry/file.c
    branches/gsoc11-rev-upgrade/base/src/cregistry/registry.c
    branches/gsoc11-rev-upgrade/base/src/cregistry/registry.h
    branches/gsoc11-rev-upgrade/base/src/cregistry/util.c
    branches/gsoc11-rev-upgrade/base/src/cregistry/util.h
    branches/gsoc11-rev-upgrade/base/src/registry2.0/entry.c
    branches/gsoc11-rev-upgrade/base/src/registry2.0/file.c
    branches/gsoc11-rev-upgrade/base/src/registry2.0/util.c
    branches/gsoc11-rev-upgrade/base/src/registry2.0/util.h

Modified: branches/gsoc11-rev-upgrade/base/src/cregistry/entry.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/cregistry/entry.c	2011-05-28 16:21:31 UTC (rev 78972)
+++ branches/gsoc11-rev-upgrade/base/src/cregistry/entry.c	2011-05-28 16:39:40 UTC (rev 78973)
@@ -77,7 +77,7 @@
  * @return              true if success; false if failure
  */
 static int reg_stmt_to_entry(void* userdata, void** entry, void* stmt,
-        reg_error* errPtr UNUSED) {
+        void* calldata UNUSED, reg_error* errPtr UNUSED) {
     int is_new;
     reg_registry* reg = (reg_registry*)userdata;
     sqlite_int64 id = sqlite3_column_int64(stmt, 0);
@@ -182,6 +182,7 @@
     reg_entry* entry = NULL;
     char* query = "SELECT id FROM registry.ports WHERE name=? AND version=? "
         "AND revision=? AND variants=? AND epoch=?";
+    int lower_bound = 0;
     if ((sqlite3_prepare(reg->db, query, -1, &stmt, NULL) == SQLITE_OK)
             && (sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC)
                 == SQLITE_OK)
@@ -198,7 +199,7 @@
             r = sqlite3_step(stmt);
             switch (r) {
                 case SQLITE_ROW:
-                    reg_stmt_to_entry(reg, (void**)&entry, stmt, errPtr);
+                    reg_stmt_to_entry(reg, (void**)&entry, stmt, &lower_bound, errPtr);
                     break;
                 case SQLITE_DONE:
                     errPtr->code = REG_NOT_FOUND;
@@ -339,8 +340,9 @@
  */
 static int reg_all_entries(reg_registry* reg, char* query, int query_len,
         reg_entry*** objects, reg_error* errPtr) {
+    int lower_bound = 0;
     return reg_all_objects(reg, query, query_len, (void***)objects,
-            reg_stmt_to_entry, NULL, errPtr);
+            reg_stmt_to_entry, &lower_bound, NULL, errPtr);
 }
 
 /**
@@ -486,6 +488,7 @@
     int result = 0;
     sqlite3_stmt* stmt = NULL;
     char* query = "SELECT id FROM registry.files WHERE actual_path=? AND active";
+    int lower_bound = 0;
     if ((sqlite3_prepare(reg->db, query, -1, &stmt, NULL) == SQLITE_OK)
             && (sqlite3_bind_text(stmt, 1, path, -1, SQLITE_STATIC)
                 == SQLITE_OK)) {
@@ -495,7 +498,7 @@
             switch (r) {
                 case SQLITE_ROW:
                     result = reg_stmt_to_entry(reg, (void**)entry, stmt,
-                            errPtr);
+                            &lower_bound, errPtr);
                     break;
                 case SQLITE_DONE:
                     *entry = NULL;

Modified: branches/gsoc11-rev-upgrade/base/src/cregistry/file.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/cregistry/file.c	2011-05-28 16:21:31 UTC (rev 78972)
+++ branches/gsoc11-rev-upgrade/base/src/cregistry/file.c	2011-05-28 16:39:40 UTC (rev 78973)
@@ -52,33 +52,42 @@
  * @return              true if success; false if failure
  */
 static int reg_stmt_to_file(void* userdata, void** file, void* stmt,
-        reg_error* errPtr UNUSED) {
+        void* calldata UNUSED, reg_error* errPtr UNUSED) {
     int is_new;
     reg_registry* reg = (reg_registry*)userdata;
     reg_file_pk key;
     Tcl_HashEntry* hash;
+    char* hashkey;
 
     key.id = sqlite3_column_int64(stmt, 0);
-    key.path = (char *) sqlite3_column_text(stmt, 1);
+    key.path = strdup((const char*) sqlite3_column_text(stmt, 1));
+    if (!key.path) {
+        return 0;
+    }
 
+    hashkey = sqlite3_mprintf("%lld:%s", key.id, key.path);
+    if (!hashkey) {
+        free(key.path);
+        return 0;
+    }
     hash = Tcl_CreateHashEntry(&reg->open_files,
-            (const char*)&key.id, &is_new);
+            hashkey, &is_new);
+    sqlite3_free(hashkey);
+
     if (is_new) {
         reg_file* f = malloc(sizeof(reg_file));
         if (!f) {
+            free(key.path);
             return 0;
         }
         f->reg = reg;
         f->key.id = key.id;
-        f->key.path = strdup(key.path);
-        if (!f->key.path) {
-            free(f);
-            return 0;
-        }
+        f->key.path = key.path;
         f->proc = NULL;
         *file = f;
         Tcl_SetHashValue(hash, f);
     } else {
+        free(key.path);
         *file = Tcl_GetHashValue(hash);
     }
     return 1;
@@ -98,6 +107,7 @@
     sqlite3_stmt* stmt = NULL;
     reg_file* file = NULL;
     char* query = "SELECT id, path FORM registry.files WHERE id=? AND version=?";
+    int lower_bound = 0;
 
     if ((sqlite3_prepare(reg->db, query, -1, &stmt, NULL) == SQLITE_OK)
             && (sqlite3_bind_text(stmt, 1, id, -1, SQLITE_STATIC)
@@ -109,7 +119,8 @@
             r = sqlite3_step(stmt);
             switch (r) {
                 case SQLITE_ROW:
-                    reg_stmt_to_file(reg, (void**)&file, stmt, errPtr);
+                    reg_stmt_to_file(reg, (void**)&file, stmt, &lower_bound,
+                            errPtr);
                     break;
                 case SQLITE_DONE:
                     errPtr->code = REG_NOT_FOUND;
@@ -134,26 +145,6 @@
 }
 
 /**
- * Frees a file. Normally this is unnecessary, as open entries will be
- * automatically freed when the registry is detached. Calling this method
- * externally should only be necessary following `reg_entry_delete`.
- *
- * @param [in] entry the entry to free
- */
-void reg_file_free(reg_file* file) {
-    Tcl_HashEntry* hash = Tcl_FindHashEntry(&file->reg->open_files,
-                            (const char*)&file->key.id);
-    Tcl_DeleteHashEntry(hash);
-    if (file->proc != NULL) {
-        free(file->proc);
-    }
-    if (file->key.path) {
-        free(file->key.path);
-    }
-    free(file);
-}
-
-/**
  * Type-safe version of `reg_all_objects` for `reg_file`.
  *
  * @param [in] reg       registry to select entries from
@@ -165,8 +156,9 @@
  */
 static int reg_all_files(reg_registry* reg, char* query, int query_len,
         reg_file*** objects, reg_error* errPtr) {
+    int lower_bound = 0;
     return reg_all_objects(reg, query, query_len, (void***)objects,
-            reg_stmt_to_file, NULL, errPtr);
+            reg_stmt_to_file, &lower_bound, NULL, errPtr);
 }
 
 /**

Modified: branches/gsoc11-rev-upgrade/base/src/cregistry/registry.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/cregistry/registry.c	2011-05-28 16:21:31 UTC (rev 78972)
+++ branches/gsoc11-rev-upgrade/base/src/cregistry/registry.c	2011-05-28 16:39:40 UTC (rev 78973)
@@ -212,8 +212,7 @@
                             Tcl_InitHashTable(&reg->open_entries,
                                     sizeof(sqlite_int64)/sizeof(int));
                             Tcl_InitHashTable(&reg->open_files,
-                                    (sizeof(sqlite_int64)+sizeof(char*)) /
-                                    sizeof(int));
+                                    TCL_STRING_KEYS);
                             reg->status |= reg_attached;
                             result = 1;
                         }

Modified: branches/gsoc11-rev-upgrade/base/src/cregistry/registry.h
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/cregistry/registry.h	2011-05-28 16:21:31 UTC (rev 78972)
+++ branches/gsoc11-rev-upgrade/base/src/cregistry/registry.h	2011-05-28 16:39:40 UTC (rev 78973)
@@ -57,7 +57,7 @@
 void reg_throw(reg_error* errPtr, char* code, char* fmt, ...);
 
 typedef int (cast_function)(void* userdata, void** dst, void* src,
-        reg_error* errPtr);
+        void* calldata, reg_error* errPtr);
 typedef void (free_function)(void* userdata, void* item);
 
 enum {

Modified: branches/gsoc11-rev-upgrade/base/src/cregistry/util.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/cregistry/util.c	2011-05-28 16:21:31 UTC (rev 78972)
+++ branches/gsoc11-rev-upgrade/base/src/cregistry/util.c	2011-05-28 16:39:40 UTC (rev 78973)
@@ -127,8 +127,8 @@
  * @return               the number of objects if success; negative if failure
  */
 int reg_all_objects(reg_registry* reg, char* query, int query_len,
-        void*** objects, cast_function* fn, free_function* del,
-        reg_error* errPtr) {
+        void*** objects, cast_function* fn, void* castcalldata,
+        free_function* del, reg_error* errPtr) {
     void** results = malloc(10*sizeof(void*));
     int result_count = 0;
     int result_space = 10;
@@ -143,7 +143,7 @@
             r = sqlite3_step(stmt);
             switch (r) {
                 case SQLITE_ROW:
-                    if (fn(reg, &row, stmt, errPtr)) {
+                    if (fn(reg, &row, stmt, castcalldata, errPtr)) {
                         if (!reg_listcat(&results, &result_count, &result_space, row)) {
                             r = SQLITE_ERROR;
                         }

Modified: branches/gsoc11-rev-upgrade/base/src/cregistry/util.h
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/cregistry/util.h	2011-05-28 16:21:31 UTC (rev 78972)
+++ branches/gsoc11-rev-upgrade/base/src/cregistry/util.h	2011-05-28 16:39:40 UTC (rev 78973)
@@ -45,8 +45,8 @@
 int reg_strcat(char** dst, size_t* dst_len, size_t* dst_space, char* src);
 int reg_listcat(void*** dst, int* dst_len, int* dst_space, void* src);
 int reg_all_objects(reg_registry* reg, char* query, int query_len,
-        void*** objects, cast_function* fn, free_function* del,
-        reg_error* errPtr);
+        void*** objects, cast_function* fn, void* castcalldata,
+        free_function* del, reg_error* errPtr);
 char* reg_strategy_op(reg_strategy strategy, reg_error* errPtr);
 
 #endif /* _CUTIL_H */

Modified: branches/gsoc11-rev-upgrade/base/src/registry2.0/entry.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/registry2.0/entry.c	2011-05-28 16:21:31 UTC (rev 78972)
+++ branches/gsoc11-rev-upgrade/base/src/registry2.0/entry.c	2011-05-28 16:39:40 UTC (rev 78973)
@@ -114,7 +114,7 @@
                 variants, epoch, &error);
         if (entry != NULL) {
             Tcl_Obj* result;
-            if (entry_to_obj(interp, &result, entry, &error)) {
+            if (entry_to_obj(interp, &result, entry, NULL, &error)) {
                 Tcl_SetObjResult(interp, result);
                 return TCL_OK;
             }
@@ -194,7 +194,7 @@
                 variants, epoch, &error);
         if (entry != NULL) {
             Tcl_Obj* result;
-            if (entry_to_obj(interp, &result, entry, &error)) {
+            if (entry_to_obj(interp, &result, entry, NULL, &error)) {
                 Tcl_SetObjResult(interp, result);
                 return TCL_OK;
             }
@@ -457,7 +457,7 @@
                 return TCL_OK;
             } else {
                 Tcl_Obj* result;
-                if (entry_to_obj(interp, &result, entry, &error)) {
+                if (entry_to_obj(interp, &result, entry, NULL, &error)) {
                     Tcl_SetObjResult(interp, result);
                     return TCL_OK;
                 }

Modified: branches/gsoc11-rev-upgrade/base/src/registry2.0/file.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/registry2.0/file.c	2011-05-28 16:21:31 UTC (rev 78972)
+++ branches/gsoc11-rev-upgrade/base/src/registry2.0/file.c	2011-05-28 16:39:40 UTC (rev 78973)
@@ -90,7 +90,7 @@
 		reg_file* file = reg_file_open(reg, id, path, &error);
 		if (file != NULL) {
 			Tcl_Obj* result;
-			if (file_to_obj(interp, &result, file, &error)) {
+			if (file_to_obj(interp, &result, file, NULL, &error)) {
 				Tcl_SetObjResult(interp, result);
 				return TCL_OK;
 			}

Modified: branches/gsoc11-rev-upgrade/base/src/registry2.0/util.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/registry2.0/util.c	2011-05-28 16:21:31 UTC (rev 78972)
+++ branches/gsoc11-rev-upgrade/base/src/registry2.0/util.c	2011-05-28 16:39:40 UTC (rev 78973)
@@ -46,24 +46,28 @@
  * Tcl interp context. This behavior is similar to that of the builtin
  * `interp create` command, and is intended to generate names for created
  * objects of a similar nature.
- *
- * TODO: add a int* parameter so that functions which need large numbers of
- * unique names can keep track of the lower bound between calls,thereby turning
- * N^2 to N. It'll be alchemy for the 21st century.
  */
-char* unique_name(Tcl_Interp* interp, char* prefix) {
+char* unique_name(Tcl_Interp* interp, char* prefix, int* lower_bound) {
     int result_size = strlen(prefix) + TCL_INTEGER_SPACE + 1;
     char* result = malloc(result_size);
     Tcl_CmdInfo info;
     int i;
     if (!result)
         return NULL;
-    for (i=0; ; i++) {
+    if (lower_bound == NULL) {
+        i = 0;
+    } else {
+        i = *lower_bound;
+    }
+    for (; ; i++) {
         snprintf(result, result_size, "%s%d", prefix, i);
         if (Tcl_GetCommandInfo(interp, result, &info) == 0) {
             break;
         }
     }
+    if (lower_bound != NULL) {
+        *lower_bound = i + 1;
+    }
     return result;
 }
 
@@ -226,47 +230,6 @@
     }
 }
 
-/**
- * Sets the result of the interpreter to all objects returned by a query.
- *
- * This function executes `query` on `db` It expects that the query will return
- * records of a single column, `rowid`. It will then use `prefix` to construct
- * unique names for these records, and call `setter` to construct their proc
- * objects. The result of `interp` will be set to a list of all such objects.
- *
- * If TCL_OK is returned, then a list is in the result. If TCL_ERROR is, then an
- * error is there.
- */
-int all_objects(Tcl_Interp* interp, sqlite3* db, char* query, char* prefix,
-        set_object_function* setter) {
-    sqlite3_stmt* stmt;
-    if (sqlite3_prepare(db, query, -1, &stmt, NULL) == SQLITE_OK) {
-        Tcl_Obj* result = Tcl_NewListObj(0, NULL);
-        Tcl_SetObjResult(interp, result);
-        while (sqlite3_step(stmt) == SQLITE_ROW) {
-            sqlite_int64 rowid = sqlite3_column_int64(stmt, 0);
-            char* name = unique_name(interp, prefix);
-            if (!name) {
-                return TCL_ERROR;
-            }
-            if (setter(interp, name, rowid) == TCL_OK) {
-                Tcl_Obj* element = Tcl_NewStringObj(name, -1);
-                Tcl_ListObjAppendElement(interp, result, element);
-                free(name);
-            } else {
-                free(name);
-                return TCL_ERROR;
-            }
-        }
-        sqlite3_finalize(stmt);
-        return TCL_OK;
-    } else {
-        sqlite3_finalize(stmt);
-        set_sqlite_result(interp, db, query);
-        return TCL_ERROR;
-    }
-}
-
 const char* string_or_null(Tcl_Obj* obj) {
     const char* string = Tcl_GetString(obj);
     if (string[0] == '\0') {
@@ -276,15 +239,16 @@
     }
 }
 
-int recast(void* userdata, cast_function* fn, free_function* del, void*** outv,
-        void** inv, int inc, reg_error* errPtr) {
+int recast(void* userdata, cast_function* fn, void* castcalldata,
+        free_function* del, void*** outv, void** inv, int inc,
+        reg_error* errPtr) {
     void** result = malloc(inc*sizeof(void*));
     int i;
     if (!result) {
         return 0;
     }
     for (i=0; i<inc; i++) {
-        if (!fn(userdata, &result[i], inv[i], errPtr)) {
+        if (!fn(userdata, &result[i], inv[i], castcalldata, errPtr)) {
             if (del != NULL) {
                 for ( ; i>=0; i--) {
                     del(userdata, result[i]);
@@ -299,9 +263,9 @@
 }
 
 int entry_to_obj(Tcl_Interp* interp, Tcl_Obj** obj, reg_entry* entry,
-        reg_error* errPtr) {
+        int* lower_bound, reg_error* errPtr) {
     if (entry->proc == NULL) {
-        char* name = unique_name(interp, "::registry::entry");
+        char* name = unique_name(interp, "::registry::entry", lower_bound);
         if (!name) {
             return 0;
         }
@@ -316,9 +280,9 @@
 }
 
 int file_to_obj(Tcl_Interp* interp, Tcl_Obj** obj, reg_file* file,
-        reg_error* errPtr) {
+        int* lower_bound, reg_error* errPtr) {
     if (file->proc == NULL) {
-        char* name = unique_name(interp, "::registry::file");
+        char* name = unique_name(interp, "::registry::file", lower_bound);
         if (!name) {
             return 0;
         }
@@ -326,6 +290,7 @@
             free(name);
             return 0;
         }
+        free(name);
     }
     *obj = Tcl_NewStringObj(file->proc, -1);
     return 1;
@@ -333,30 +298,32 @@
 
 int list_entry_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
         reg_entry** entries, int entry_count, reg_error* errPtr) {
-    return recast(interp, (cast_function*)entry_to_obj, NULL, (void***)objs,
-            (void**)entries, entry_count, errPtr);
+    int lower_bound = 0;
+    return recast(interp, (cast_function*)entry_to_obj, &lower_bound, NULL,
+            (void***)objs, (void**)entries, entry_count, errPtr);
 }
 
 int list_file_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
         reg_file** files, int file_count, reg_error* errPtr) {
-    return recast(interp, (cast_function*)file_to_obj, NULL, (void***)objs,
-            (void**)files, file_count, errPtr);
+    int lower_bound = 0;
+    return recast(interp, (cast_function*)file_to_obj, &lower_bound, NULL,
+            (void***)objs, (void**)files, file_count, errPtr);
 }
 
 static int obj_to_string(void* userdata UNUSED, char** string, Tcl_Obj* obj,
-        reg_error* errPtr UNUSED) {
+        void* param UNUSED, reg_error* errPtr UNUSED) {
     *string = Tcl_GetString(obj);
     return 1;
 }
 
 int list_obj_to_string(char*** strings, Tcl_Obj** objv, int objc,
         reg_error* errPtr) {
-    return recast(NULL, (cast_function*)obj_to_string, NULL, (void***)strings,
+    return recast(NULL, (cast_function*)obj_to_string, NULL, NULL, (void***)strings,
             (void**)objv, objc, errPtr);
 }
 
 static int string_to_obj(void* userdata UNUSED, Tcl_Obj** obj, char* string,
-        reg_error* errPtr UNUSED) {
+        void* param UNUSED, reg_error* errPtr UNUSED) {
     *obj = Tcl_NewStringObj(string, -1);
     return 1;
 }
@@ -367,6 +334,6 @@
 
 int list_string_to_obj(Tcl_Obj*** objv, char** strings, int objc,
         reg_error* errPtr) {
-    return recast(NULL, (cast_function*)string_to_obj, (free_function*)free_obj,
+    return recast(NULL, (cast_function*)string_to_obj, NULL, (free_function*)free_obj,
             (void***)objv, (void**)strings, objc, errPtr);
 }

Modified: branches/gsoc11-rev-upgrade/base/src/registry2.0/util.h
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/registry2.0/util.h	2011-05-28 16:21:31 UTC (rev 78972)
+++ branches/gsoc11-rev-upgrade/base/src/registry2.0/util.h	2011-05-28 16:39:40 UTC (rev 78973)
@@ -46,7 +46,7 @@
 
 #define END_FLAGS 0
 
-char* unique_name(Tcl_Interp* interp, char* prefix);
+char* unique_name(Tcl_Interp* interp, char* prefix, int* lower_bound);
 
 int parse_flags(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[], int* start,
         option_spec options[], int* flags);
@@ -58,28 +58,24 @@
 int set_entry(Tcl_Interp* interp, char* name, reg_entry* entry,
         reg_error* errPtr);
 int set_file(Tcl_Interp* interp, char* name, reg_file* file,
-		reg_error* errPtr);
+        reg_error* errPtr);
 
 void set_sqlite_result(Tcl_Interp* interp, sqlite3* db, const char* query);
 
-typedef int set_object_function(Tcl_Interp* interp, char* name,
-        sqlite_int64 rowid);
-int all_objects(Tcl_Interp* interp, sqlite3* db, char* query, char* prefix,
-        set_object_function* setter);
-
 const char* string_or_null(Tcl_Obj* obj);
 
-int recast(void* userdata, cast_function* fn, free_function* del, void*** outv,
-        void** inv, int inc, reg_error* errPtr);
+int recast(void* userdata, cast_function* fn, void* castcalldata,
+        free_function* del, void*** outv, void** inv, int inc,
+        reg_error* errPtr);
 
 int entry_to_obj(Tcl_Interp* interp, Tcl_Obj** obj, reg_entry* entry,
-        reg_error* errPtr);
+        int* lower_bound, reg_error* errPtr);
 int list_entry_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
         reg_entry** entries, int entry_count, reg_error* errPtr);
 int file_to_obj(Tcl_Interp* interp, Tcl_Obj** ibj, reg_file* file,
-		reg_error* errPtr);
+        int* lower_bound, reg_error* errPtr);
 int list_file_to_obj(Tcl_Interp* interp, Tcl_Obj*** objs,
-		reg_file** files, int file_count, reg_error* errPtr);
+        reg_file** files, int file_count, reg_error* errPtr);
 
 void free_strings(void* userdata UNUSED, char** strings, int count);
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20110528/ae5fe014/attachment-0001.html>


More information about the macports-changes mailing list