diff options
author | Bruce Momjian <bruce@momjian.us> | 2003-03-20 04:51:44 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2003-03-20 04:51:44 +0000 |
commit | 15ce2d2e4a3e9ae70801a5caa07579200a66b510 (patch) | |
tree | 6adec7f9487d6af68091139a0f93c260cd54c869 /src/backend/utils/init/miscinit.c | |
parent | e733510d5d67a0b4fb1a9228df598034e487f194 (diff) | |
download | postgresql-15ce2d2e4a3e9ae70801a5caa07579200a66b510.tar.gz postgresql-15ce2d2e4a3e9ae70801a5caa07579200a66b510.zip |
> I can see a couple possible downsides: (a) the library might have some
> weird behavior across fork boundaries; (b) the additional memory space
> that has to be duplicated into child processes will cost something per
> child launch, even if the child never uses it. But these are only
> arguments that it might not *always* be a prudent thing to do, not that
> we shouldn't give the DBA the tool to do it if he wants. So fire away.
Here is a patch for the above, including a documentation update. It
creates a new GUC variable "preload_libraries", that accepts a list in
the form:
preload_libraries = '$libdir/mylib1:initfunc,$libdir/mylib2'
If ":initfunc" is omitted or not found, no initialization function is
executed, but the library is still preloaded. If "$libdir/mylib" isn't
found, the postmaster refuses to start.
In my testing with PL/R, it reduces the first call to a PL/R function
(after connecting) from almost 2 seconds, down to about 8 ms.
Joe Conway
Diffstat (limited to 'src/backend/utils/init/miscinit.c')
-rw-r--r-- | src/backend/utils/init/miscinit.c | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 12154396193..8b49ca2e584 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.100 2003/01/27 00:51:06 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.101 2003/03/20 04:51:44 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1044,3 +1044,92 @@ ValidatePgVersion(const char *path) "which is not compatible with this version %s.", file_major, file_minor, version_string); } + +/*------------------------------------------------------------------------- + * Library preload support + *------------------------------------------------------------------------- + */ + +#if defined(__mc68000__) && defined(__ELF__) +typedef int32 ((*func_ptr) ()); +#else +typedef char *((*func_ptr) ()); +#endif + +/* + * process any libraries that should be preloaded and + * optionally pre-initialized + */ +void +process_preload_libraries(char *preload_libraries_string) +{ + char *rawstring; + List *elemlist; + List *l; + + if (preload_libraries_string == NULL) + return; + + /* Need a modifiable copy of string */ + rawstring = pstrdup(preload_libraries_string); + + /* Parse string into list of identifiers */ + if (!SplitIdentifierString(rawstring, ',', &elemlist)) + { + /* syntax error in list */ + pfree(rawstring); + freeList(elemlist); + elog(LOG, "invalid list syntax for preload_libraries configuration option"); + } + + foreach(l, elemlist) + { + char *tok = (char *) lfirst(l); + char *sep = strstr(tok, ":"); + char *filename = NULL; + char *funcname = NULL; + func_ptr initfunc; + + if (sep) + { + /* + * a colon separator implies there is an initialization function + * that we need to run in addition to loading the library + */ + size_t filename_len = sep - tok; + size_t funcname_len = strlen(tok) - filename_len - 1; + + filename = (char *) palloc(filename_len + 1); + memset(filename, '\0', filename_len + 1); + snprintf(filename, filename_len + 1, "%s", tok); + + funcname = (char *) palloc(funcname_len + 1); + memset(funcname, '\0', funcname_len + 1); + snprintf(funcname, funcname_len + 1, "%s", sep + 1); + } + else + { + /* + * no separator -- just load the library + */ + filename = pstrdup(tok); + funcname = NULL; + } + + initfunc = (func_ptr) load_external_function(filename, funcname, false, NULL); + if (initfunc) + (*initfunc)(); + + elog(LOG, "preloaded library %s with initialization function %s", filename, funcname); + + if (filename != NULL) + pfree(filename); + + if (funcname != NULL) + pfree(funcname); + } + + pfree(rawstring); + freeList(elemlist); +} + |