コード例 #1
0
ファイル: lru.c プロジェクト: ql2723/cs6210
int gtcache_set(char *key, void *value, size_t val_size){
  struct timeval *time;
  cache_entry_t *victim;
  int id, *idp;

  /* Determine if we can add this to the cache without evicting */
  while (need_eviction(val_size)) {
    /* Evict based on LFU policy */
    if (!indexminpq_isempty(&id_by_time_pq)) {
      id = indexminpq_minindex(&id_by_time_pq);
      time = indexminpq_keyof(&id_by_time_pq, id);

      indexminpq_delmin(&id_by_time_pq);
      victim = &cache.entries[id];

      idp = (int *) hshtbl_get(&url_to_id_tbl, victim->url);
      hshtbl_delete(&url_to_id_tbl, victim->url);
      steque_push(&free_ids, id);

      free(idp);
      free(time);

      cache.mem_used -= victim->size;
      cache.num_entries--;
      free(victim->data);
      free(victim->url);
      victim->size = 0;
    } else {
      /* the val size is bigger than the total cache available memory */
      return 0;
    }
  }

  /* Get next free ID */
  id = (int) steque_pop(&free_ids);
  idp = malloc(sizeof(int));
  *idp = id;

  /* Allocate memory for new entry */
  cache.entries[id].size = val_size;
  cache.entries[id].data = (char *) malloc(val_size);
  cache.entries[id].url = (char *) malloc(strlen(key));
  cache.mem_used += val_size;
  cache.num_entries++;

  /* Add to cache */
  memcpy(cache.entries[id].data, value, val_size);
  strcpy(cache.entries[id].url, key); // FIXME: Should probably use strncpy for safety

  /* Create hash table mapping */
  hshtbl_put(&url_to_id_tbl, cache.entries[id].url, (hshtbl_item) idp);

  time = (struct timeval *) malloc(sizeof(struct timeval));
  gettimeofday(time, NULL);

  /* Add ID to minpq */
  indexminpq_insert(&id_by_time_pq, id, (void *) time);

  return 1;
}
コード例 #2
0
ファイル: lru.c プロジェクト: ql2723/cs6210
int gtcache_init(size_t capacity, size_t min_entry_size, int num_levels){
  int i;

  /* Initialize cache metadata */
  cache.max_entries = capacity / min_entry_size;
  cache.num_entries = 0;
  cache.mem_used = 0;
  cache.capacity = capacity;
  cache.min_entry_size = min_entry_size;

  /* Initialize cache */
  cache.entries = malloc(cache.max_entries * sizeof(cache_entry_t));
  for (i = 0; i < cache.max_entries; i++) {
    cache.entries[i].data = NULL;
    cache.entries[i].url = NULL;
    cache.entries[i].size = 0;
  }

  /* Initialize other data structures */
  /* Hash table should be at least twice the size of expected number of entries */
  hshtbl_init(&url_to_id_tbl, cache.max_entries * 2);
  indexminpq_init(&id_by_time_pq, cache.max_entries, keycmp);
  steque_init(&free_ids);

  /* Populate free_ids */
  for (i = cache.max_entries - 1; i >= 0; i--) {
    steque_push(&free_ids, i);
  }

  return 1;
}
コード例 #3
0
ファイル: webproxy.c プロジェクト: rohan-kekatpure/courses
/* main */
int main(int argc, char **argv) {
    int option_char = 0;
    unsigned short port = 8888;
    unsigned short nworkerthreads = 1;
    char *server = "s3.amazonaws.com/content.udacity-data.com";
    size_t shm_segsize = 4 * KBYTE;
    fprintf(stderr, "server = %s\n", server);

    if (signal(SIGINT, _sig_handler) == SIG_ERR){
        fprintf(stderr,"Can't catch SIGINT...exiting.\n");
        exit(EXIT_FAILURE);
    }

    if (signal(SIGTERM, _sig_handler) == SIG_ERR){
        fprintf(stderr,"Can't catch SIGTERM...exiting.\n");
        exit(EXIT_FAILURE);
    }

    /* Parse and set command line arguments */
    while ((option_char = getopt_long(argc, argv, "p:t:s:z:n:h", gLongOptions, NULL)) != -1) {
        switch (option_char) {
            case 'p': // listen-port
              port = atoi(optarg);
                break;
            case 't': // thread-count
                nworkerthreads = atoi(optarg);
                break;
            case 's': // file-path
                server = optarg;
                break;
            case 'z': // shm segment size
                shm_segsize = atoi(optarg);
                break;
            case 'n': // shm segment count 
                shm_segcount = atoi(optarg);
                break;                                                                          
            case 'h': // help
                fprintf(stdout, "%s", USAGE);
                exit(0);
                break;       
            default:
                fprintf(stderr, "%s", USAGE);
                exit(1);
        }
    }
  
    /* Initialize steque to hold shm segment ids */
    steque_init(&shm_segnum_queue);

    /* SHM initialization...*/
    /* Initially spawn 100 threads */    
    long shm_segnum;
    int shm_fd;
    char shm_segid[SEGID_LEN];

    /* total size of shared memory segment is size of the struct + requested segment size */    
    size_t shm_blocksize = sizeof(Shm_Block) + shm_segsize;
    printf("shm_blocksize = %zu\n", shm_blocksize);

    for (shm_segnum = 0; shm_segnum < shm_segcount; shm_segnum++) {
        sprintf(shm_segid, "/%ld", shm_segnum);

        /* Steps to create SHM segment id */  

        /* Delete previous shm instance of same name */
        if (shm_unlink(shm_segid) == -1) {
            //warn("main", "No previous shared memory instance found");
        }

        /* Create file descritor */
        shm_fd = shm_open(shm_segid, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
        if (shm_fd == -1) {
            err_exit("webproxy", "shm_open", errno);
        }

        /* adjust the memory region to size of shmbuf */
        if (ftruncate(shm_fd, shm_blocksize) == -1) {
            err_exit("main", "ftruncate", errno);
        }
        
        /* map the memory */
        Shm_Block *shmb_p;
        shmb_p = mmap(NULL, shm_blocksize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
        if (shmb_p == MAP_FAILED) {
            err_exit("main", "mmap failed", errno);
        }

        /* Push the segnum into the queue; because steque performs 
        only a shallow copy, we need to push elemental types, not 
        pointers. */
        steque_push(&shm_segnum_queue, (steque_item)shm_segnum);

        /* close the SHM file descriptors, they're no longer needed */   
        close(shm_fd);
    }

    /* Set up message queue attrs */
    struct mq_attr attr;
    attr.mq_maxmsg = MQ_MAXMSG;
    attr.mq_msgsize = MQ_MSGSIZE;

    /* Open message mqueue with specified attributes */
    mqd = mq_open(mq_name, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR, &attr);
    if (mqd == (mqd_t) -1){
        strerr_exit("webproxy, mq_open", errno);
    }
    
    /* Initialize mutex and cv to protect segqueue*/
    pthread_mutex_init(&sq_mtx, NULL);
    pthread_cond_init(&sq_notempty, NULL);

    /* Initializing server */
    gfserver_init(&gfs, nworkerthreads);

    /* Setting options */
    gfserver_setopt(&gfs, GFS_PORT, port);
    gfserver_setopt(&gfs, GFS_MAXNPENDING, 10);
    gfserver_setopt(&gfs, GFS_WORKER_FUNC, handle_with_cache);

    /* Spawn threads */
    num_writers = 0;
    num_readers = nworkerthreads;

    long *th_ids = (long *) malloc(nworkerthreads * sizeof(long)); 
    int i;
    for(i = 0; i < nworkerthreads; i++) {
        th_ids[i] = i;
        // fprintf(stderr, "Assigning thread id %ld\n", th_ids[i]);

        /* Construct workload context to pass on to the handler */
        Workload wld;
        wld.shm_blocksize = shm_blocksize;
        wld.mqd = mqd;                      /* populate mq file desc */
        wld.segqueue = &shm_segnum_queue;   /* populate segment queue id */
        wld.sq_mtx_p = &sq_mtx;             /* populate the mutex */
        wld.sq_notempty_p = &sq_notempty; /* populate cv */

        gfserver_setopt(&gfs, GFS_WORKER_ARG, i, &wld);
    }

    free(th_ids);
    /* Loops forever */
    gfserver_serve(&gfs);

}
コード例 #4
0
ssize_t handle_with_cache(gfcontext_t *ctx, char *path, void* arg)
{
	mqd_t msg_q;
	void *mem;
	struct request_info *req;
	struct shm_info *shm_blk;
	sem_t *sem1;
	sem_t *sem2;
	int file_in_cache;
	size_t file_size = 0;
	size_t bytes_transferred = 0;
	ssize_t write_len;
	size_t cache_file_size;

	pthread_mutex_lock(seg_q_mutex);
	while (steque_isempty(seg_q)) {
		pthread_cond_wait(seg_q_cond, seg_q_mutex);
	}
	shm_blk = (struct shm_info *)steque_pop(seg_q);
	pthread_mutex_unlock(seg_q_mutex);

	if ((sem1 = sem_open(shm_blk->sem1_name, O_CREAT, 0644, 0)) ==
	    SEM_FAILED) {
		perror("sem_open");
		return -1;
    	}
    	if ((sem2 = sem_open(shm_blk->sem2_name, O_CREAT, 0644, 0)) ==
	    SEM_FAILED) {
		perror("sem_open");
		return -1;
    	}
retry:
	errno = 0;
	msg_q = mq_open(QUEUE_NAME, O_WRONLY);
	if (msg_q == -1) {
		if (errno == ENOENT || errno == EACCES) {
			/* simplecached isn't ready yet, sleep and then retry */
			fprintf(stdout, "waiting for simplecached\n");
			sleep(2);
			goto retry;
		}
		perror("mq_open");
		return -1;
	}

	mem = mmap(NULL, seg_size, PROT_READ | PROT_WRITE, MAP_SHARED,
	    shm_blk->memfd, 0);
	if (!mem) {
		perror("mmap");
		return -1;
	}
	req = malloc(sizeof(*req) + strlen(path) + 1);
	memcpy(&req->mem_i, (char *)shm_blk + sizeof(int), sizeof(req->mem_i));
	req->mem_size = seg_size;
	req->file_len = strlen(path) + 1;
	strncpy(req->file_path, path, strlen(path));
	req->file_path[strlen(path)] = '\0';
	mq_send(msg_q, (char *)req, sizeof(*req) + strlen(path) + 1, 0);
	free(req);

	sem_wait(sem1);
	file_in_cache = *(int *)mem;
	sem_post(sem1);

	if (file_in_cache == -1) {
		 gfs_sendheader(ctx, GF_FILE_NOT_FOUND, 0);
		 goto finish;
	}
	sem_wait(sem1);
	file_size = *(size_t *)mem;
	cache_file_size = file_size;
	gfs_sendheader(ctx, GF_OK, file_size);
	sem_post(sem1);
	if (!file_size) {
		goto finish;
	}
	while (file_size) {
		sem_wait(sem1);
		bytes_transferred =  seg_size < file_size ?
		    seg_size : file_size;
		write_len = gfs_send(ctx, (char *)mem, bytes_transferred);
		if (write_len != bytes_transferred) {
			fprintf(stderr, "write error");
		}
		file_size -= bytes_transferred;
		sem_post(sem1);
	}
	sem_wait(sem1);
	file_size = *(size_t *)mem;
	if (file_size) {
		fprintf(stderr, "transfer error");
	}
	sem_post(sem1);

finish:
	mq_close(msg_q);
	sem_close(sem1);
	sem_close(sem2);
	sem_unlink(shm_blk->sem1_name);
	sem_unlink(shm_blk->sem2_name);
	munmap(mem, seg_size);
	pthread_mutex_lock(seg_q_mutex);
	steque_push(seg_q, shm_blk);
	pthread_mutex_unlock(seg_q_mutex);
	pthread_cond_signal(seg_q_cond);

	return cache_file_size;
}
コード例 #5
0
ファイル: webproxy.c プロジェクト: jigarvora/shared_mem
/* Main ========================================================= */
int main(int argc, char **argv) {
  int i, option_char = 0;
  unsigned short port = 8888;
  unsigned short nworkerthreads = 1;
  unsigned short nsegments = 1;
  unsigned long segment_size = 1024;
  char *server = "s3.amazonaws.com/content.udacity-data.com";
  struct shm_info *shm_blk;

  if (signal(SIGINT, _sig_handler) == SIG_ERR){
    fprintf(stderr,"Can't catch SIGINT...exiting.\n");
    exit(EXIT_FAILURE);
  }

  if (signal(SIGTERM, _sig_handler) == SIG_ERR){
    fprintf(stderr,"Can't catch SIGTERM...exiting.\n");
    exit(EXIT_FAILURE);
  }

  // Parse and set command line arguments
  while ((option_char = getopt_long(argc, argv, "n:z:p:t:s:h", gLongOptions,
   NULL)) != -1) {
    switch (option_char) {
      case 'n': // num segments
        nsegments = atoi(optarg);
        break;
      case 'z': // size of segments
        segment_size = atol(optarg);
        break;
      case 'p': // listen-port
        port = atoi(optarg);
        break;
      case 't': // thread-count
        nworkerthreads = atoi(optarg);
        break;
      case 's': // file-path
        server = optarg;
        break;                                          
      case 'h': // help
        fprintf(stdout, "%s", USAGE);
        exit(0);
        break;       
      default:
        fprintf(stderr, "%s", USAGE);
        exit(1);
    }
  }
  
  /* SHM initialization...*/

  /*Initializing server*/
  gfserver_init(&gfs, nworkerthreads);

  /*Setting options*/
  gfserver_setopt(&gfs, GFS_PORT, port);
  gfserver_setopt(&gfs, GFS_MAXNPENDING, 10);
  gfserver_setopt(&gfs, GFS_WORKER_FUNC, handle_with_cache);

  steque_init(&segfds_q);
  /* Create the segments */
  for (i = 0; i < nsegments; i++) {
    shm_blk = malloc(sizeof(*shm_blk));
    snprintf(shm_blk->mem_name, sizeof(shm_blk->mem_name), "mem_%d", i);
    if (shm_unlink(shm_blk->mem_name) == 0) {
      fprintf(stdout, "Shared mem %s removed from system.\n",
        shm_blk->mem_name);
    }
    shm_blk->memfd = shm_open(shm_blk->mem_name, O_CREAT | O_RDWR | O_TRUNC,
        0777);
    if (shm_blk->memfd < 0) {
      perror("shm_open");
      exit(1);
    }
    ftruncate(shm_blk->memfd, segment_size);
    snprintf(shm_blk->sem1_name, sizeof(shm_blk->sem1_name), "sem_%d_1", i);
    if (sem_unlink(shm_blk->sem1_name) == 0) {
      fprintf(stdout, "Semaphore %s removed from system.\n",
        shm_blk->sem1_name);
    }
    snprintf(shm_blk->sem2_name, sizeof(shm_blk->sem2_name), "sem_%d_2", i);
    if (sem_unlink(shm_blk->sem2_name) == 0) {
      fprintf(stdout, "Semaphore %s removed from system.\n",
        shm_blk->sem2_name);
    }
    steque_push(&segfds_q, shm_blk);
  }
  for(i = 0; i < nworkerthreads; i++)
    gfserver_setopt(&gfs, GFS_WORKER_ARG, i, server);

  handle_with_cache_init(&segfds_q, segment_size, &segfds_q_mutex,
      &segfds_q_cond);

  /*Loops forever*/
  gfserver_serve(&gfs);
}