Exemple #1
0
/* search_cell searches the cache and returns the cached
 * cell if found and returns NULL if the request cell is 
 * not cached. request_line is treated as the key. The 
 * strategy is to lock the cache for reading. reading from
 * the cache is permitted but writing to the cache is not. 
 * In the hit case, the cache is not unlocked until data is
 * writen to client. */
struct cache_cell *search_cell(char *request_line)
{
	struct cache_cell *ptr;
	
	/* locks the cache for reading */
	Pthread_rwlock_rdlock(&cache_lock);
	for (ptr = head; ptr != NULL; ptr = ptr->next)
	{
		if (!strcmp(ptr->request_line, request_line))
		{
			/* locks the mutex in the cell so that 
			 * other threads cannot access this cell. */
			Pthread_rwlock_wrlock(&(ptr->lock));
			Pthread_mutex_lock(&time_mutex);
			ptr->last_use = cache_time;
			cache_time++;
			Pthread_mutex_unlock(&time_mutex);
			Pthread_rwlock_unlock(&(ptr->lock));
			return ptr;
		}
	}
	/* unlocks the cache immediately in miss case */
	Pthread_rwlock_unlock(&cache_lock);
	return NULL;
}
Exemple #2
0
void *thread2(void *arg)
{
		/* 4second child */
	sleep(3);
	printf("%s: second child tries to obtain read lock\n", gf_time());
	Pthread_rwlock_rdlock(&rwlock);
	printf("%s: second child obtains read lock\n", gf_time());

	sleep(4);
	Pthread_rwlock_unlock(&rwlock);
	printf("%s: second child releases read lock\n", gf_time());
	return NULL;
}
Exemple #3
0
/* search_cell_variant searches the cache but does not update*/
int search_cell_variant(char *request_line)
{
	struct cache_cell *ptr;
	
	Pthread_rwlock_rdlock(&cache_lock);
	for (ptr = head; ptr != NULL; ptr = ptr->next)
		if (!strcmp(ptr->request_line, request_line))
		{
			Pthread_rwlock_unlock(&cache_lock);
			return 1;
		}
	Pthread_rwlock_unlock(&cache_lock);
	return 0;
}
Exemple #4
0
/* Search the cache, if hit, copy content to the user buffer */
int search_and_get(Cache_List *cache_list, char *for_uri, void *usrbuf, 
		unsigned int *size) 
{
	Cache_Item *cache_item = NULL;

	Pthread_rwlock_rdlock(&cache_rwlock);	/* Lock for concurrent reading */

	cache_item = search_cache_item(cache_list, for_uri);	/* Reading */
	
	Pthread_rwlock_unlock(&cache_rwlock);	/* Unlocked reading */

	/* During this small transition period after releasing the reading lock 
	 * but before acquiring the writing lock, it is possible that the cache 
	 * item just found would be evicted by another writter who has been 
	 * waiting in the que. So it needs to be double checked before using. If 
	 * it is evicted, just treat it as a cache-miss.
	 */

	if (cache_item != NULL) {

		Pthread_rwlock_wrlock(&cache_rwlock);	/* Lock for exlusive writing */

		/* Check the item again in case it has been evicted instantaneously */
		if (strcmp(cache_item->uri, for_uri) == 0) {
			/* If it is still there, treat it as a cache-hit and use it */
			use_cache_item(cache_list, cache_item, usrbuf, size);
			print_cache_status(cache_list);

			Pthread_rwlock_unlock(&cache_rwlock);	/* Unlock writing */

			return 0;
		}
		else {
			/* If it is lost, treated it as a cache-miss */

			Pthread_rwlock_unlock(&cache_rwlock);	/* Unlock writing */

			return -1;
		}
	}
	else {
		/* Cache-miss */
		return -1;
	}
}