[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(®->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(®->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(®->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(®->open_entries,
sizeof(sqlite_int64)/sizeof(int));
+ Tcl_InitHashTable(®->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(®->open_entries);
+ for (curr = Tcl_FirstHashEntry(®->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(®->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