Index: appfs.c ================================================================== --- appfs.c +++ appfs.c @@ -1,9 +1,10 @@ #define FUSE_USE_VERSION 26 #include #include +#include #include #include #include #include #include @@ -14,13 +15,15 @@ #define APPFS_CACHEDIR "/tmp/appfs-cache" #define APPFS_DEBUG(x...) { fprintf(stderr, "[debug] %s:%i:%s: ", __FILE__, __LINE__, __func__); fprintf(stderr, x); fprintf(stderr, "\n"); } +static pthread_key_t interpKey; + struct appfs_thread_data { - Tcl_Interp *interp; sqlite3 *db; + const char *cachedir; }; struct appfs_thread_data globalThread; typedef enum { @@ -165,10 +168,55 @@ return("unknown"); } return("unknown"); } + +static Tcl_Interp *appfs_create_TclInterp(const char *cachedir) { + Tcl_Interp *interp; + int tcl_ret; + + interp = Tcl_CreateInterp(); + if (interp == NULL) { + fprintf(stderr, "Unable to create Tcl Interpreter. Aborting.\n"); + + return(NULL); + } + + tcl_ret = Tcl_Init(interp); + if (tcl_ret != TCL_OK) { + fprintf(stderr, "Unable to initialize Tcl. Aborting.\n"); + + return(NULL); + } + + tcl_ret = Tcl_Eval(interp, "" +#include "appfs.tcl.h" + ""); + if (tcl_ret != TCL_OK) { + fprintf(stderr, "Unable to initialize Tcl AppFS script. Aborting.\n"); + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + + return(NULL); + } + + if (Tcl_SetVar(interp, "::appfs::cachedir", cachedir, TCL_GLOBAL_ONLY) == NULL) { + fprintf(stderr, "Unable to set cache directory. This should never fail.\n"); + + return(NULL); + } + + tcl_ret = Tcl_Eval(interp, "::appfs::init"); + if (tcl_ret != TCL_OK) { + fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init). Aborting.\n"); + fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + + return(NULL); + } + + return(interp); +} static int appfs_Tcl_Eval(Tcl_Interp *interp, int objc, const char *cmd, ...) { Tcl_Obj **objv; const char *arg; va_list argp; @@ -193,53 +241,83 @@ Tcl_DecrRefCount(objv[i]); } ckfree((void *) objv); - return(retval); -} - -static int appfs_update_index(const char *hostname) { - int tcl_ret; - - tcl_ret = appfs_Tcl_Eval(globalThread.interp, 2, "::appfs::getindex", hostname); - if (tcl_ret != TCL_OK) { - APPFS_DEBUG("Call to ::appfs::getindex failed: %s", Tcl_GetStringResult(globalThread.interp)); - - return(-1); - } - - return(0); -} - -static const char *appfs_getfile(const char *hostname, const char *sha1) { - char *retval; - int tcl_ret; - - tcl_ret = appfs_Tcl_Eval(globalThread.interp, 3, "::appfs::download", hostname, sha1); - if (tcl_ret != TCL_OK) { - APPFS_DEBUG("Call to ::appfs::download failed: %s", Tcl_GetStringResult(globalThread.interp)); - - return(NULL); - } - - retval = strdup(Tcl_GetStringResult(globalThread.interp)); - - return(retval); -} - -static int appfs_update_manifest(const char *hostname, const char *sha1) { - int tcl_ret; - - tcl_ret = appfs_Tcl_Eval(globalThread.interp, 3, "::appfs::getpkgmanifest", hostname, sha1); - if (tcl_ret != TCL_OK) { - APPFS_DEBUG("Call to ::appfs::getpkgmanifest failed: %s", Tcl_GetStringResult(globalThread.interp)); - - return(-1); - } - - return(0); + if (retval != TCL_OK) { + APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0)); + } + + return(retval); +} + +static void appfs_update_index(const char *hostname) { + Tcl_Interp *interp; + int tcl_ret; + + APPFS_DEBUG("Enter: hostname = %s", hostname); + + interp = pthread_getspecific(interpKey); + if (interp == NULL) { + interp = appfs_create_TclInterp(globalThread.cachedir); + + pthread_setspecific(interpKey, interp); + } + + tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getindex", hostname); + if (tcl_ret != TCL_OK) { + APPFS_DEBUG("Call to ::appfs::getindex failed: %s", Tcl_GetStringResult(interp)); + + return; + } + + return; +} + +static const char *appfs_getfile(const char *hostname, const char *sha1) { + Tcl_Interp *interp; + char *retval; + int tcl_ret; + + interp = pthread_getspecific(interpKey); + if (interp == NULL) { + interp = appfs_create_TclInterp(globalThread.cachedir); + + pthread_setspecific(interpKey, interp); + } + + tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::download", hostname, sha1); + if (tcl_ret != TCL_OK) { + APPFS_DEBUG("Call to ::appfs::download failed: %s", Tcl_GetStringResult(interp)); + + return(NULL); + } + + retval = strdup(Tcl_GetStringResult(interp)); + + return(retval); +} + +static void appfs_update_manifest(const char *hostname, const char *sha1) { + Tcl_Interp *interp; + int tcl_ret; + + interp = pthread_getspecific(interpKey); + if (interp == NULL) { + interp = appfs_create_TclInterp(globalThread.cachedir); + + pthread_setspecific(interpKey, interp); + } + + tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::getpkgmanifest", hostname, sha1); + if (tcl_ret != TCL_OK) { + APPFS_DEBUG("Call to ::appfs::getpkgmanifest failed: %s", Tcl_GetStringResult(interp)); + + return; + } + + return; } #define appfs_free_list_type(id, type) static void appfs_free_list_ ## id(type *head) { \ type *obj, *next; \ @@ -326,20 +404,17 @@ } static struct appfs_package *appfs_getindex(const char *hostname, int *package_count_p) { struct appfs_package *head = NULL; char *sql; - int index_ret, sqlite_ret; + int sqlite_ret; if (package_count_p == NULL) { return(NULL); } - index_ret = appfs_update_index(hostname); - if (index_ret != 0) { - return(NULL); - } + appfs_update_index(hostname); sql = sqlite3_mprintf("SELECT package, version, sha1, os, cpuArch, isLatest FROM packages WHERE hostname = %Q;", hostname); if (sql == NULL) { APPFS_DEBUG("Call to sqlite3_mprintf failed."); @@ -385,25 +460,18 @@ } static struct appfs_children *appfs_getchildren(const char *hostname, const char *package_hash, const char *path, int *children_count_p) { struct appfs_children *head = NULL; char *sql; - int index_ret, sqlite_ret, manifest_ret; + int sqlite_ret; if (children_count_p == NULL) { return(NULL); } - index_ret = appfs_update_index(hostname); - if (index_ret != 0) { - return(NULL); - } - - manifest_ret = appfs_update_manifest(hostname, package_hash); - if (manifest_ret != 0) { - return(NULL); - } + appfs_update_index(hostname); + appfs_update_manifest(hostname, package_hash); sql = sqlite3_mprintf("SELECT file_name FROM files WHERE package_sha1 = %Q AND file_directory = %Q;", package_hash, path); if (sql == NULL) { APPFS_DEBUG("Call to sqlite3_mprintf failed."); @@ -436,16 +504,13 @@ } static char *appfs_lookup_package_hash(const char *hostname, const char *package, appfs_os_t os, appfs_cpuArch_t cpuArch, const char *version) { char *sql; char *retval = NULL; - int index_ret, sqlite_ret; + int sqlite_ret; - index_ret = appfs_update_index(hostname); - if (index_ret != 0) { - return(NULL); - } + appfs_update_index(hostname); sql = sqlite3_mprintf("SELECT sha1 FROM packages WHERE hostname = %Q AND package = %Q AND os = %Q AND cpuArch = %Q AND version = %Q;", hostname, package, appfs_convert_os_toString(os), @@ -525,25 +590,18 @@ } static int appfs_getfileinfo(const char *hostname, const char *package_hash, const char *_path, struct appfs_pathinfo *pathinfo) { char *directory, *file, *path; char *sql; - int index_ret, sqlite_ret, manifest_ret; + int sqlite_ret; if (pathinfo == NULL) { return(-EIO); } - index_ret = appfs_update_index(hostname); - if (index_ret != 0) { - return(-EIO); - } - - manifest_ret = appfs_update_manifest(hostname, package_hash); - if (manifest_ret != 0) { - return(-EIO); - } + appfs_update_index(hostname); + appfs_update_manifest(hostname, package_hash); path = strdup(_path); directory = path; file = strrchr(path, '/'); if (file == NULL) { @@ -1008,46 +1066,17 @@ #endif int main(int argc, char **argv) { const char *cachedir = APPFS_CACHEDIR; char dbfilename[1024]; - int tcl_ret, snprintf_ret, sqlite_ret; - - globalThread.interp = Tcl_CreateInterp(); - if (globalThread.interp == NULL) { - fprintf(stderr, "Unable to create Tcl Interpreter. Aborting.\n"); - - return(1); - } - - tcl_ret = Tcl_Init(globalThread.interp); - if (tcl_ret != TCL_OK) { - fprintf(stderr, "Unable to initialize Tcl. Aborting.\n"); - - return(1); - } - - tcl_ret = Tcl_Eval(globalThread.interp, "" -#include "appfs.tcl.h" - ""); - if (tcl_ret != TCL_OK) { - fprintf(stderr, "Unable to initialize Tcl AppFS script. Aborting.\n"); - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(globalThread.interp)); - - return(1); - } - - if (Tcl_SetVar(globalThread.interp, "::appfs::cachedir", cachedir, TCL_GLOBAL_ONLY) == NULL) { - fprintf(stderr, "Unable to set cache directory. This should never fail.\n"); - - return(1); - } - - tcl_ret = appfs_Tcl_Eval(globalThread.interp, 1, "::appfs::init"); - if (tcl_ret != TCL_OK) { - fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init). Aborting.\n"); - fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(globalThread.interp)); + int pthread_ret, snprintf_ret, sqlite_ret; + + globalThread.cachedir = cachedir; + + pthread_ret = pthread_key_create(&interpKey, NULL); + if (pthread_ret != 0) { + fprintf(stderr, "Unable to create TSD key for Tcl. Aborting.\n"); return(1); } snprintf_ret = snprintf(dbfilename, sizeof(dbfilename), "%s/%s", cachedir, "cache.db");