ssize_t handler_get(gfcontext_t *ctx, char *path, void* arg){ int fildes; ssize_t file_len, bytes_transferred; ssize_t read_len, write_len; char buffer[BUFFER_SIZE]; if( 0 > (fildes = content_get(path))) return gfs_sendheader(ctx, GF_FILE_NOT_FOUND, 0); /* Calculating the file size */ file_len = lseek(fildes, 0, SEEK_END); gfs_sendheader(ctx, GF_OK, file_len); /* Sending the file contents chunk by chunk. */ bytes_transferred = 0; while(bytes_transferred < file_len){ read_len = pread(fildes, buffer, BUFFER_SIZE, bytes_transferred); if (read_len <= 0){ fprintf(stderr, "handle_with_file read error, %zd, %zu, %zu", read_len, bytes_transferred, file_len ); gfs_abort(ctx); return -1; } write_len = gfs_send(ctx, buffer, read_len); if (write_len != read_len){ fprintf(stderr, "handle_with_file write error"); gfs_abort(ctx); return -1; } bytes_transferred += write_len; } return bytes_transferred; }
ssize_t handle_with_file(gfcontext_t *ctx, char *path, void* arg){ int fildes; size_t file_len, bytes_transferred; ssize_t read_len, write_len; char buffer[4096]; char *data_dir = arg; strcpy(buffer,data_dir); strcat(buffer,path); if( 0 > (fildes = open(buffer, O_RDONLY))){ if (errno == ENOENT) /* If the file just wasn't found, then send FILE_NOT_FOUND code*/ return gfs_sendheader(ctx, GF_FILE_NOT_FOUND, 0); else /* Otherwise, it must have been a server error. gfserver library will handle*/ return EXIT_FAILURE; } /* Calculating the file size */ file_len = lseek(fildes, 0, SEEK_END); lseek(fildes, 0, SEEK_SET); gfs_sendheader(ctx, GF_OK, file_len); /* Sending the file contents chunk by chunk. */ bytes_transferred = 0; while(bytes_transferred < file_len){ read_len = read(fildes, buffer, 4096); if (read_len <= 0){ fprintf(stderr, "handle_with_file read error, %zd, %zu, %zu", read_len, bytes_transferred, file_len ); return EXIT_FAILURE; } write_len = gfs_send(ctx, buffer, read_len); if (write_len != read_len){ fprintf(stderr, "handle_with_file write error"); return EXIT_FAILURE; } bytes_transferred += write_len; } return bytes_transferred; }
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; }
ssize_t handle_with_cache(gfcontext_t *ctx, char *path, void *arg) { /* Get thread id */ Workload *wld = (Workload *)arg; pthread_t tid = pthread_self(); printf("entered %ld\n", tid); /* Sequence of steps to pop a segment number from the queue */ /* Read phase */ /* Lock the mutex */ pthread_mutex_lock(wld->sq_mtx_p); /* Wait until the queue is empty and writers are waiting */ while(steque_isempty(wld->segqueue)) { fprintf(stderr, "[handle_with_cache, thread_id = %ld] Waiting for shm segment\n", tid); pthread_cond_wait(wld->sq_notempty_p, wld->sq_mtx_p); } /* Pop a segment number */ long shm_segnum = (long) steque_pop(wld->segqueue); fprintf(stderr, "[handle_with_cache, thread_id = %ld] Popped shm segment %ld\n", tid, shm_segnum); /* unlock the mutex */ fprintf(stderr, "[handle_with_cache, thread_id = %ld] Unlocking the mutex\n", tid); pthread_mutex_unlock(wld->sq_mtx_p); /* convert the shm_segnum to shm_segid string */ fprintf(stderr, "[handle_with_cache, thread_id = %ld] converting segnum to segid\n", tid); char shm_segid[SEGID_LEN]; memset(shm_segid, 0, SEGID_LEN); if (sprintf(shm_segid, "%ld", shm_segnum) < 0) { err_exit("handle_with_cache", "sprintf", 1); } /* Open descriptor for shared memory region */ int shm_fd = shm_open(shm_segid, O_RDWR, 0); if (shm_fd == -1) { strerr_exit("handle_with_cache, shm_open", errno); } /* obtain the pointer to shared memory */ Shm_Block *shmb_p; shmb_p = mmap(NULL, wld->shm_blocksize, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); if (shmb_p == MAP_FAILED) { err_exit("handle_with_cache", "mmap failed", errno); } /* close shm file descriptor; its no longer needed */ close(shm_fd); /* SHM data buffer starts after the shm metadata */ char *shm_buf = (char *) shmb_p + sizeof(Shm_Block); /* Initialize writer (simplecached) semaphore to 1; initially available */ if (sem_init(&shmb_p->sem_writer, 1, 1) == -1) { err_exit("handle_with_cache", "Unable to initialize writer semaphore.", errno); } /* Initialize reader (handle_with_cache) semaphore to 0; initially unavailable */ if (sem_init(&shmb_p->sem_reader, 1, 0) == -1) { err_exit("handle_with_cache", "Unable to initialize reader semaphore.", errno); } /* Compose message to be sent to simplecached with URL, shm segment id and shm_blocksize */ char msg[MQ_MSGSIZE]; if(sprintf(msg, "%s %ld %zu", path, shm_segnum, wld->shm_blocksize) < 0 ) { err_exit("handle_with_cache", "sprintf", 1); } /* Send message */ fprintf(stderr, "[handle_with_cache, thread_id = %ld] Sending message on mqueue\n", tid); if (mq_send(wld->mqd, msg, strlen(msg), 0) == -1) strerr_exit("handle_with_cache, mq_send", errno); /* Lock the reader */ if (sem_wait(&shmb_p->sem_reader) == -1) { strerr_exit("handle_with_cache, sem_wait (hdr)", errno); } /* Read file size from simplecached */ fprintf(stderr, "[handle_with_cache, thread_id = %ld] Reading file-size from simplecached\n", tid); int file_size = shmb_p->file_size; fprintf(stderr, "[handle_with_cache] Req path = %s, file_size = %d\n", path, file_size); /* send GFS header */ if (file_size == -1) { fprintf(stderr, "[handle_with_cache, thread_id = %ld] FNF, about to lock mutex\n", tid); pthread_mutex_lock(wld->sq_mtx_p); fprintf(stderr, "[handle_with_cache, thread_id = %ld] Enqueuing the segnum %ld\n", tid, shm_segnum); steque_enqueue(wld->segqueue, (steque_item) shm_segnum); pthread_mutex_unlock(wld->sq_mtx_p); pthread_cond_broadcast(wld->sq_notempty_p); return gfs_sendheader(ctx, GF_FILE_NOT_FOUND, 0); } /* unlock the writer */ if (sem_post(&shmb_p->sem_writer) == -1) { strerr_exit("handle_with_cache, sem_post (hdr)", errno); } gfs_sendheader(ctx, GF_OK, file_size); /* STEPS FOR FILE TRANSFER */ /* We use a pair of semaphores to alternate control between reader (i.e. handle_with_cache) and the writer (i.e. simplecached). We also keep track of number of trnasfers and bytes transferred */ int nxfrs = 0; ssize_t bytes_xfrd = 0; for (nxfrs = 0, bytes_xfrd = 0 ;; nxfrs++, bytes_xfrd += shmb_p->cnt) { /* Lock the reader semaphore. If it is already locked, this call will block. Thus, the control will never go past this point unless the writer has unlocked the semaphore. */ if (sem_wait(&shmb_p->sem_reader) == -1) { strerr_exit("handle_with_cache, sem_wait (data)", errno); } /* File is done on the writer side */ if (shmb_p->cnt == 0) { break; } /* Read Bytes from the shared memory */ // printf("\n[handle_with_cache] writing data below \n\n"); // write(STDOUT_FILENO, shm_buf, shmb_p->cnt); if (gfs_send(ctx, shm_buf, shmb_p->cnt) != shmb_p->cnt) { err_exit("handle_with_cache", "gfs_send", EXIT_FAILURE); } /* Unlock the writer */ if (sem_post(&shmb_p->sem_writer) == -1) { strerr_exit("handle_with_cache, sem_post (data)", errno); } } /* Work is done; steps to put the shared memory segment back into queue */ fprintf(stderr, "[handle_with_cache, thread_id = %ld] FF, about to lock mutex\n", tid); pthread_mutex_lock(wld->sq_mtx_p); fprintf(stderr, "[handle_with_cache, thread_id = %ld] Enqueuing the segnum %ld\n", tid, shm_segnum); steque_enqueue(wld->segqueue, (steque_item) shm_segnum); pthread_mutex_unlock(wld->sq_mtx_p); pthread_cond_broadcast(wld->sq_notempty_p); return bytes_xfrd; }
ssize_t handle_with_cache(gfcontext_t* ctx, char *path, void* arg) { char* fldes; pthread_mutex_lock(&fldes_mutex); while (fldes_queue_size == 0) { pthread_cond_wait(&read_cond, &fldes_mutex); } fldes = (char*)steque_pop(&fldes_queue); fldes_queue_size--; // fprintf(stdout, "fldes is:%s.", fldes); pthread_mutex_unlock(&fldes_mutex); pthread_cond_broadcast(&write_cond); //pthread_cond_signal(&write_cond); shm_data* mem = create_shm_channel(fldes); mqd_t mq; do { mq = mq_open (MSGQID, O_RDWR); } while(mq == (mqd_t) -1 || mq == 0); msgq_data data; strcpy(data.path, path); strcpy(data.fldes, fldes); data.segment_size = segment_size; // pthread_mutex_lock(&msgq_mutex); int msg_rsp = mq_send(mq, (const char *) &data, 1024, 1); if (msg_rsp < 0) { fprintf(stderr, "Error %d (%s) on server proxy mq_send.\n", errno, strerror(errno)); fflush(stdout); // exit(1); } mq_close(mq); // pthread_mutex_unlock(&msgq_mutex); pthread_mutex_lock(&mem->file_len_mutex); while(mem->file_length == 0) { pthread_cond_wait(&mem->proxy_cond, &mem->file_len_mutex); } int file_len = mem->file_length; pthread_mutex_unlock(&mem->file_len_mutex); pthread_cond_broadcast(&mem->cache_cond); // fprintf(stdout, "Received file length is: %d\n", file_len); // fflush(stdout); if(file_len < 0) { // fprintf(stdout, "File not found in cache\n"); // fflush(stdout); destroy_shm_seg(fldes, mem); return gfs_sendheader(ctx, GF_FILE_NOT_FOUND, 0); }else { gfs_sendheader(ctx, GF_OK, file_len); int bytes_transferred = 0; int write_len = 0; char *data_start = (void *)(mem + 1); while (bytes_transferred < file_len) { pthread_mutex_lock(&mem->data_mutex); while(mem->bytes_written == 0) { pthread_cond_wait(&mem->proxy_cond, &mem->data_mutex); } int read_len = mem->bytes_written; write_len = gfs_send(ctx, data_start, read_len); if (write_len != read_len) { fprintf(stderr, "handle_with_cache write error"); return EXIT_FAILURE; } mem->bytes_written = 0; pthread_mutex_unlock(&mem->data_mutex); pthread_cond_broadcast(&mem->cache_cond); bytes_transferred += write_len; } destroy_shm_seg(fldes, mem); fflush(stdout); return bytes_transferred; } }