00001
00002
00003 #include "../include/repository.h"
00004 #include "../include/cond_comp.h"
00005
00006 repository_class::repository_class() {
00007 for(int i = 0; i < SEC_NUM; i++) {
00008 pthread_mutex_init(&archive[i].mutex,0);
00009 }
00010 }
00011
00012 int repository_class::section_number(char c) {
00013 if(c >= 'a' && c <= 'z')
00014 return (int)(c-'a');
00015 if(c >='A' && c <= 'Z')
00016 return (int)(c-'A');
00017 return SEC_NUM-1;
00018 }
00019
00020 void repository_class::add_file(string file_name, int sock,
00021 string ip_address, int port, int max_clients) {
00022 if(max_clients < 1) return;
00023 int i = section_number(file_name[0]);
00024 DEB(fprintf(stderr, "add_file1: %s\n", file_name.c_str()));
00025 pthread_mutex_lock(&archive[i].mutex);
00026 file* f= archive[i].files[file_name];
00027 if(f) {
00028
00029 DEB(fprintf(stderr, "add_file2: %s, file exists\n", file_name.c_str()));
00030 list<location*>::iterator j;
00031 for(j = f->locations.begin(); j != f->locations.end(); j++)
00032 if((*j)->serv_sock == sock) {
00033
00034 DEB(fprintf(stderr, "add_file3: %s, location match\n", file_name.c_str()));
00035 pthread_mutex_unlock(&archive[i].mutex);
00036 return;
00037 }
00038 DEB(fprintf(stderr, "add_file3: %s, location not match\n", file_name.c_str()));
00039 location* l = new location;
00040 l->serv_sock = sock;
00041 l->serv_ip_address = ip_address;
00042 l->port = port;
00043 l->max_clients = max_clients;
00044 l->cur_clients = 0;
00045 f->locations.push_back(l);
00046 pthread_cond_broadcast(&f->free);
00047 } else {
00048
00049 DEB(fprintf(stderr, "add_file2: %s, file does not exists\n", file_name.c_str()));
00050 file* new_f = new file;
00051 pthread_cond_init(&new_f->free, 0);
00052 new_f->waiting_clients = 0;
00053 location* l = new location;
00054 l->serv_sock = sock;
00055 l->serv_ip_address = ip_address;
00056 l->port = port;
00057 l->max_clients = max_clients;
00058 l->cur_clients = 0;
00059 new_f->locations.push_back(l);
00060 archive[i].files[file_name]=new_f;
00061
00062 }
00063 DEB(fprintf(stderr, "add_file: %s, terminated\n", file_name.c_str()));
00064 pthread_mutex_unlock(&archive[i].mutex);
00065 return;
00066 }
00067
00068 int repository_class::remove_file(string file_name, int sock) {
00069 int i = section_number(file_name[0]);
00070 DEB(printf("remove_file1: %s\n", file_name.c_str()));
00071 pthread_mutex_lock(&archive[i].mutex);
00072 file* f= archive[i].files[file_name];
00073 if(!f) {
00074 DEB(fprintf(stderr, "remove_file2: %s, file not found\n", file_name.c_str()));
00075 pthread_mutex_unlock(&archive[i].mutex);
00076 return -1;
00077 }
00078 DEB(fprintf(stderr, "remove_file2: %s, file found\n", file_name.c_str()));
00079 list<location*>::iterator j;
00080 for(j = f->locations.begin(); j != f->locations.end(); j++)
00081 if((*j)->serv_sock == sock) {
00082
00083 DEB(fprintf(stderr, "remove_file3: %s, location found\n", file_name.c_str()));
00084 location* l = *j;
00085 f->locations.erase(j);
00086 delete(l);
00087
00088 if(f->locations.empty() && f->waiting_clients==0) {
00089 DEB(fprintf(stderr, "remove_file4: %s, erasing entire file!\n", file_name.c_str()));
00090 archive[i].files.erase(file_name);
00091 }
00092 DEB(fprintf(stderr, "remove_file: %s, terminated\n", file_name.c_str()));
00093 pthread_mutex_unlock(&archive[i].mutex);
00094 return 0;
00095 }
00096 DEB(fprintf(stderr, "remove_file3: %s, location not found\n", file_name.c_str()));
00097 pthread_mutex_unlock(&archive[i].mutex);
00098 return -1;
00099 }
00100
00101 int repository_class::obtain_file(string file_name,
00102 string* ip_address, int* port, int cli_sock) {
00103 int i = section_number(file_name[0]);
00104 DEB(fprintf(stderr, "obtain_file1: %s\n", file_name.c_str()));
00105 pthread_mutex_lock(&archive[i].mutex);
00106 file* f= archive[i].files[file_name];
00107 if(!f) {
00108 DEB(fprintf(stderr, "obtain_file2: %s, file not found\n", file_name.c_str()));
00109 pthread_mutex_unlock(&archive[i].mutex);
00110 return -1;
00111 }
00112 DEB(fprintf(stderr, "obtain_file2: %s, file found\n", file_name.c_str()));
00113 list<location*>::iterator j;
00114 for(j = f->locations.begin(); j != f->locations.end(); j++)
00115 if((*j)->cur_clients < (*j)->max_clients) {
00116
00117 DEB(fprintf(stderr, "obtain_file3: %s, free!\n", file_name.c_str()));
00118 (*j)->cur_clients++;
00119 (*j)->active_clients.push_back(cli_sock);
00120 *ip_address = (*j)->serv_ip_address;
00121 *port = (*j)->port;
00122 pthread_mutex_unlock(&archive[i].mutex);
00123 return 0;
00124 }
00125 DEB(fprintf(stderr, "obtain_file3: %s, too many clients!\n", file_name.c_str()));
00126 pthread_mutex_unlock(&archive[i].mutex);
00127 return 1;
00128 }
00129
00130 int repository_class::release_file(string file_name, int cli_sock) {
00131 int i = section_number(file_name[0]);
00132 DEB(fprintf(stderr, "release_file1: %s\n", file_name.c_str()));
00133 pthread_mutex_lock(&archive[i].mutex);
00134 file* f= archive[i].files[file_name];
00135 if(!f) {
00136 DEB(fprintf(stderr, "release_file2: %s, file not found\n", file_name.c_str()));
00137 pthread_mutex_unlock(&archive[i].mutex);
00138 return -1;
00139 }
00140 DEB(fprintf(stderr, "release_file2: %s, file found\n", file_name.c_str()));
00141 list<location*>::iterator j;
00142 for(j = f->locations.begin(); j != f->locations.end(); j++) {
00143 list<int>::iterator k;
00144 for(k = (*j)->active_clients.begin(); k != (*j)->active_clients.end(); k++)
00145 if((*k) == cli_sock) {
00146
00147 DEB(fprintf(stderr, "release_file3: %s, client found!\n", file_name.c_str()));
00148 (*j)->active_clients.erase(k);
00149 (*j)->cur_clients--;
00150 pthread_cond_broadcast(&f->free);
00151 pthread_mutex_unlock(&archive[i].mutex);
00152 return 0;
00153 }
00154 }
00155
00156 DEB(fprintf(stderr, "release_file3: %s, client not in active clients!\n", file_name.c_str()));
00157 pthread_mutex_unlock(&archive[i].mutex);
00158 return -1;
00159 }
00160
00161 void repository_class::wait_file(string file_name) {
00162 int i = section_number(file_name[0]);
00163 DEB(fprintf(stderr, "wait_file1: %s\n", file_name.c_str()));
00164 pthread_mutex_lock(&archive[i].mutex);
00165 file* f= archive[i].files[file_name];
00166 if(!f) {
00167
00168 DEB(fprintf(stderr, "wait_file2: %s, file not found\n", file_name.c_str()));
00169 f = new file;
00170 pthread_cond_init(&f->free, 0);
00171 f->waiting_clients = 0;
00172 archive[i].files[file_name]=f;
00173 }
00174 list<location*>::iterator j;
00175 do {
00176 DEB(fprintf(stderr, "wait_file3: %s, testing\n", file_name.c_str()));
00177 for(j = f->locations.begin(); j != f->locations.end(); j++)
00178 if((*j)->cur_clients < (*j)->max_clients) {
00179 DEB(fprintf(stderr, "wait_file4: %s, terminated\n", file_name.c_str()));
00180 pthread_mutex_unlock(&archive[i].mutex);
00181 return;
00182 }
00183 f->waiting_clients++;
00184 pthread_cond_wait(&f->free, &archive[i].mutex);
00185 f->waiting_clients--;
00186 } while (1);
00187 }