diff options
author | Mohamad Chaarawi <chaarawi@hdfgroup.org> | 2013-05-10 19:38:53 (GMT) |
---|---|---|
committer | Mohamad Chaarawi <chaarawi@hdfgroup.org> | 2013-05-10 19:38:53 (GMT) |
commit | 68a20c3f56f30e62e062eba2f4c8f782fa604cd3 (patch) | |
tree | db86db14954362b093891cf311ce514cf87fe051 /src/H5PL.c | |
parent | 0a3191e36d4ee22c383de9b0917990149c1f2df2 (diff) | |
parent | 5ecebe5b9bc161153a3391bf32eb64687f675172 (diff) | |
download | hdf5-68a20c3f56f30e62e062eba2f4c8f782fa604cd3.zip hdf5-68a20c3f56f30e62e062eba2f4c8f782fa604cd3.tar.gz hdf5-68a20c3f56f30e62e062eba2f4c8f782fa604cd3.tar.bz2 |
[svn-r23694] merge from trunk
Diffstat (limited to 'src/H5PL.c')
-rw-r--r-- | src/H5PL.c | 661 |
1 files changed, 661 insertions, 0 deletions
diff --git a/src/H5PL.c b/src/H5PL.c new file mode 100644 index 0000000..07e90af --- /dev/null +++ b/src/H5PL.c @@ -0,0 +1,661 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic document set and is * + * linked from the top-level documents page. It can also be found at * + * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have access * + * to either file, you may request a copy from help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/****************/ +/* Module Setup */ +/****************/ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5PL__init_interface + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5PLprivate.h" /* Plugin */ +#include "H5Zprivate.h" /* Filter pipeline */ + + +/****************/ +/* Local Macros */ +/****************/ + +#define H5PL_MAX_PATH_NUM 16 + +/****************************/ +/* Macros for supporting + * both Windows and Unix */ +/****************************/ +/* Windows support */ +#ifdef H5_HAVE_WIN32_API + +#define H5PL_DEFAULT_PATH "%ALLUSERSPROFILE%/hdf5/lib/plugin" +#define H5PL_PATH_SEPARATOR ";" + +/* Handle for dynamic library */ +#define H5PL_HANDLE HINSTANCE + +/* Get a handle to a plugin library. Windows: TEXT macro handles Unicode strings */ +#define H5PL_OPEN_DLIB(S) LoadLibraryEx(TEXT(S), NULL, LOAD_WITH_ALTERED_SEARCH_PATH) + +/* Get the address of a symbol in dynamic library */ +#define H5PL_GET_LIB_FUNC(H,N) GetProcAddress(H,N) + +/* Close dynamic library */ +#define H5PL_CLOSE_LIB(H) FreeLibrary(H) + +/* Clear error - nothing to do */ +#define H5PL_CLR_ERROR + +typedef const void *(__cdecl *H5PL_get_plugin_info_t)(void); + +/* Unix support */ +#else /* H5_HAVE_WIN32_API */ + +#define H5PL_DEFAULT_PATH "/usr/local/hdf5/lib/plugin" +#define H5PL_PATH_SEPARATOR ":" + +/* Handle for dynamic library */ +#define H5PL_HANDLE void * + +/* Get a handle to a plugin library. Windows: TEXT macro handles Unicode strings */ +#define H5PL_OPEN_DLIB(S) dlopen(S, RTLD_NOW) + +/* Get the address of a symbol in dynamic library */ +#define H5PL_GET_LIB_FUNC(H,N) dlsym(H,N) + +/* Close dynamic library */ +#define H5PL_CLOSE_LIB(H) dlclose(H) + +/* Clear error */ +#define H5PL_CLR_ERROR dlerror() + +typedef const void *(*H5PL_get_plugin_info_t)(void); +#endif /* H5_HAVE_WIN32_API */ + +/* Special symbol to indicate no plugin loading */ +#define H5PL_NO_PLUGIN "::" + +/******************/ +/* Local Typedefs */ +/******************/ + +/* Type for the list of info for opened plugin libraries */ +typedef struct H5PL_table_t { + H5PL_type_t pl_type; /* plugin type */ + int pl_id; /* ID for the plugin */ + H5PL_HANDLE handle; /* plugin handle */ +} H5PL_table_t; + + +/********************/ +/* Local Prototypes */ +/********************/ + +static herr_t H5PL__init_path_table(void); +static htri_t H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, const void **info); +static htri_t H5PL__open(H5PL_type_t pl_type, char *libname, int plugin_id, const void **pl_info); +static htri_t H5PL__search_table(H5PL_type_t plugin_type, int type_id, const void **info); +static herr_t H5PL__close(H5PL_HANDLE handle); + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Table for opened plugin libraries */ +static size_t H5PL_table_alloc_g = 0; +static size_t H5PL_table_used_g = 0; +static H5PL_table_t *H5PL_table_g = NULL; + +/* Table of location paths for plugin libraries */ +static char *H5PL_path_table_g[H5PL_MAX_PATH_NUM]; +static size_t H5PL_num_paths_g = 0; +static hbool_t H5PL_path_found_g = FALSE; + +/* Whether to preload pathnames for plugin libraries */ +static hbool_t H5PL_no_plugin_g = FALSE; + + +/*-------------------------------------------------------------------------- +NAME + H5PL__init_interface -- Initialize interface-specific information +USAGE + herr_t H5PL__init_interface() +RETURNS + Non-negative on success/Negative on failure +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t +H5PL__init_interface(void) +{ + char *preload_path; + + FUNC_ENTER_STATIC_NOERR + + /* Retrieve pathnames from HDF5_PLUGIN_PRELOAD if the user sets it + * to tell the library to load plugin libraries without search. + */ + if(NULL != (preload_path = HDgetenv("HDF5_PLUGIN_PRELOAD"))) { + /* Special symbal "::" means no plugin during data reading. */ + if(!HDstrcmp(preload_path, H5PL_NO_PLUGIN)) + H5PL_no_plugin_g = TRUE; + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5PL__init_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5PL_no_plugin + * + * Purpose: Quick way for filter module to query whether to load plugin + * + * Return: TRUE: No plugin loading during data reading + * + * FALSE: Load plugin during data reading + * + * Programmer: Raymond Lu + * 20 February 2013 + * + *------------------------------------------------------------------------- + */ +htri_t +H5PL_no_plugin(void) +{ + htri_t ret_value; + + FUNC_ENTER_NOAPI(FAIL) + + ret_value = (htri_t)H5PL_no_plugin_g; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL_no_plugin() */ + + +/*------------------------------------------------------------------------- + * Function: H5PL_term_interface + * + * Purpose: Terminate the H5PL interface: release all memory, reset all + * global variables to initial values. This only happens if all + * types have been destroyed from other interfaces. + * + * Return: Success: Positive if any action was taken that might + * affect some other interface; zero otherwise. + * + * Failure: Negative. + * + * Programmer: Raymond Lu + * 20 February 2013 + * + *------------------------------------------------------------------------- + */ +int +H5PL_term_interface(void) +{ + int i = 0; + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + if(H5_interface_initialize_g) { + size_t u; /* Local index variable */ + + /* Close opened dynamic libraries */ + for(u = 0; u < H5PL_table_used_g; u++) + H5PL__close((H5PL_table_g[u]).handle); + + /* Free the table of dynamic libraries */ + H5PL_table_g = (H5PL_table_t *)H5MM_xfree(H5PL_table_g); + H5PL_table_used_g = H5PL_table_alloc_g = 0; + + /* Free the table of search paths */ + for(u = 0; u < H5PL_num_paths_g; u++) + if(H5PL_path_table_g[u]) + H5PL_path_table_g[u] = (char *)H5MM_xfree(H5PL_path_table_g[u]); + H5PL_num_paths_g = 0; + H5PL_path_found_g = FALSE; + + H5_interface_initialize_g = 0; + i = 1; + } /* end if */ + + FUNC_LEAVE_NOAPI(i) +} /* end H5PL_term_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5PL_load + * + * Purpose: Given the plugin type and identifier, this function searches + * and/or loads a dynamic plugin library first among the already + * opened libraries then in the designated location paths. + * + * Return: Non-NULL on success/NULL on failure + * + * Programmer: Raymond Lu + * 13 February 2013 + * + *------------------------------------------------------------------------- + */ +const void * +H5PL_load(H5PL_type_t type, int id) +{ + htri_t found; /* Whether the plugin was found */ + const void *plugin_info = NULL; + const void *ret_value = NULL; + + FUNC_ENTER_NOAPI(NULL) + + /* Initialize the location paths for dynamic libraries, if they aren't + * already set up. + */ + if(FALSE == H5PL_path_found_g) + if(H5PL__init_path_table() < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTINIT, NULL, "can't initialize search path table") + + /* Search in the table of already loaded plugin libraries */ + if((found = H5PL__search_table(type, id, &plugin_info)) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in table failed") + + /* If not found, iterate through the path table to find the right dynamic library */ + if(!found) { + size_t i; /* Local index variable */ + + for(i = 0; i < H5PL_num_paths_g; i++) { + if((found = H5PL__find(type, id, H5PL_path_table_g[i], &plugin_info)) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, NULL, "search in paths failed") + + /* Break out if found */ + if(found) { + HDassert(plugin_info); + break; + } /* end if */ + } /* end for */ + } /* end if */ + + /* Check if we found the plugin */ + if(found) + ret_value = plugin_info; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL_load() */ + + +/*------------------------------------------------------------------------- + * Function: H5PL__init_path_table + * + * Purpose: Initialize the path table. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * 18 March 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5PL__init_path_table(void) +{ + char *dl_path = NULL; + char *origin_dl_path; + char *dir; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Retrieve paths from HDF5_PLUGIN_PATH if the user sets it + * or from the default paths if it isn't set. + */ + origin_dl_path = HDgetenv("HDF5_PLUGIN_PATH"); + if(NULL == origin_dl_path) + dl_path = HDstrdup(H5PL_DEFAULT_PATH); + else + dl_path = HDstrdup(origin_dl_path); + if(NULL == dl_path) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path") + + /* Put paths in the path table. They are separated by ":" */ + dir = HDstrtok(dl_path, H5PL_PATH_SEPARATOR); + while(dir) { + /* Check for too many directories in path */ + if(H5PL_num_paths_g == H5PL_MAX_PATH_NUM) + HGOTO_ERROR(H5E_PLUGIN, H5E_NOSPACE, FAIL, "too many directories in path for table") + if(NULL == (H5PL_path_table_g[H5PL_num_paths_g] = HDstrdup(dir))) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path") + H5PL_num_paths_g++; + dir = HDstrtok(NULL, H5PL_PATH_SEPARATOR); + } /* end while */ + + H5PL_path_found_g = TRUE; + +done: + if(dl_path) + dl_path = (char *)H5MM_xfree(dl_path); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL__init_path_table() */ + + +/*------------------------------------------------------------------------- + * Function: H5PL__find + * + * Purpose: Given a path, this function opens the directory and envokes + * another function to go through all files to find the right + * plugin library. Two function definitions are for Unix and + * Windows. + * + * Return: TRUE on success, + * FALSE on not found, + * negative on failure + * + * Programmer: Raymond Lu + * 13 February 2013 + * + *------------------------------------------------------------------------- + */ +#ifndef H5_HAVE_WIN32_API +static htri_t +H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, const void **info) +{ + char *pathname = NULL; + DIR *dirp = NULL; + struct dirent *dp; + htri_t ret_value = FALSE; + + FUNC_ENTER_STATIC + + /* Open the directory */ + if(!(dirp = HDopendir(dir))) + HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory") + + /* Iterates through all entries in the directory to find the right plugin library */ + while(NULL != (dp = HDreaddir(dirp))) { + /* The library we are looking for should be called libxxx.so... on Unix + * or libxxx.xxx.dylib on Mac. + */ + if(!HDstrncmp(dp->d_name, "lib", (size_t)3) && + (HDstrstr(dp->d_name, ".so") || HDstrstr(dp->d_name, ".dylib"))) { + h5_stat_t my_stat; + size_t pathname_len; + htri_t found_in_dir; + + /* Allocate & initialize the path name */ + pathname_len = HDstrlen(dir) + HDstrlen(dp->d_name) + 2; + if(NULL == (pathname = (char *)H5MM_malloc(pathname_len))) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path") + HDsnprintf(pathname, pathname_len, "%s/%s", dir, dp->d_name); + + /* Get info for directory entry */ + if(HDstat(pathname, &my_stat) == -1) + HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't stat file: %s", strerror(errno)) + + /* If it is a directory, skip it */ + if(S_ISDIR(my_stat.st_mode)) + continue; + + /* Attempt to open the dynamic library as a filter library */ + if((found_in_dir = H5PL__open(plugin_type, pathname, type_id, info)) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed") + if(found_in_dir) { + /* Indicate success */ + HGOTO_DONE(TRUE) + } /* end if */ + else + HDassert(pathname); + pathname = (char *)H5MM_xfree(pathname); + } /* end if */ + } /* end while */ + +done: + if(dirp) + if(HDclosedir(dirp) < 0) + HDONE_ERROR(H5E_FILE, H5E_CLOSEERROR, FAIL, "can't close directory: %s", strerror(errno)) + if(pathname) + pathname = (char *)H5MM_xfree(pathname); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL__find() */ +#else /* H5_HAVE_WIN32_API */ +static htri_t +H5PL__find(H5PL_type_t plugin_type, int type_id, char *dir, const void **info) +{ + WIN32_FIND_DATA fdFile; + HANDLE hFind; + char *pathname = NULL; + char service[2048]; + htri_t ret_value = FALSE; + + FUNC_ENTER_STATIC + + /* Specify a file mask. *.* = We want everything! */ + sprintf(service, "%s\/*.dll", dir); + if((hFind = FindFirstFile(service, &fdFile)) == INVALID_HANDLE_VALUE) + HGOTO_ERROR(H5E_PLUGIN, H5E_OPENERROR, FAIL, "can't open directory") + + do { + /* Find first file will always return "." + * and ".." as the first two directories. + */ + if(HDstrcmp(fdFile.cFileName, ".") != 0 && HDstrcmp(fdFile.cFileName, "..") != 0) { + size_t pathname_len; + htri_t found_in_dir; + + /* Allocate & initialize the path name */ + pathname_len = HDstrlen(dir) + HDstrlen(fdFile.cFileName) + 2; + if(NULL == (pathname = (char *)H5MM_malloc(pathname_len))) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTALLOC, FAIL, "can't allocate memory for path") + HDsnprintf(pathname, pathname_len, "%s\\%s", dir, fdFile.cFileName); + + /* Is the entity a File or Folder? */ + if(fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + if((found_in_dir = H5PL__open(plugin_type, pathname, type_id, info)) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "search in directory failed") + if(found_in_dir) { + /* Indicate success */ + HGOTO_DONE(TRUE) + } /* end if */ + else + HDassert(pathname); + pathname = (char *)H5MM_xfree(pathname); + } /* end if */ + } while(FindNextFile(hFind, &fdFile)); /* Find the next file. */ + +done: + if(hFind) + FindClose(hFind); + if(pathname) + pathname = (char *)H5MM_xfree(pathname); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL__find() */ +#endif /* H5_HAVE_WIN32_API */ + + +/*------------------------------------------------------------------------- + * Function: H5PL__open + * + * Purpose: Iterates through all files to find the right plugin library. + * It loads the dynamic plugin library and keeps it on the list + * of loaded libraries. + * + * Return: TRUE on success, + * FALSE on not found, + * negative on failure + * + * Programmer: Raymond Lu + * 13 February 2013 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5PL__open(H5PL_type_t pl_type, char *libname, int pl_id, const void **pl_info) +{ + H5PL_HANDLE handle = NULL; + htri_t ret_value = FALSE; + + FUNC_ENTER_STATIC + + /* There are different reasons why a library can't be open, e.g. wrong architecture. + * simply continue if we can't open it. + */ + if(NULL == (handle = H5PL_OPEN_DLIB(libname))) { + H5PL_CLR_ERROR; /* clear error */ + } /* end if */ + else { + H5PL_get_plugin_info_t get_plugin_info = NULL; + + /* Return a handle for the function H5PLget_plugin_info in the dynamic library. + * The plugin library is suppose to define this function. + */ + if(NULL == (get_plugin_info = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC(handle, "H5PLget_plugin_info"))) { + if(H5PL__close(handle) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library") + } /* end if */ + else { + const H5Z_class2_t *plugin_info; + + /* Invoke H5PLget_plugin_info to verify this is the right library we are looking for. + * Move on if it isn't. + */ + if(NULL == (plugin_info = (const H5Z_class2_t *)(*get_plugin_info)())) { + if(H5PL__close(handle) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library") + HGOTO_ERROR(H5E_PLUGIN, H5E_CANTGET, FAIL, "can't get plugin info") + } /* end if */ + + /* Successfully found plugin library, check if it's the right one */ + if(plugin_info->id == pl_id) { + /* Expand the table if it is too small */ + if(H5PL_table_used_g >= H5PL_table_alloc_g) { + size_t n = MAX(H5Z_MAX_NFILTERS, 2 * H5PL_table_alloc_g); + H5PL_table_t *table = (H5PL_table_t *)H5MM_realloc(H5PL_table_g, n * sizeof(H5PL_table_t)); + + if(!table) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "unable to extend dynamic library table") + + H5PL_table_g = table; + H5PL_table_alloc_g = n; + } /* end if */ + + (H5PL_table_g[H5PL_table_used_g]).handle = handle; + (H5PL_table_g[H5PL_table_used_g]).pl_type = pl_type; + (H5PL_table_g[H5PL_table_used_g]).pl_id = plugin_info->id; + H5PL_table_used_g++; + + /* Set the plugin info to return */ + *pl_info = (const void *)plugin_info; + + /* Indicate success */ + ret_value = TRUE; + } /* end if */ + else + if(H5PL__close(handle) < 0) + HGOTO_ERROR(H5E_PLUGIN, H5E_CLOSEERROR, FAIL, "can't close dynamic library") + } /* end if */ + } /* end else */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL__open() */ + + +/*------------------------------------------------------------------------- + * Function: H5PL__search_table + * + * Purpose: Search in the list of already opened dynamic libraries + * to see if the one we are looking for is already opened. + * + * Return: TRUE on success, + * FALSE on not found, + * Negative on failure + * + * Programmer: Raymond Lu + * 13 February 2013 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5PL__search_table(H5PL_type_t plugin_type, int type_id, const void **info) +{ + htri_t ret_value = FALSE; + + FUNC_ENTER_STATIC + + /* Search in the table of already opened dynamic libraries */ + if(H5PL_table_used_g > 0) { + size_t i; + + for(i = 0; i < H5PL_table_used_g; i++) { + if((plugin_type == (H5PL_table_g[i]).pl_type) && (type_id == (H5PL_table_g[i]).pl_id)) { + H5PL_get_plugin_info_t get_plugin_info; + const H5Z_class2_t *plugin_info; + + if(NULL == (get_plugin_info = (H5PL_get_plugin_info_t)H5PL_GET_LIB_FUNC((H5PL_table_g[i]).handle, "H5PLget_plugin_info"))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get function for H5PLget_plugin_info") + + if(NULL == (plugin_info = (const H5Z_class2_t *)(*get_plugin_info)())) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get plugin info") + + *info = plugin_info; + HGOTO_DONE(TRUE) + } /* end if */ + } /* end for */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5PL__search_table() */ + + +/*------------------------------------------------------------------------- + * Function: H5PL__close + * + * Purpose: Closes the handle for dynamic library + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Raymond Lu + * 13 February 2013 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5PL__close(H5PL_HANDLE handle) +{ + FUNC_ENTER_STATIC_NOERR + + H5PL_CLOSE_LIB(handle); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5PL__close() */ + |