void *sha_checkout(ShmemArray *array, unsigned int elementNumber) { void *element; if (elementNumber < array->elementCount) { /* read locks block if a write is pending */ #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_checkout(): about to check out %s element %d", array->name, elementNumber); #endif WA_lock(array->elements[elementNumber].writeLock); WA_lock(array->elements[elementNumber].lock); WA_unlock(array->elements[elementNumber].writeLock); element = array->elements[elementNumber].element; /* if this was the first read lock by this process, obtain a file lock on the data as well */ if (array->elements[elementNumber].lockCount == 0) array->elements[elementNumber].lockHandle = WOShmem_lock(element, array->elementSize, 0); array->elements[elementNumber].lockCount++; WA_unlock(array->elements[elementNumber].lock); #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_checkout(): checked out %s element %d", array->name, elementNumber); #endif } else { element = NULL; WOLog(WO_ERR, "sha_checkout(): failed to check out %s element %d", array->name, elementNumber); } return element; }
void sha_unlock(ShmemArray *array, unsigned int elementNumber) { if (elementNumber < array->elementCount) { #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_unlock(): about to unlock %s element %d", array->name, elementNumber); #endif WA_lock(array->elements[elementNumber].lock); /* release the file lock on the data */ WOShmem_unlock(array->elements[elementNumber].lockHandle); array->elements[elementNumber].lockHandle = NULL; WA_unlock(array->elements[elementNumber].lock); WA_unlock(array->elements[elementNumber].writeLock); #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_unlock(): unlocked %s element %d", array->name, elementNumber); #endif } }
void *sha_lock(ShmemArray *array, unsigned int elementNumber) { void *element; if (elementNumber < array->elementCount) { #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_lock(): about to lock %s element %d", array->name, elementNumber); #endif /* block read lock requests */ WA_lock(array->elements[elementNumber].writeLock); WA_lock(array->elements[elementNumber].lock); int maxTry = 10000; while (array->elements[elementNumber].lockCount > 0 && maxTry-- > 0) { WA_unlock(array->elements[elementNumber].lock); WA_yield(); WA_lock(array->elements[elementNumber].lock); } if(array->elements[elementNumber].lockCount <= 0) { element = array->elements[elementNumber].element; array->elements[elementNumber].lockHandle = WOShmem_lock(element, array->elementSize, 1); WA_unlock(array->elements[elementNumber].lock); #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_lock(): locked %s element %d", array->name, elementNumber); #endif } else { WA_unlock(array->elements[elementNumber].lock); WA_unlock(array->elements[elementNumber].writeLock); element = NULL; WOLog(WO_ERR, "sha_lock(): element already locked: %s / %d", array->name, elementNumber); } } else { element = NULL; WOLog(WO_ERR, "sha_lock(): failed to lock %s element %d", array->name, elementNumber); } return element; }
/* * Obtain a lock on a chunk of shared memory. The range of memory * begins add address addr, and is size bytes in length. If exclusive * is zero the lock is a shared lock for read only access to the region. * If exclusive is nonzero the lock is an exclusive lock for write * access to the region. * The return value is a handle which must be supplied to the WOShmem_unlock * function when the lock is released. If some error occurrs and * a lock could not be obtained, NULL is returned. */ void *WOShmem_lock(const void *addr, size_t size, int exclusive) { struct flock *lockInfo; ptrdiff_t offset; LockInfo *info = NULL; if (addr && WOShmem_fd != -1) { offset = addr_to_offset(addr); if (offset >= 0 && offset + size < WOShmem_size) { /* This gets called a lot, so as an optimization to avoid the malloc() overhead */ /* we keep a cache of LockInfo's. */ WA_lock(WOShmem_mutex); info = WOShmem_lockInfoCache; if (info) WOShmem_lockInfoCache = info->cache; WA_unlock(WOShmem_mutex); /* if there wasn't one in the cache, malloc a new one */ if (!info) info = WOMALLOC(sizeof(LockInfo)); if (info) { lockInfo = &info->flockInfo; if (lock_file_section(WOShmem_fd, offset, size, lockInfo, exclusive)) { /* failed; put the info struct back on the cache */ WA_lock(WOShmem_mutex); info->cache = WOShmem_lockInfoCache; WOShmem_lockInfoCache = info; WA_unlock(WOShmem_mutex); info = NULL; } } } } return info; }
static String *tr_uniqueID() { String *uniqueID; char counter_str[9]; int count; uniqueID = str_create(uniqueID_str, 25); WA_lock(tr_lock); count = uniqueID_counter++; WA_unlock(tr_lock); sprintf(counter_str, "%8.8x", count); str_appendLength(uniqueID, counter_str, 8); return uniqueID; }
/* * Only consult the flag (existence of /tmp/logWebObjects) once every * so many log attempts. This reduces the number of stats() to * (hopefully) once per request on average. */ inline static int shouldLog() { #ifdef ALWAYS_LOG return 1; #else static int _shouldLog = 0; static time_t statTime = 0; time_t now; now = time(NULL); WA_lock(logMutex); if (statTime < now) { struct stat statbuf; statTime = now + STATINTERVAL; /* reset timer */ _shouldLog = ( (stat(logFlag,&statbuf) == 0) && (statbuf.st_uid == 0) ); } WA_unlock(logMutex); return _shouldLog; #endif }
void sha_checkin(ShmemArray *array, unsigned int elementNumber) { if (elementNumber < array->elementCount) { #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_checkin(): about to check in %s element %d", array->name, elementNumber); #endif WA_lock(array->elements[elementNumber].lock); array->elements[elementNumber].lockCount--; /* if this was the last read lock by this process, release the file lock on the data as well */ if (array->elements[elementNumber].lockCount == 0) { WOShmem_unlock(array->elements[elementNumber].lockHandle); array->elements[elementNumber].lockHandle = NULL; } WA_unlock(array->elements[elementNumber].lock); #ifdef EXTRA_DEBUGGING_LOGS WOLog(WO_DBG, "sha_checkin(): checked in %s element %d", array->name, elementNumber); #endif } }
/* * Release a lock obtained by WOShmem_lock. handle is the value returned * by WOShmem_lock. */ void WOShmem_unlock(void *handle) { if (handle) { LockInfo *info = (LockInfo *)handle; struct flock *lockInfo = &info->flockInfo; lockInfo->l_type = F_UNLCK; if (fcntl(WOShmem_fd, F_SETLK, lockInfo) == -1) { char *errMsg = WA_errorDescription(WA_error()); WOLog(WO_ERR,"WOShmem_unlock(): failed to unlock %d bytes at 0x%x: %s", lockInfo->l_len, lockInfo->l_start, errMsg); WA_freeErrorDescription(errMsg); /* how should we recover? */ } /* put the info struct back on the cache */ WA_lock(WOShmem_mutex); info->cache = WOShmem_lockInfoCache; WOShmem_lockInfoCache = info; WA_unlock(WOShmem_mutex); } }
void WOLog(int level, const char *format, ...) { FILE *log; va_list ap; int do_it; #if defined(TIMESTAMP_LOG_MESSAGES) struct tm *t; time_t now; char timestamp[64]; #endif if (level < baselevel) return; if (! initialized ) return; do_it = shouldLog(); if ( do_it ) { /* * plenty of people have complained that we need to timestamp * the log entries. the problem is that mktime & friends aren't * reentrant. */ #if defined(TIMESTAMP_LOG_MESSAGES) WA_lock(logMutex); time(&now); t = localtime(&now); strftime(timestamp, sizeof(timestamp), "%d-%b-%Y %T - ", t); WA_unlock(logMutex); #endif log = fopen(logPath, "a+"); if (log != NULL) { #if defined(TIMESTAMP_LOG_MESSAGES) fprintf(log, timestamp); #endif fprintf(log,"%s: ", WOLogLevel[level]); va_start(ap, format); vfprintf(log, format, ap); va_end(ap); fprintf(log,"\n"); fclose(log); } } /* * if the error is serious, include it into the server's log */ #if defined(Netscape) || defined(Apache) || defined(IIS) if (level == WO_ERR) { String *str; str = str_create(NULL, 128); va_start(ap,format); str_vappendf(str, format, ap); va_end(ap); #if defined(Netscape) log_error(0,"WebObjects",NULL,NULL,str->text); #elif defined(Apache) ap_log_error("WebObjects",0, APLOG_ERR, _webobjects_server, str->text); #elif defined(IIS) /* * again, we're stymied because we don't have a ptr to the * server struct * / { LPDWORD len = strlen(logstr); ServerSupportFunction(p->ConnID, HSE_APPEND_LOG_PARAMETER, str->text, &len, (LPDWORD)NULL); } */ #endif str_free(str); } #endif }