// ML: string -> cache ptr_option const cache * apsml_cacheFind (char *cacheName, request_data *rd) /*{{{ */ { // ppGlobalCache(rd); apr_thread_rwlock_rdlock (rd->cachetable->rwlock); const cache *c; // void **c1 = (void **) &c; // ap_log_error(APLOG_MARK, LOG_DEBUG, 0, rd->server, "apsml_cacheFind: cacheName == %s", cacheName); // keyNhash kn; // kn.key = cacheName; // kn.hash = charhashfunction (cacheName); if (cachetable_find (rd->cachetable->ht, cacheName, &c) == hash_DNE) { // ap_log_error(APLOG_MARK, LOG_NOTICE, 0, rd->server, "apsml_cacheFind: cacheName == %s not in main cache", cacheName); c = NULL; } // ap_log_error(APLOG_MARK, LOG_NOTICE, 0, rd->server, "apsml_cacheFind: 2"); apr_thread_rwlock_unlock (rd->cachetable->rwlock); return c; } /*}}} */
static void *APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data) { int exitLoop = 1; while (1) { apr_thread_rwlock_rdlock(rwlock); if (i == MAX_ITER) exitLoop = 0; apr_thread_rwlock_unlock(rwlock); if (!exitLoop) break; apr_thread_rwlock_wrlock(rwlock); if (i != MAX_ITER) { i++; x++; } apr_thread_rwlock_unlock(rwlock); } return NULL; }
SWITCH_DECLARE(switch_status_t) switch_thread_rwlock_rdlock(switch_thread_rwlock_t *rwlock) { return apr_thread_rwlock_rdlock(rwlock); }
int cstat (NXPathCtx_t ctx, char *path, struct stat *buf, unsigned long requestmap, apr_pool_t *p) { apr_pool_t *gPool = (apr_pool_t *)getGlobalPool(); apr_hash_t *statCache = NULL; apr_thread_rwlock_t *rwlock = NULL; NXPathCtx_t pathctx = 0; char *ptr = NULL, *tr; int len = 0, x; char *ppath; char *pinfo; if (ctx == 1) { /* If there isn't a global pool then just stat the file and return */ if (!gPool) { char poolname[50]; if (apr_pool_create(&gPool, NULL) != APR_SUCCESS) { return getstat(ctx, path, buf, requestmap); } setGlobalPool(gPool); apr_pool_tag(gPool, apr_pstrdup(gPool, "cstat_mem_pool")); statCache = apr_hash_make(gPool); apr_pool_userdata_set ((void*)statCache, "STAT_CACHE", stat_cache_cleanup, gPool); apr_thread_rwlock_create(&rwlock, gPool); apr_pool_userdata_set ((void*)rwlock, "STAT_CACHE_LOCK", apr_pool_cleanup_null, gPool); } else { apr_pool_userdata_get((void**)&statCache, "STAT_CACHE", gPool); apr_pool_userdata_get((void**)&rwlock, "STAT_CACHE_LOCK", gPool); } if (!gPool || !statCache || !rwlock) { return getstat(ctx, path, buf, requestmap); } for (x = 0,tr = path;*tr != '\0';tr++,x++) { if (*tr == '\\' || *tr == '/') { ptr = tr; len = x; } if (*tr == ':') { ptr = "\\"; len = x; } } if (ptr) { ppath = apr_pstrndup (p, path, len); strlwr(ppath); if (ptr[1] != '\0') { ptr++; } /* If the path ended in a trailing slash then our result path will be a single slash. To avoid stat'ing the root with a slash, we need to make sure we stat the current directory with a dot */ if (((*ptr == '/') || (*ptr == '\\')) && (*(ptr+1) == '\0')) { pinfo = apr_pstrdup (p, "."); } else { pinfo = apr_pstrdup (p, ptr); } } /* If we have a statCache then try to pull the information from the cache. Otherwise just stat the file and return.*/ if (statCache) { apr_thread_rwlock_rdlock(rwlock); pathctx = (NXPathCtx_t) apr_hash_get(statCache, ppath, APR_HASH_KEY_STRING); apr_thread_rwlock_unlock(rwlock); if (pathctx) { return getstat(pathctx, pinfo, buf, requestmap); } else { int err; err = NXCreatePathContext(0, ppath, 0, NULL, &pathctx); if (!err) { apr_thread_rwlock_wrlock(rwlock); apr_hash_set(statCache, apr_pstrdup(gPool,ppath) , APR_HASH_KEY_STRING, (void*)pathctx); apr_thread_rwlock_unlock(rwlock); return getstat(pathctx, pinfo, buf, requestmap); } } } } return getstat(ctx, path, buf, requestmap); }
static int ip_in_url_test (request_rec *r, apr_sockaddr_t *ip_to_be_test, REMOTE_INFO *p_remote_info, apr_time_t expire_time) { apr_status_t rv; char errmsg_buf[120]; #ifdef DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "cur_time: %lld | last_contact_time:" " %lld | last_update_time: %s | expire_time: %lld", apr_time_now (), p_remote_info->last_contact_time, p_remote_info->last_update_time, expire_time); #endif #if APR_HAS_THREADS if (apr_time_now () - p_remote_info->last_contact_time >= expire_time) { /* the ip-list from url is expired */ rv = apr_thread_rwlock_wrlock (p_remote_info->rwlock); if (rv != APR_SUCCESS) { p_remote_info->last_contact_time = apr_time_now (); apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf)); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to obtain wrlock: %s", errmsg_buf); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to update expired data from remote url," " the ipsubnet-list remains unchanged," " after remote_expire_time next update" " will be invoked by another request"); } else { /* rejudge whether it is necessary to update */ if (apr_time_now () - p_remote_info->last_contact_time >= expire_time) { p_remote_info->last_contact_time = apr_time_now (); if (update_expired_data_from_remote_info (r, p_remote_info) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to update expired data from remote url," " the ipsubnet-list remains unchanged," " after remote_expire_time next update will" " be invoked by another request"); } } rv = apr_thread_rwlock_unlock (p_remote_info->rwlock); if (rv != APR_SUCCESS) { apr_strerror (rv, errmsg_buf, sizeof(errmsg_buf)); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to release wrlock: %s", errmsg_buf); } } } rv = apr_thread_rwlock_rdlock (p_remote_info->rwlock); if (rv != APR_SUCCESS) { apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf)); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to obtain rdlock: %s", errmsg_buf); } /* check if the request's ip is match one of the ipsubnets * getting from url */ int ret = ip_in_ipsubnet_list_test (ip_to_be_test, p_remote_info->p_ipsubnet_list); rv = apr_thread_rwlock_unlock (p_remote_info->rwlock); if (rv != APR_SUCCESS) { apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf)); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to release rdlock: %s", errmsg_buf); } return ret; #else if (apr_time_now () - p_remote_info->last_contact_time >= expire_time) { /* the ip-list from url is expired */ p_remote_info->last_contact_time = apr_time_now (); if (update_expired_data_from_remote_info (r, p_remote_info) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to update expired data from remote url," " the ipsubnet-list remains unchanged," " after remote_expire_time next update will" " be invoked by another request"); } } /* check if the request's ip is match one * of the ipsubnets getting from url */ return ip_in_ipsubnet_list_test (ip_to_be_test, p_remote_info->p_ipsubnet_list); #endif }
static int ip_in_local_file_test (request_rec *r, apr_sockaddr_t *ip_to_be_test, LOCAL_FILE_INFO *p_local_file_info) { apr_status_t rv; char errmsg_buf[120]; #if APR_HAS_THREADS rv = apr_thread_rwlock_wrlock (p_local_file_info->rwlock); if (rv != APR_SUCCESS) { apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf)); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to obtain wrlock: %s", errmsg_buf); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to update from local file, " "the ipsubnet-list remains unchanged," " next update will be invoked by another request"); } else { if (update_expired_data_from_local_file_info (r, p_local_file_info) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to update from local file, " "the ipsubnet-list remains unchanged," " next update will be invoked by another request"); } rv = apr_thread_rwlock_unlock (p_local_file_info->rwlock); if (rv != APR_SUCCESS) { apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf)); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to release wrlock: %s", errmsg_buf); } } rv = apr_thread_rwlock_rdlock (p_local_file_info->rwlock); if (rv != APR_SUCCESS) { apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf)); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to obtain rdlock: %s", errmsg_buf); } /* check if the request's ip is match one of the ipsubnets * getting from local file */ int ret = ip_in_ipsubnet_list_test (ip_to_be_test, p_local_file_info->p_ipsubnet_list); rv = apr_thread_rwlock_unlock (p_local_file_info->rwlock); if (rv != APR_SUCCESS) { apr_strerror (rv, errmsg_buf, sizeof (errmsg_buf)); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to release rdlock: %s", errmsg_buf); } return ret; #else if (update_expired_data_from_local_file_info (r, p_local_file_info) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "fail to update from local file, " "the ipsubnet-list remains unchanged," " next update will be invoked by another request"); } /* check if the request's ip is match one of the * ipsubnets getting from url */ return ip_in_ipsubnet_list_test (ip_to_be_test, p_local_file_info->p_ipsubnet_list); #endif }
// ML : cache * string -> string_ptr String apsml_cacheGet (Region rAddr, cache *c, String key1, request_data *rd) /*{{{ */ { // ap_log_error(APLOG_MARK, LOG_DEBUG, 0, rd->server, "apsml_cacheGet 1"); // ppCache (c, rd); // keyNhash kn; char *key = &(key1->data); // kn.hash = charhashfunction (kn.key); // ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, // "apsml_cacheGet: key == %s, hash: %i", kn.key, kn.hash); int too_old = 0; apr_thread_rwlock_rdlock (c->rwlock); apr_proc_mutex_lock(rd->ctx->cachelock.plock); unsigned long cachehash = c->hashofname % rd->ctx->cachelock.shmsize; unsigned long cacheversion = rd->ctx->cachelock.version[cachehash]; apr_proc_mutex_unlock(rd->ctx->cachelock.plock); // ap_log_error(APLOG_MARK, LOG_DEBUG, 0, rd->server, // "apsml_cacheGet global version: %d, local version %d", cacheversion, c->version); if (cacheversion != c->version) { apr_thread_rwlock_unlock (c->rwlock); apsml_cacheFlush(c, rd, 0); c->version = cacheversion; return (String) NULL; } entry *entry; // void **entry1 = (void **) &entry; if (entrytable_find (c->htable, key, &entry) == hash_DNE) { entry = NULL; // ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, // "apsml_cacheGet: No such thing"); } if (entry) { // we found an entry // which should be put on top of the list // We require locking on the list // If time is too old then drop the entry time_t ct = time (NULL); apr_thread_mutex_lock (c->mutex); LINKEDLIST_REMOVE (entry); //time_t t = ct < entry->time ? 0 : ct - entry->time; if (entry->timeout) { if (ct > entry->time) { // entry too old too_old = 1; /* ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, "apsml_cacheGet: Entry too old, ct == %ld, entry->time == %ld", ct, entry->time); */ LINKEDLIST_INSERTOVER (c->sentinel, entry); } else { // keep entry fresh LINKEDLIST_INSERTUNDER (c->sentinel, entry); // ap_log_error (APLOG_MARK, LOG_NOTICE, 0, rd->server, // "apsml_cacheGet: Entry fine ct == %i, entry->time == %i", // ct, entry->time); cacheheap_heapchangekey(c->heap, entry->heappos, MAX (ct + entry->timeout, entry->time)); //entry->time = MAX (ct + entry->timeout, entry->time); } } else { LINKEDLIST_INSERTUNDER (c->sentinel, entry); } // ap_log_rerror(APLOG_MARK, LOG_NOTICE, 0, rd->request, "apsml_cacheGetFound: etime: %d, rtime: %d, too_old: %i key: %s, value %d, valuedata: %s", entry->time, time(NULL), too_old, key, entry, entry->data); apr_thread_mutex_unlock (c->mutex); } String s; if (too_old == 0 && entry) { s = convertStringToML (rAddr, entry->data); } else { s = (String) NULL; } apr_thread_rwlock_unlock (c->rwlock); // ap_log_rerror(APLOG_MARK, LOG_NOTICE, 0, rd->request, "apsml_cacheGet: Returning"); return s; } /*}}} */