Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "vault_utils.h"
- #include "priority_queue.h"
- #include "includes.h"
- /*create - fails if:
- -requasted file size isnt big enough
- //TODO - check what they mean
- //TODO - check if i need another for just to initilize
- */
- vault* create_vault(char* vault_name, ssize_t size){//???
- vault* v=(vault*)malloc(sizeof(vault));
- if(v==NULL){
- //TODO - check malloc
- }
- v->vault_size = size;
- v->biggest_pq.type=MAX;
- v->biggest_pq.seg_num=0;
- v->closest_pq.type=MIN;
- v->closest_pq.seg_num=0;
- v->free_space=size;
- v->empty_seg_num=1;
- v->seg_arr[0].offset=sizeof(vault)+1;
- v->seg_arr[0].size=size;
- v->seg_arr[0].pos=0;
- q_insert(&v->biggest_pq,&v->seg_arr[0]);
- v->creation_time = time(NULL);//???TODO
- int fd = open(vault_name,O_RDWR|O_CREAT,0755);
- if(fd<0){
- //TODO - print error
- }
- v->fd=fd;
- return v;
- }
- void print_fat(vault* v){
- for(int i =0;i<v->number_of_files;i++){
- print_file(&v->fat[i]);
- }
- }
- vault* read_vault(char* vault_name){
- vault* v=(vault*)malloc(sizeof(vault));
- int fd = open(vault_name,O_RDWR,0777);
- if(fd<0||read(fd,v,sizeof(vault))<0){
- free(v);
- //TODO -print msg
- return NULL;
- }
- //initilise closest pq
- //list_vault(v);
- for(int i=0;i<v->number_of_files;i++){
- for(int j=0;j<(v->fat)[i].seg_num;j++){
- v->closest_pq.arr[(v->fat)[i].seg_arr[j].pos]=
- &(v->fat)[i].seg_arr[j];
- }
- }
- //initilise biggest pq
- for(int i=0;i<v->empty_seg_num;i++){
- v->biggest_pq.arr[v->seg_arr[i].pos]=
- &v->seg_arr[i];
- }
- v->fd=fd;
- return v;
- }
- void write_vault(vault* v){
- if(lseek(v->fd,0,SEEK_SET)<0){
- //TODO -fix seek
- }
- int just_written = write(v->fd,v,sizeof(vault));
- if(just_written<0){
- //TODO -handle
- }
- return;
- }
- void list_vault(vault* v){
- file_record tmp;
- for(int i=0;i< v->number_of_files;i++){
- tmp=v->fat[i];
- printf("%s \t %zu \t %d \t %zu \n",tmp.file_name,
- tmp.file_size,
- tmp.perm,
- tmp.insertion_time);//TODO - check how to print time_t and st_mode
- }
- print_fat(v);
- }
- void print_vault_status(vault* v){//sum the spaces in the queue.
- //we find the last segement in the seg_num/2 last elements and
- // reduce the current capcicity from the sum of segements->
- queue* pq=&(v->closest_pq);
- ssize_t sum=v->first_gap;
- off_t last=0;
- for(int i=0;i<pq->seg_num/2-1;i++){
- sum+=pq->arr[i]->size;
- }
- for(int i=pq->seg_num/2;i<pq->seg_num;i++){
- sum+=pq->arr[i]->size;
- last=MAX(pq->arr[i]->offset,last);
- }
- }
- /*add - fails if:
- -file name exists already
- -no free space available
- -has free space but content has to be fragmented into more then 3 blocks
- */
- //remember to cleanup if this fails
- int add_to_vault(vault* v,char* file_name){
- if(linear_search(v,file_name)<0){
- //TODO -print error
- }
- int file_fd = open(file_name,O_RDWR);
- if(file_fd<0){
- printf("ERROR: opening input file : %s\n",strerror(errno));
- return errno;
- }
- struct stat statbuf;
- if(fstat(file_fd,&statbuf)<0){
- close(file_fd);
- printf("ERROR: getting stat of input file : %s\n",strerror(errno));
- return errno;
- }
- ssize_t file_s = statbuf.st_size;
- v->fat[v->number_of_files].perm=statbuf.st_mode;
- //notice we have in file_name the full path and only have to keep the last part
- //TODO - check if file exists
- queue* pq=&(v->biggest_pq);
- if(file_s>v->free_space){
- //TODO -return error - not enough free space
- }
- ssize_t sum=0;
- int file_seg_num=0;
- while(file_seg_num<MIN(3,pq->seg_num)&&file_s>sum){
- sum+=pq->arr[file_seg_num++]->size;
- }
- q_print_pq(pq);
- if(file_s>sum){
- printf("Error: file need to be fragmented more then 3 blocks\n");
- exit(1);
- }
- v->fat[v->number_of_files].seg_arr;
- v->fat[v->number_of_files].file_size=file_s;
- strcpy(v->fat[v->number_of_files].file_name,file_name);
- v->fat[v->number_of_files].insertion_time=time(NULL);
- ssize_t write_amount;
- ssize_t left_to_write=file_s;
- int j=0;
- segment* tmp;
- for(;j<file_seg_num;j++){
- write_amount=MIN(pq->arr[j]->size,left_to_write);
- tmp = write_seg(v,file_fd,(pq->arr[j]),write_amount);
- v->fat[v->number_of_files].seg_arr[j]=*tmp;
- free(tmp);
- left_to_write-=write_amount;
- }
- v->fat[v->number_of_files].seg_num=file_seg_num;
- v->number_of_files++;
- }
- /*rm fails if:
- -no such file exists
- */
- void remove_from_vault(vault* v,char* file_name){
- //we need to merge gaps
- //once we found we go through and remove the segments from the queue
- //also we need to decrease the key of some of the elements in the queue
- //also to check if we need to update first_gap
- int file_index=linear_search(v,file_name);
- if(file_index<0){
- //TODO - print error
- }
- printf("%s,%d\n",file_name,file_index);
- file_record* file = v->fat+file_index;
- printf("%d\n", file_index);
- for(int i=0;i< file->seg_num;i++){
- printf("deleting:\n");
- print_file(file);//DEBUG print
- delete_seg(v,file->seg_arr+i);
- q_delete(&(v->closest_pq),file->seg_arr[i].pos);
- /* while(){//go over the empty segments
- if(need_to_merge){
- merge_empty_seg(v,NULL,file.seg_arr[i]);//TODO
- }
- }*/
- }
- file_record* fat = v->fat;
- for(int i=file_index;i<v->number_of_files-1;i++){
- fat[i]=fat[i+1];
- }
- v->number_of_files--;
- }
- /*fetch fails if:
- -no such file exists
- -we dont have write permision for the current directory
- */
- int fetch_from_vault(vault* v,char* file_name){
- //use fstat on v to get dir and then check if we belong in the write group
- //ask ariel for help
- int file_index;
- if(file_index=linear_search(v,file_name)<0){
- printf("Error: file not found");
- return 1;
- }
- int file_fd = open(file_name,O_WRONLY | O_CREAT | O_TRUNC, 0775);
- if(file_fd<0){
- printf("Error opening vault file: %s\n", strerror(errno));
- return errno;
- }
- file_record file = (v->fat[file_index]);
- segment file_seg;
- file_seg.offset=0;
- for(int i=0;i<file.seg_num;i++){
- file_seg.size=file.seg_arr[i].size;
- segment* tmp_seg = &(file.seg_arr[i]);
- copy_seg(v->fd,file_fd,tmp_seg,&file_seg);
- file_seg.offset+=file.seg_arr[i].size;
- }
- return 0;
- }
- void defrag_vault(vault* v){//use heapsort thing on queue and move every block to the left
- queue* pq=&(v->closest_pq);
- segment* tmp_seg;
- while(!is_empty(pq)){
- tmp_seg=q_extract(pq);
- //we update first_gap because when we move
- //the segment to the left we set his new offset as first_gap
- move_to_left(v,tmp_seg);
- }
- //TODO - we need to restart biggest_pq and closest_pq
- }
- //copy the read_seg from input_fd to the out_seg in the output_fd -- NO DELIMITER
- int copy_seg(int read_fd, int write_fd, segment* read_seg, segment* write_seg){
- ssize_t bytes_left = read_seg->size;
- ssize_t amount;
- int just_written;
- char* buff=(char*)malloc(BUFF_SIZE);//TODO
- if(buff==NULL){
- printf("Error allocating memory: %s\n", strerror(errno));
- return errno;
- }
- if(lseek(read_fd, read_seg->offset,SEEK_SET)<0){
- printf("Error using lseek: %s\n", strerror(errno));
- return errno;
- }
- if(lseek(write_fd, write_seg->offset,SEEK_SET)<0){
- printf("Error using lseek: %s\n", strerror(errno));
- return errno;
- }
- while(bytes_left>0){
- amount=MIN(bytes_left,BUFF_SIZE);
- if(read(read_fd,buff,amount)<0){
- printf("Error reading from file: %s\n", strerror(errno));
- return errno;
- }
- just_written = write(write_fd,buff,amount);
- if(just_written<0){
- printf("Error writing into file: %s\n", strerror(errno));
- return errno;
- }
- bytes_left-=just_written;
- }
- free(buff);
- return 0;
- }
- void move_to_left(vault* v,segment* seg){
- segment s;
- s.offset = v->first_gap;
- s.size = (seg->offset)-(v->first_gap);
- write_seg(v,v->fd,&s,seg->size);
- delete_seg(v,seg);
- //tehn write_to_vault on appropriate segment
- }
- void print_seg(segment* s){
- printf("size: %zu offset: %zu pos: %d\n",s->size,s->offset,s->pos);
- }
- void print_file(file_record* f){
- printf("%s\n",f->file_name);
- for(int i=0;i<f->seg_num;i++){
- print_seg(&f->seg_arr[i]);
- }
- }
- //can be linear
- void merge_empty_seg(vault* v,segment* pq_seg,segment* removed_seg){
- }
- //writes a segment of size amount to the vault from the current position of input_fd
- //MUST ACCOUNT FOR OVERLAP - when used by move_to_left
- segment* write_seg(vault* v,int input_fd ,segment* empty_seg,ssize_t amount){
- queue* c_pq=&(v->closest_pq);
- queue* b_pq=&(v->biggest_pq);
- segment* s=(segment*)malloc(sizeof(segment));
- if(s->offset=lseek(input_fd, 0,SEEK_CUR)<0){
- //TODO - print error
- }
- s->size=amount;
- copy_seg(input_fd,v->fd,s,empty_seg);
- s->offset = empty_seg->offset;
- empty_seg->offset += amount;
- if(amount==empty_seg->size){
- q_delete(b_pq,empty_seg->pos);
- }
- else{
- q_update(b_pq,empty_seg->pos,empty_seg->size-amount);
- }
- s->pos = q_insert(c_pq,s);
- v->free_space -= amount;
- return s;
- }
- //deletes a segment from the vault
- //needs to be O(lgn)
- void delete_seg(vault* v,segment* seg){
- //may be inefficent with some extra reads
- int zero_fd = open("/dev/zero",O_RDWR,0755);
- copy_seg(zero_fd,v->fd,seg,seg);
- q_insert(&(v->biggest_pq),seg);
- v->free_space += seg->size;
- v->first_gap=MIN(seg->offset,v->first_gap);//TODO -write MIN
- close(zero_fd);
- }
- int linear_search(vault* v,char* key){
- file_record* fat = v->fat;
- for(int i=0;i<v->number_of_files;i++){
- if(strcmp(key,fat[i].file_name)==0){
- printf("index: %d\n",i );
- return i;
- }
- }
- return -1;
- }
- ssize_t pharse(char* str){
- int data_offset=0;
- int arlen = strlen(str)-1;
- char data_prefix = str[arlen];
- str[arlen] = '\0';
- ssize_t data_amount = atoi(str);
- switch(toupper(data_prefix)){
- case 'B':
- break;
- case 'K':
- data_offset=10;
- break;
- case 'M':
- data_offset=20;
- break;
- case 'G':
- data_offset=30;
- break;
- default:
- printf("ERROR: wrong usage of arguments\n");//TODO-print diffrent error
- return 1;
- }
- return data_amount<<data_offset;
- }
- char* lowercase(char* str){
- for (int i = 0; i < strlen(str); ++i) {
- str[i] = tolower(str[i]);
- }
- return str;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement