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
Ejemplo n.º 2
0
//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);
}