/* * aolstub.c -- * * This file provides the stubs needed for the AOLserver, to load NSF. * Please note that at least AOLserver 4.* or NaviServer 4.99.4 or newer * are required. Might have to have to apply a small patch to the * AOLserver as well (available from www.xotcl.org) in order to get it * working. * * Copyright (C) 2006-2013 Zoran Vasiljevic (a) * Copyright (C) 2006-2014 Gustaf Neumann (b) * * (a) Archiware Inc. * * (b) Vienna University of Economics and Business * Institute of Information Systems and New Media * A-1020, Welthandelsplatz 1 * Vienna, Austria * * This work is licensed under the MIT License https://www.opensource.org/licenses/MIT * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * */ #ifdef AOL_SERVER #include "nsf.h" #include NS_EXPORT int Ns_ModuleVersion = 1; #if NS_MAJOR_VERSION>=4 # define AOL4 #endif /* *---------------------------------------------------------------------------- * * NsNsf_Init -- * * Loads the package for the first time, i.e. in the startup thread. * * Results: * Standard Tcl result * * Side effects: * Package initialized. Tcl commands created. * *---------------------------------------------------------------------------- */ static int NsNsf_Init (Tcl_Interp *interp, void *context) { static int firsttime = 1; int ret; ret = Nsf_Init(interp); if (firsttime != 0) { if (ret != TCL_OK) { Ns_Log(Warning, "can't load module %s: %s", (char *)context, Tcl_GetStringResult(interp)); } else { Ns_Log(Notice, "%s module version %s", (char*)context, NSF_PATCHLEVELL); /* * Import the Nsf namespace only for the shell after * predefined is through */ Tcl_Import(interp, Tcl_GetGlobalNamespace(interp), "nsf::*", 0); } firsttime = 0; } return ret; } /* *---------------------------------------------------------------------------- * * NsNsf_Init1 -- * * Loads the package in each thread-interpreter. * This is needed since Nsf Class/Object commands are not copied * from the startup thread to the connection (or any other) thread. * during AOLserver initialization and/or thread creation times. * * Why ? * * Simply because these two commands declare a delete callback which is * unsafe to call in any other thread but in the one which created them. * * To understand this, you may need to get yourself acquainted with the * mechanics of the AOLserver, more precisely, with the way Tcl interps * are initialized (dive into nsd/tclinit.c in AOLserver distro). * * So, we made sure (by patching the AOLserver code) that no commands with * delete callbacks declared, are ever copied from the startup thread. * Additionally, we also made sure that AOLserver properly invokes any * AtCreate callbacks. So, instead of activating those callbacks *after* * running the Tcl-initialization script (which is the standard behavior) * we activate them *before*. So we may get a chance to configure the * interpreter correctly for any commands within the init script. * * Proper Nsf usage would be to declare all resources (classes, objects) * at server initialization time and let AOLserver machinery to copy them * (or re-create them, better yet) in each new thread. * Resources created within a thread are automatically garbage-collected * on thread-exit time, so don't create any Nsf resources there. * Create them in the startup thread and they will automatically be copied * for you. * Look in /modules/tcl/nsf for a simple example. * * Results: * Standard Tcl result. * * Side effects: * Tcl commands created. * *---------------------------------------------------------------------------- */ static int NsNsf_Init1 (Tcl_Interp *interp, void *notUsed) { int result; #ifndef AOL4 result = Nsf_Init(interp); #else result = TCL_OK; #endif /* * Import the Nsf namespace only for the shell after * predefined is through */ Tcl_Import(interp, Tcl_GetGlobalNamespace(interp), "nsf::*", 1); return result; } /* *---------------------------------------------------------------------------- * * Ns_ModuleInit -- * * Called by the AOLserver when loading shared object file. * * Results: * Standard AOLserver result * * Side effects: * Many. Depends on the package. * *---------------------------------------------------------------------------- */ int Ns_ModuleInit(char *hServer, char *hModule) nonnull(1) nonnull(2); int Ns_ModuleInit(char *hServer, char *hModule) { int ret; assert(hServer != NULL); assert(hModule != NULL); /*Ns_Log(Notice, "+++ ModuleInit","INIT");*/ ret = Ns_TclInitInterps(hServer, NsNsf_Init, (void*)hModule); if (ret == TCL_OK) { /* * See discussion for NsNsf_Init1 procedure. * Note that you need to patch AOLserver for this to work! * The patch basically forbids copying of C-level commands with * declared delete callbacks. It also runs all AtCreate callbacks * BEFORE AOLserver runs the Tcl script for initializing new interps. * These callbacks are then responsible for setting up the stage * for correct (Nsf) extension startup (including copying any * Nsf resources (classes, objects) created in the startup thread. */ Ns_TclRegisterAtCreate((Ns_TclInterpInitProc *)NsNsf_Init1, NULL); } return ret == TCL_OK ? NS_OK : NS_ERROR; } #else /* avoid empty translation unit */ typedef void empty; #endif /* * Local Variables: * mode: c * c-basic-offset: 2 * fill-column: 78 * indent-tabs-mode: nil * End: */