1/* 2 * ==================================================================== 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * ==================================================================== 20 */ 21 22#include <apr_thread_mutex.h> 23#include <apr_hash.h> 24 25#include "svn_hash.h" 26#include "svn_dso.h" 27#include "svn_pools.h" 28#include "svn_private_config.h" 29 30#include "private/svn_mutex.h" 31 32/* A mutex to protect our global pool and cache. */ 33static svn_mutex__t *dso_mutex = NULL; 34 35/* Global pool to allocate DSOs in. */ 36static apr_pool_t *dso_pool; 37 38/* Global cache for storing DSO objects. */ 39static apr_hash_t *dso_cache; 40 41/* Just an arbitrary location in memory... */ 42static int not_there_sentinel; 43 44/* A specific value we store in the dso_cache to indicate that the 45 library wasn't found. This keeps us from allocating extra memory 46 from dso_pool when trying to find libraries we already know aren't 47 there. */ 48#define NOT_THERE ((void *) ¬_there_sentinel) 49 50svn_error_t * 51svn_dso_initialize2(void) 52{ 53 if (dso_pool) 54 return SVN_NO_ERROR; 55 56 dso_pool = svn_pool_create(NULL); 57 58 SVN_ERR(svn_mutex__init(&dso_mutex, TRUE, dso_pool)); 59 60 dso_cache = apr_hash_make(dso_pool); 61 return SVN_NO_ERROR; 62} 63 64#if APR_HAS_DSO 65static svn_error_t * 66svn_dso_load_internal(apr_dso_handle_t **dso, const char *fname) 67{ 68 *dso = svn_hash_gets(dso_cache, fname); 69 70 /* First check to see if we've been through this before... We do this 71 to avoid calling apr_dso_load multiple times for a given library, 72 which would result in wasting small amounts of memory each time. */ 73 if (*dso == NOT_THERE) 74 { 75 *dso = NULL; 76 return SVN_NO_ERROR; 77 } 78 79 /* If we got nothing back from the cache, try and load the library. */ 80 if (! *dso) 81 { 82 apr_status_t status = apr_dso_load(dso, fname, dso_pool); 83 if (status) 84 { 85#ifdef SVN_DEBUG_DSO 86 char buf[1024]; 87 fprintf(stderr, 88 "Dynamic loading of '%s' failed with the following error:\n%s\n", 89 fname, 90 apr_dso_error(*dso, buf, 1024)); 91#endif 92 *dso = NULL; 93 94 /* It wasn't found, so set the special "we didn't find it" value. */ 95 svn_hash_sets(dso_cache, apr_pstrdup(dso_pool, fname), NOT_THERE); 96 97 return SVN_NO_ERROR; 98 } 99 100 /* Stash the dso so we can use it next time. */ 101 svn_hash_sets(dso_cache, apr_pstrdup(dso_pool, fname), *dso); 102 } 103 104 return SVN_NO_ERROR; 105} 106 107svn_error_t * 108svn_dso_load(apr_dso_handle_t **dso, const char *fname) 109{ 110 if (! dso_pool) 111 SVN_ERR(svn_dso_initialize2()); 112 113 SVN_MUTEX__WITH_LOCK(dso_mutex, svn_dso_load_internal(dso, fname)); 114 115 return SVN_NO_ERROR; 116} 117#endif /* APR_HAS_DSO */ 118