void dataService(int client_sock, void* buff, sockaddr_in fromAddr, NoVoHT* pmap) { // cout << strlen((char*)buff) << "{" << ((char*)buff) << "}" << endl; //cout<<"dataService: from port "<< fromAddr.sin_port<<endl; srand(getpid() + clock()); //srand(kyotocabinet::getpid() + clock()); //cout << "Current service thread ID = " << pthread_self()<< ", dbService() begin..." << endl; // char buff[Env::MAX_MSG_SIZE]; int32_t operation_status = -99; // // sockaddr_in toAddr; int r; void* buff1; Package package; package.ParseFromArray(buff, Env::MAX_MSG_SIZE); string result; // cout << endl << endl << "in dbService: received replicano = "<< package.replicano() << endl; // cout << "Server got package size: " << package.ByteSize() << endl; // cout <<"Package content: "<< (char*)buff<<endl; switch (package.operation()) { case 1: //lookup { // cout << "Lookup..." << endl; if (package.virtualpath().empty()) { // cerr << "Bad key: nothing to find" << endl; operation_status = -1; } else { //result = HB_lookup(db, package); // cout << "Lookup...2" << endl; //cout<<"Will lookup key: "<< package.virtualpath()<<endl; // result = HB_lookup(hmap, package); result = HB_lookup(pmap, package); // cout << "Lookup...3" << endl; //don't really send result back to client now, do it latter. if (result.compare("Empty") == 0) { operation_status = -2; } else { operation_status = 0; } } /* * pack the status and lookup-result into one string */ buff1 = &operation_status; char statusBuff[3]; sprintf(statusBuff, "%03d", operation_status); string sAllInOne; sAllInOne.append(statusBuff); sAllInOne.append(result); generalSendBack(client_sock, sAllInOne.c_str(), sAllInOne.size(), fromAddr, 0, TCP); } break; case 4: { if (package.virtualpath().empty()) { operation_status = -1; } else { // cout << "Server: append..." << endl; //operation_status = HB_insert(db, package); operation_status = HB_append(pmap, package); // cout << "Server: append ret = "<< operation_status <<endl; //cout<<"Inserted: key: "<< package.virtualpath()<<endl; // cout << "insert finished, return: " << operation_status << endl; } buff1 = &operation_status; if (TCP == true) { r = send(client_sock, &operation_status, sizeof(int32_t), 0); } else { r = sendto(client_sock, &operation_status, sizeof(int32_t), 0, (struct sockaddr *) &fromAddr, sizeof(struct sockaddr)); } if (r <= 0) { cout << "Append: Server could not send acknowledgement to client: sendto r = " << r << endl; } } break; case 2: { //remove // cout << "Remove..." << endl; //cout << "Package:key "<<package.virtualpath()<<endl; if (package.virtualpath().empty()) { cerr << "Bad key: nothing to remove" << endl; operation_status = -1; } else { //operation_status = HB_remove(db, package); // operation_status = HB_remove(hmap, package); operation_status = HB_remove(pmap, package); //r = d3_send_data(client_sock, buff1, sizeof(int32_t), 0, &toAddr); //r = generalSendBack(client_sock, (const char*) buff1, fromAddr, 0,TCP); } buff1 = &operation_status; if (TCP == true) { r = send(client_sock, &operation_status, sizeof(int32_t), 0); } else { r = sendto(client_sock, &operation_status, sizeof(int32_t), 0, (struct sockaddr *) &fromAddr, sizeof(struct sockaddr)); } if (r <= 0) { cout << "Remove: Server could not send acknowledgement to client, r = " << r << endl; } // cout << "Remove succeeded, return " << operation_status << endl; //end remove if-else } break; case 3: { //insert if (package.virtualpath().empty()) { operation_status = -1; } else { // cout << "Insert..." << endl; //operation_status = HB_insert(db, package); operation_status = HB_insert(pmap, package); // operation_status = HB_insert_cstr(chmap, package); // operation_status = HB_insert(hmap, package); //cout<<"Inserted: key: "<< package.virtualpath()<<endl; // cout << "insert finished, return: " << operation_status << endl; // r = d3_send_data(client_sock, buff1, sizeof(int32_t), 0, &toAddr); // r = generalSendBack(client_sock, (const char*)&operation_status, fromAddr, 0, TCP); } buff1 = &operation_status; if (TCP == true) { r = send(client_sock, &operation_status, sizeof(int32_t), 0); } else { r = sendto(client_sock, &operation_status, sizeof(int32_t), 0, (struct sockaddr *) &fromAddr, sizeof(struct sockaddr)); } //cout << "Insert: Server send acknowledgement to client: sendto r = " <<r<< endl; //cout<<"send back status: "<< *(int*)buff1<<endl; if (r <= 0) { cout << "Insert: Server could not send acknowledgement to client: sendto r = " << r << endl; } } break; case 99: { //shut the server // cout << "Server will be shut shortly." << endl; turn_off = 1; //turn off service. } break; default: { operation_status = -98; //unrecognized operation buff1 = &operation_status; if (TCP == true) { r = send(client_sock, &operation_status, sizeof(int32_t), 0); } else { r = sendto(client_sock, &operation_status, sizeof(int32_t), 0, (struct sockaddr *) &fromAddr, sizeof(struct sockaddr)); } } break; } //end switch-case buff1 = &operation_status; // cout << "Before handle Replication " << endl; if (Env::NUM_REPLICAS > 0) { // infinite loop if not limited by replicano, coz it will send the replica to itself infinitely if (package.replicano() == 5) { if (package.operation() == 3 || package.operation() == 2) { int i = Env::NUM_REPLICAS; unsigned int n; // package.set_replicano(3); while (i > 0) { //change from numReplica to i n = myhash((package.virtualpath()).c_str(), nHost) + i; n = n % hostList.size(); struct HostEntity destination = hostList.at(n); general_replica(package, Replicas[i - 1]); // cout << "Replica remove: sent to " << destination.port << " and before send replicano() = "<< package.replicano() << endl; // cout << "Replication: i = " << i << endl; //numReplica--; i--; } } } } } //end function
//raman-replication-e void *dbService(void *threadarg) { srand(kyotocabinet::getpid() + clock()); //cout << "Current service thread ID = " << pthread_self()<< ", dbService() begin..." << endl; char buff[MAX_MSG_SIZE]; int32_t operation_status; sockaddr_in toAddr; int client_sock, r; void* buff1 = (void*) malloc(sizeof(int32_t)); #if TRANS_PROTOCOL ==USE_TCP client_sock = ((struct threaddata *) threadarg)->socket; #elif TRANS_PROTOCOL == USE_UDP toAddr = ((struct threaddata *) threadarg)->sockinfo; strcpy( buff, ((struct threaddata *) threadarg)->buffer ); //here the buffer(it seems a global variable) should be refreshed so clean it. #endif //raman-s // if (size > 0) { //if size < 0, consider it as a "quit command" //raman-e cout << "Thread: receive request from client..." << endl; #if TRANS_PROTOCOL == USE_TCP r = d3_svr_recv(client_sock, buff, MAX_MSG_SIZE * sizeof(char), 0, &toAddr); if (r <= 0) { cout << "Server could not recv data" << endl; } #endif Package package; package.ParseFromArray(buff, MAX_MSG_SIZE); string result; cout << endl << endl << "in dbService: received replicano = " << package.replicano() << endl; cout << "package size: " << package.ByteSize() << endl; // cout <<"Package content: "<< buff<<endl; switch (package.operation()) { case 3: //insert cout << "Insert..."<< endl; operation_status = HB_insert(db, package); break; case 1: //lookup cout << "Lookup..."<< endl; if (package.virtualpath().empty()) { cerr << "Bad key: nothing to find" << endl; operation_status = -1; } else { result = HB_lookup(db, package); //don't really send result back to client now, do it latter. if (result.empty()) { operation_status = -2; buff1 = &operation_status; } else { //find result, send back here cout << "Lookup: Result found, sending back..." << endl; //===================================== //how to know where to send back? Use the one that created when receive request as above. //d3_send_data(client_sock, (void*)result.c_str(),result.length(), 0, &toAddr); //just a try, not use simpleSend, because no need to make a new socket and connection.. if (TRANS_PROTOCOL == USE_TCP) { d3_send_data(client_sock, (void*) result.c_str(), result.length(), 0, &toAddr); //TCP reuse the socket and connection. } else if (TRANS_PROTOCOL == USE_UDP) { HostEntity dest; char host[INET_ADDRSTRLEN]; cout << "before inet_ntop" << endl; inet_ntop(AF_INET, &(toAddr.sin_addr), host, INET_ADDRSTRLEN); //get a hostname from toAddr cout << "before inet_ntop" << endl; string hostName = string(host); cout << "string made" << endl; dest.host = hostName; dest.port = toAddr.sin_port; //this is arandom port used by client just once, it was discarded after once use. //dest.port = 50001; working, but ugly and dangerous cout << "send back result to host: " << dest.host << "; port: " << dest.port << endl; int sock = 0; cout << "host entity ready, now simpleSend..." << endl; simpleSend(result, dest, sock); //d3_closeConnection(sock);//may be necessary. // Do nothing below.---------------- operation_status = 0; } } } break; case 2: //remove cout << "Remove..."<< endl; if (package.virtualpath().empty()) { cerr << "Bad key: nothing to remove" << endl; operation_status = -1; } else { operation_status = HB_remove(db, package.virtualpath()); } break; default: operation_status = -3; break; } buff1 = &operation_status; #if TRANS_PROTOCOL == USE_TCP r = d3_send_data(client_sock, buff1, sizeof(int32_t), 0, &toAddr); if (r <= 0) { cout << "Server could not send acknowledgement to client" << endl; } if (!result.empty()) { //return lookup result. r = d3_send_data(client_sock, (void*) result.c_str(), MAX_MSG_SIZE * sizeof(char), 0, &toAddr); //RCV_MSG_SIZE = 134 } #elif TRANS_PROTOCOL == USE_UDP d3_send_data( server_sock, buff1, sizeof(int32_t), 0, &toAddr ); if(!result.empty()) { //return lookup result. r = d3_send_data(client_sock, (void*)result.c_str(), MAX_MSG_SIZE*sizeof(char), 0, &toAddr);//RCV_MSG_SIZE = 134 } #endif //raman-s // } // if (size < 0) { // cout << "Received QUIT command." << endl; // //do something joining/exiting... // } //raman-e //raman-replication-s //raman-the insert/remove have not been unit tested when two or three servers //have failed or when a random server failes (not the primary) // cout << "Package replication process begin: ..." << endl; //v----------------------------- do replication ------------------------------------v //cout <<"in dbService: replicano() = "<< package.replicano()<<endl; // cout<<"in dbService: replicano() = "<< package.replicano() <<endl;//here problem: replicano is always 0, where it come from??? /* //Tony: this is a stupid and ugly patch for UDP: the package size 132 problem is still not solved. #if TRANS_PROTOCOL == USE_UDP if(package.replicano() == 0){ cout<<"Stupid patch working: replicano changed from 0 to 5."<<endl; package.set_replicano(5); } #endif //---------------------------------------------- */ if (package.replicano() == 5) { //only forward orginal copy:5--Tony cout << "tell if new package..." << endl; if (package.operation() == 3) { //insert int32_t numReplica = package.replicano(); int i = NUM_REPLICAS; unsigned int n; package.set_replicano(3); //3 means it's not an original(5) request.:------here the definition of replicano are different: //mine is that replicano is a indicator for original copy, raman's is that it is the num of replicas, given by user. while (i > 0) { //numReplica was given by package.replicano,and this is always <==. //loop condition variable should be i n = myhash((package.virtualpath()).c_str(), nHost) + i; n = n % hostList.size(); struct HostEntity destination = hostList.at(n); cout << "Replica insert: sent to " << destination.port << " and before send replicano() = " << package.replicano() << endl; //sleep(3); int ret = contactReplica(package, destination); //seems don't need to handle failure here // cout << "Replica Insert: i = " << i << endl; //numReplica--; i--; } //return anything? /* //-------------copied from end, for stop the thread #if TRANS_PROTOCOL==USE_TCP int closingSock = ((struct threaddata *) threadarg)->socket; close(closingSock); ((struct threaddata *) threadarg)->socket = -1; #elif TRANS_PROTOCOL==USE_UDP memset( &(((struct threaddata *) threadarg)->sockinfo), 0, sizeof(sockaddr_in) ); memset( (((struct threaddata *) threadarg)->buffer), 0, sizeof(RCV_MSG_SIZE) ); #endif cout << "leaving thread..."<<endl; pthread_mutex_lock(&mutex1); numthreads--; pthread_mutex_unlock(&mutex1); cout << "After unlock mutex..."<<endl; pthread_detach(pthread_self());//end thread. cout << "After detach thread..."<<endl; pthread_exit(NULL); //-------------copied from end */ } if (package.operation() == 2) { //remove int32_t numReplica = package.replicano(); int i = NUM_REPLICAS; unsigned int n; package.set_replicano(3); while (i > 0) { //change from numReplica to i n = myhash((package.virtualpath()).c_str(), nHost) + i; n = n % hostList.size(); struct HostEntity destination = hostList.at(n); contactReplica(package, destination); cout << "Replica remove: sent to " << destination.port << " and before send replicano() = " << package.replicano() << endl; // cout << "Replica Remove: i = " << i << endl; //numReplica--; i--; } /* //-------------copied from end, for stop the thread #if TRANS_PROTOCOL==USE_TCP int closingSock = ((struct threaddata *) threadarg)->socket; close(closingSock); ((struct threaddata *) threadarg)->socket = -1; #elif TRANS_PROTOCOL==USE_UDP memset( &(((struct threaddata *) threadarg)->sockinfo), 0, sizeof(sockaddr_in) ); memset( (((struct threaddata *) threadarg)->buffer), 0, sizeof(RCV_MSG_SIZE) ); #endif cout << "leaving thread..."<<endl; pthread_mutex_lock(&mutex1); numthreads--; pthread_mutex_unlock(&mutex1); cout << "After unlock mutex..."<<endl; pthread_detach(pthread_self());//end thread. cout << "After detach thread..."<<endl; pthread_exit(NULL); //-------------copied from end */ } } //raman-replication-e #if TRANS_PROTOCOL==USE_TCP int closingSock = ((struct threaddata *) threadarg)->socket; close(closingSock); ((struct threaddata *) threadarg)->socket = -1; //this should work but seems it donesn't.-----------------???? #elif TRANS_PROTOCOL==USE_UDP memset( &(((struct threaddata *) threadarg)->sockinfo), 0, sizeof(sockaddr_in) ); memset( (((struct threaddata *) threadarg)->buffer), 0, sizeof(MAX_MSG_SIZE) ); #endif //cout << "leaving thread..."<<endl; pthread_mutex_lock(&mutex1); numthreads--; pthread_mutex_unlock(&mutex1); //cout << "Ending thread: "<< pthread_self() <<endl; pthread_detach(pthread_self()); //end thread. cout << "After detach thread..." << endl << endl << endl; pthread_exit(NULL); }