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

cal at macports.org cal at macports.org
Fri May 27 15:39:26 PDT 2011


Revision: 78950
          http://trac.macports.org/changeset/78950
Author:   cal at macports.org
Date:     2011-05-27 15:39:26 -0700 (Fri, 27 May 2011)
Log Message:
-----------
rev-upgrade: Hopefully these changes make file correctly memory managed

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

Modified: branches/gsoc11-rev-upgrade/base/src/cregistry/file.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/cregistry/file.c	2011-05-27 22:35:10 UTC (rev 78949)
+++ branches/gsoc11-rev-upgrade/base/src/cregistry/file.c	2011-05-27 22:39:26 UTC (rev 78950)
@@ -1,5 +1,6 @@
 /*
  * file.c
+ * vim:tw=80:expandtab
  * $Id$
  *
  * Copyright (c) 2011 Clemens Lang <cal at macports.org>
@@ -54,23 +55,26 @@
         reg_error* errPtr UNUSED) {
     int is_new;
     reg_registry* reg = (reg_registry*)userdata;
-    sqlite_int64 id = sqlite3_column_int64(stmt, 0);
-	const unsigned char* path = sqlite3_column_text(stmt, 1);
+    reg_file_pk key;
+    Tcl_HashEntry* hash;
 
-	/* FIXME: custom hashing */
-    Tcl_HashEntry* hash = Tcl_CreateHashEntry(&reg->open_entries,
-            (const char*)&id, &is_new);
+    key.id = sqlite3_column_int64(stmt, 0);
+    key.path = (char *) sqlite3_column_text(stmt, 1);
+
+    hash = Tcl_CreateHashEntry(&reg->open_files,
+            (const char*)&key.id, &is_new);
     if (is_new) {
         reg_file* f = malloc(sizeof(reg_file));
         if (!f) {
             return 0;
         }
         f->reg = reg;
-        f->id = id;
-		f->path = strdup((const char*) path);
-		if (!f->path) {
-			return 0;
-		}
+        f->key.id = key.id;
+        f->key.path = strdup(key.path);
+        if (!f->key.path) {
+            free(f);
+            return 0;
+        }
         f->proc = NULL;
         *file = f;
         Tcl_SetHashValue(hash, f);
@@ -81,6 +85,55 @@
 }
 
 /**
+ * Opens an existing file in the registry.
+ *
+ * @param [in] reg      registry to open entry in
+ * @param [in] id       port id in the dabatase
+ * @param [in] path     file path in the database
+ * @param [out] errPtr  on error, a description of the error that occures
+ * @return              the file if success, NULL if failure
+ */
+reg_file* reg_file_open(reg_registry* reg, char* id, char* name,
+        reg_error* errPtr) {
+    sqlite3_stmt* stmt = NULL;
+    reg_file* file = NULL;
+    char* query = "SELECT id, path FORM registry.files WHERE id=? AND version=?";
+
+    if ((sqlite3_prepare(reg->db, query, -1, &stmt, NULL) == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 1, id, -1, SQLITE_STATIC)
+                == SQLITE_OK)
+            && (sqlite3_bind_text(stmt, 2, name, -1, SQLITE_STATIC)
+                == SQLITE_OK)) {
+        int r;
+        do {
+            r = sqlite3_step(stmt);
+            switch (r) {
+                case SQLITE_ROW:
+                    reg_stmt_to_file(reg, (void**)&file, stmt, errPtr);
+                    break;
+                case SQLITE_DONE:
+                    errPtr->code = REG_NOT_FOUND;
+                    errPtr->description = sqlite3_mprintf("no matching file found for: "
+                            "id=%s, name=%s", id, name);
+                    errPtr->free = (reg_error_destructor*) sqlite3_free;
+                    break;
+                case SQLITE_BUSY:
+                    continue;
+                default:
+                    reg_sqlite_error(reg->db, errPtr, query);
+                    break;
+            }
+        } while (r == SQLITE_BUSY);
+    } else {
+        reg_sqlite_error(reg->db, errPtr, query);
+    }
+    if (stmt) {
+        sqlite3_finalize(stmt);
+    }
+    return file;
+}
+
+/**
  * 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`.
@@ -88,16 +141,15 @@
  * @param [in] entry the entry to free
  */
 void reg_file_free(reg_file* file) {
-	/* FIXME: custom hashing */
-    Tcl_HashEntry* hash = Tcl_FindHashEntry(&file->reg->open_entries,
-                            (const char*)&file->id);
+    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->path) {
-		free(file->path);
-	}
+    if (file->key.path) {
+        free(file->key.path);
+    }
     free(file);
 }
 
@@ -193,7 +245,7 @@
     char* query;
     const char *text;
     query = sqlite3_mprintf("SELECT %q FROM registry.file WHERE id=%lld "
-            "AND path='%q'", key, file->id, file->path);
+            "AND path='%q'", key, file->key.id, file->key.path);
     if (sqlite3_prepare(reg->db, query, -1, &stmt, NULL) == SQLITE_OK) {
         int r;
         do {
@@ -248,7 +300,7 @@
     sqlite3_stmt* stmt = NULL;
     char* query;
     query = sqlite3_mprintf("UPDATE registry.ports SET %q = '%q' WHERE id=%lld "
-            "AND path='%q'", key, value, file->id, file->path);
+            "AND path='%q'", key, value, file->key.id, file->key.path);
     if (sqlite3_prepare(reg->db, query, -1, &stmt, NULL) == SQLITE_OK) {
         int r;
         do {
@@ -280,3 +332,31 @@
     return result;
 }
 
+/**
+ * Fetches a list of all open files
+ *
+ * @param [in] reg      registry to fetch files from
+ * @param [out] files   a list of open files
+ * @return              the number of open entries, -1 on error
+ */
+int reg_all_open_files(reg_registry* reg, reg_file*** files) {
+    reg_file* file;
+    int file_count = 0;
+    int file_space = 10;
+    Tcl_HashEntry* hash;
+    Tcl_HashSearch search;
+    *files = malloc(10 * sizeof(void*));
+    if (!*files) {
+        return -1;
+    }
+    for (hash = Tcl_FirstHashEntry(&reg->open_files, &search); hash != NULL;
+            hash = Tcl_NextHashEntry(&search)) {
+        file = Tcl_GetHashValue(hash);
+        if (!reg_listcat((void***)files, &file_count, &file_space, file)) {
+            free(*files);
+            return -1;
+        }
+    }
+    return file_count;
+}
+

Modified: branches/gsoc11-rev-upgrade/base/src/cregistry/file.h
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/cregistry/file.h	2011-05-27 22:35:10 UTC (rev 78949)
+++ branches/gsoc11-rev-upgrade/base/src/cregistry/file.h	2011-05-27 22:39:26 UTC (rev 78950)
@@ -38,22 +38,31 @@
 #include <sqlite3.h>
 
 typedef struct {
-	/* rowid and path form the primary key */
-	/* unfortunately, we don't have a surrogate key in this db */
-    sqlite_int64 id; /* rowid in database */
-	char *path; /* path in database */
+    /* rowid and path form the primary key */
+    /* unfortunately, we don't have a surrogate key in this db */
+    sqlite_int64 id; /* rowid in the database */
+    char* path; /* path in the database */
+} reg_file_pk;
+
+typedef struct {
+    reg_file_pk key;
     reg_registry* reg; /* associated registry */
     char* proc; /* name of Tcl proc, if using Tcl */
 } reg_file;
 
+reg_file* reg_file_open(reg_registry* reg, char* id, char* path,
+        reg_error* errPtr);
+
 void reg_file_free(reg_file* file); /* TODO: is this actually being used? */
 
 int reg_file_search(reg_registry* reg, char** keys, char** vals, int* strats,
         int key_count, reg_file*** files, reg_error* errPtr);
 
 int reg_file_propget(reg_file* file, char* key, char** value,
-		reg_error* errPtr);
+        reg_error* errPtr);
 int reg_file_propset(reg_file* file, char* key, char* value,
-		reg_error* errPtr);
+        reg_error* errPtr);
 
+int reg_all_open_files(reg_registry* reg, reg_file*** files);
+
 #endif /* _CFILE_H */

Modified: branches/gsoc11-rev-upgrade/base/src/cregistry/registry.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/cregistry/registry.c	2011-05-27 22:35:10 UTC (rev 78949)
+++ branches/gsoc11-rev-upgrade/base/src/cregistry/registry.c	2011-05-27 22:39:26 UTC (rev 78950)
@@ -31,6 +31,7 @@
 #endif
 
 #include "entry.h"
+#include "file.h"
 #include "sql.h"
 
 #include <stdio.h>
@@ -210,6 +211,9 @@
                         if (initialized || (create_tables(reg->db, errPtr))) {
                             Tcl_InitHashTable(&reg->open_entries,
                                     sizeof(sqlite_int64)/sizeof(int));
+                            Tcl_InitHashTable(&reg->open_files,
+                                    (sizeof(sqlite_int64)+sizeof(char*)) /
+                                    sizeof(int));
                             reg->status |= reg_attached;
                             result = 1;
                         }
@@ -258,6 +262,7 @@
     if (sqlite3_prepare(reg->db, query, -1, &stmt, NULL) == SQLITE_OK) {
         int r;
         reg_entry* entry;
+        reg_file* file;
         Tcl_HashEntry* curr;
         Tcl_HashSearch search;
         /* XXX: Busy waiting, consider using sqlite3_busy_handler/timeout */
@@ -275,6 +280,18 @@
                         free(entry);
                     }
                     Tcl_DeleteHashTable(&reg->open_entries);
+                    for (curr = Tcl_FirstHashEntry(&reg->open_files, &search);
+                            curr != NULL; curr = Tcl_NextHashEntry(&search)) {
+                        file = Tcl_GetHashValue(curr);
+                        if (file->proc) {
+                            free(file->proc);
+                        }
+                        if (file->key.path) {
+                            free(file->key.path);
+                        }
+                        free(file);
+                    }
+                    Tcl_DeleteHashTable(&reg->open_files);
                     reg->status &= ~reg_attached;
                     result = 1;
                     break;

Modified: branches/gsoc11-rev-upgrade/base/src/cregistry/registry.h
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/cregistry/registry.h	2011-05-27 22:35:10 UTC (rev 78949)
+++ branches/gsoc11-rev-upgrade/base/src/cregistry/registry.h	2011-05-27 22:39:26 UTC (rev 78950)
@@ -1,5 +1,6 @@
 /*
  * registry.h
+ * vim:tw=80:expandtab
  * $Id$
  *
  * Copyright (c) 2007 Chris Pickel <sfiera at macports.org>
@@ -70,6 +71,7 @@
     sqlite3* db;
     int status;
     Tcl_HashTable open_entries;
+    Tcl_HashTable open_files;
 } reg_registry;
 
 int reg_open(reg_registry** regPtr, reg_error* errPtr);

Modified: branches/gsoc11-rev-upgrade/base/src/registry2.0/file.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/registry2.0/file.c	2011-05-27 22:35:10 UTC (rev 78949)
+++ branches/gsoc11-rev-upgrade/base/src/registry2.0/file.c	2011-05-27 22:39:26 UTC (rev 78950)
@@ -1,5 +1,6 @@
 /*
  * file.c
+ * vim:tw=80:expandtab
  * $Id$
  *
  * Copyright (c) 2011 Clemens Lang <cal at macports.org>
@@ -52,9 +53,9 @@
  * @return             a file, or NULL if one couldn't be found
  * @see get_object
  */
-/*static reg_file* get_file(Tcl_Interp* interp, char* name, reg_error* errPtr) {
+static reg_file* get_file(Tcl_Interp* interp, char* name, reg_error* errPtr) {
     return (reg_file*)get_object(interp, name, "file", file_obj_cmd, errPtr);
-}*/
+}
 
 /**
  * Removes the file from the Tcl interpreter. Doesn't actually delete it since
@@ -66,10 +67,61 @@
 void delete_file(ClientData clientData) {
     reg_file* file = (reg_file*)clientData;
     free(file->proc);
-    free(file->path);
+    free(file->key.path);
     file->proc = NULL;
 }
 
+/**
+ * registry::file open portid path
+ *
+ * Opens a file matching the given parameters.
+ */
+static int file_open(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
+	reg_registry* reg = registry_for(interp, reg_attached);
+	if (objc != 4) {
+		Tcl_WrongNumArgs(interp, 1, objv, "open portid path");
+		return TCL_ERROR;
+	} else if (reg == NULL) {
+		return TCL_ERROR;
+	} else {
+		char* id = Tcl_GetString(objv[2]);
+		char* path = Tcl_GetString(objv[3]);
+		reg_error error;
+		reg_file* file = reg_file_open(reg, id, path, &error);
+		if (file != NULL) {
+			Tcl_Obj* result;
+			if (file_to_obj(interp, &result, file, &error)) {
+				Tcl_SetObjResult(interp, result);
+				return TCL_OK;
+			}
+		}
+		return registry_failed(interp, &error);
+	}
+	return TCL_ERROR;
+}
+
+/**
+ * registry::file close file
+ *
+ * Closes a file. It will remain in the registry.
+ */
+static int file_close(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]) {
+	if (objc != 3) {
+		Tcl_WrongNumArgs(interp, 1, objv, "close file");
+		return TCL_ERROR;
+	} else {
+		reg_error error;
+		char* proc = Tcl_GetString(objv[2]);
+		reg_file* file = get_file(interp, proc, &error);
+		if (file == NULL) {
+			return registry_failed(interp, &error);
+		} else {
+			Tcl_DeleteCommand(interp, proc);
+			return TCL_OK;
+		}
+	}
+}
+
 typedef struct {
     char* name;
     reg_strategy strategy;
@@ -207,6 +259,8 @@
 
 static file_cmd_type file_cmds[] = {
     /* Global commands */
+    { "open", file_open },
+    { "close", file_close },
     { "search", file_search },
     { NULL, NULL }
 };

Modified: branches/gsoc11-rev-upgrade/base/src/registry2.0/registry.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/registry2.0/registry.c	2011-05-27 22:35:10 UTC (rev 78949)
+++ branches/gsoc11-rev-upgrade/base/src/registry2.0/registry.c	2011-05-27 22:39:26 UTC (rev 78950)
@@ -56,6 +56,8 @@
     return TCL_ERROR;
 }
 
+/* we don't need delete_file_list and restore_file_list unless we allow deletion
+   of files via the file interface */
 static void delete_entry_list(ClientData list, Tcl_Interp* interp UNUSED) {
     entry_list* curr = *(entry_list**)list;
     while (curr) {
@@ -82,8 +84,11 @@
 int registry_tcl_detach(Tcl_Interp* interp, reg_registry* reg,
         reg_error* errPtr) {
     reg_entry** entries;
-    int entry_count = reg_all_open_entries(reg, &entries);
+    reg_file** files;
+    int entry_count;
+    int file_count;
     int i;
+    entry_count = reg_all_open_entries(reg, &entries);
     if (entry_count == -1) {
         return 0;
     }
@@ -93,6 +98,19 @@
         }
     }
     free(entries);
+    file_count = reg_all_open_files(reg, &files);
+    if (file_count == -1) {
+        return 0;
+    }
+    for (i = 0; i < file_count; i++) {
+        if (files[i]->proc) {
+            Tcl_DeleteCommand(interp, files[i]->proc);
+        }
+        if (files[i]->key.path) {
+            free(files[i]->key.path);
+        }
+    }
+    free(files);
     if (!reg_detach(reg, errPtr)) {
         return registry_failed(interp, errPtr);
     }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20110527/a05162a7/attachment.html>


More information about the macports-changes mailing list