void* ReceiveStateFromParticipant(void* _rcv_thread_arg) { ReceiveStateThreadArgument *rcv_thread_arg = (ReceiveStateThreadArgument *)_rcv_thread_arg; int pid = rcv_thread_arg->pid; int tid = rcv_thread_arg->transaction_id; Process *p = rcv_thread_arg->p; char buf[kMaxDataSize]; int num_bytes; //TODO: write code to extract multiple messages fd_set temp_set; FD_ZERO(&temp_set); FD_SET(p->get_fd(pid), &temp_set); int fd_max = p->get_fd(pid); int rv; rv = select(fd_max + 1, &temp_set, NULL, NULL, (timeval*)&kTimeout); if (rv == -1) { //error in select // cout << "P" << p->get_pid() << ": ERROR in select() for P" << pid << strerror(errno)<< endl; rcv_thread_arg->st = PROCESSTIMEOUT; p->RemoveFromUpSet(pid); } else if (rv == 0) { //timeout rcv_thread_arg->st = PROCESSTIMEOUT; p->RemoveFromUpSet(pid); } else { // activity happened on the socket if ((num_bytes = recv(p->get_fd(pid), buf, kMaxDataSize - 1, 0)) == -1) { // cout << "P" << p->get_pid() << ": ERROR in receiving for P" << pid << endl; rcv_thread_arg->st = PROCESSTIMEOUT; p->RemoveFromUpSet(pid); } else if (num_bytes == 0) { //connection closed // cout << "P" << p->get_pid() << ": Connection closed by P" << pid << endl; // if participant closes connection, it is equivalent to it crashing // can treat it as TIMEOUT // TODO: verify argument rcv_thread_arg->st = PROCESSTIMEOUT; p->RemoveFromUpSet(pid); //TODO: handle connection close based on different cases } else { buf[num_bytes] = '\0'; cout << "P" << p->get_pid() << ": STATE received from P" << pid << ": " << buf << endl; string extracted_msg; int received_tid; // in this case, we don't care about the received_tid, // because it will surely be for the transaction under consideration p->ExtractMsg(string(buf), extracted_msg, received_tid); ProcessState msg = static_cast<ProcessState>(atoi(extracted_msg.c_str())); rcv_thread_arg->st = msg; //assumes that correct message type is sent by participant // if (msg==) { // it's a YES // received_msg_type = YES; // } else if (extracted_msg == msg2) { // it's a NO // received_msg_type = NO; // } else { // //TODO: take actions appropriately, like check log for previous transaction decision. // cout << "P" << p->get_pid() << ": Unexpected msg received from P" << pid << endl; // received_msg_type = ERROR; // } } } // cout << "P" << p->get_pid() << ": Receive thread exiting for P" << pid << endl; return NULL; }
// thread for receiving SR/DR messages from one process void* ReceiveUp(void* _arg) { ReceiveSDRUpThreadArgument* arg = (ReceiveSDRUpThreadArgument*)_arg; Process* p = arg->p; int for_whom = arg->for_whom; char buf[kMaxDataSize]; int num_bytes; pthread_t sr_response_thread; set<string> many_messages; ofstream outf("log/up/" + to_string(p->get_pid()) + "from" + to_string(for_whom)); if (!outf.is_open()) cout << "Failed to open log file for up" << endl; outf<<"All set to receive"<<endl; while (true) { // cout<<"in "<<p->get_pid()<<"; "<<for_whom<<" fd is "<<p->get_up_fd(for_whom)<<endl; if ((num_bytes = recv(p->get_up_fd(for_whom), buf, kMaxDataSize - 1, 0)) == -1) { // cout << "P" << p->get_pid() << ": ERROR in receiving UP for P" << for_whom << endl; // p->RemoveFromUpSet(for_whom); } else if (num_bytes == 0) { //connection closed // cout << "P" << p->get_pid() << ": UP connection closed by P" << for_whom << endl; // p->RemoveFromUpSet(for_whom); } else { buf[num_bytes] = '\0'; string bufstring(buf); vector<string> all_msgs = split(bufstring, '$'); for (auto iter = all_msgs.begin(); iter != all_msgs.end(); iter++) { many_messages.insert(*iter); } string extracted_msg; int recvd_tid; for(auto iter = many_messages.begin(); iter!=many_messages.end(); iter++) { p->ExtractMsg(*iter, extracted_msg, recvd_tid); outf << "P" << p->get_pid() << ": UP recevd from P" << for_whom << ": " << *iter << endl; if (extracted_msg == kUpReq && recvd_tid == p->get_transaction_id()) { //upreq sent only in total failure. means everyone is in same trans. //if lower upreq got, ignore p->SendMyUp(for_whom); } else {//up set received // outf<<"Up Set received "<<extracted_msg<<endl; p->all_up_sets_[for_whom] = ConvertStringToSet(extracted_msg); // outf<<"up set assigned "<< ConvertSetToString(p->all_up_sets_[for_whom])<<endl; } } } usleep(kGeneralSleep); } }
// thread for receiving ACK messages from ONE participant void* ReceiveAckFromParticipant(void* _rcv_thread_arg) { ReceiveThreadArgument *rcv_thread_arg = (ReceiveThreadArgument *)_rcv_thread_arg; int pid = rcv_thread_arg->pid; int tid = rcv_thread_arg->transaction_id; string msg1 = rcv_thread_arg->expected_msg1; //ACK string msg2 = rcv_thread_arg->expected_msg2; //NULL Process *p = rcv_thread_arg->p; char buf[kMaxDataSize]; int num_bytes; //TODO: write code to extract multiple messages fd_set temp_set; FD_ZERO(&temp_set); FD_SET(p->get_fd(pid), &temp_set); int fd_max = p->get_fd(pid); int rv; rv = select(fd_max + 1, &temp_set, NULL, NULL, (timeval*)&kTimeout); if (rv == -1) { //error in select // cout << "P" << p->get_pid() << ": ERROR in select() for P" << pid << strerror(errno)<< endl; rcv_thread_arg->received_msg_type = TIMEOUT; p->RemoveFromUpSet(pid); } else if (rv == 0) { //timeout rcv_thread_arg->received_msg_type = TIMEOUT; p->RemoveFromUpSet(pid); } else { // activity happened on the socket if ((num_bytes = recv(p->get_fd(pid), buf, kMaxDataSize - 1, 0)) == -1) { // cout << "P" << p->get_pid() << ": ERROR in receiving for P" << pid << endl; rcv_thread_arg->received_msg_type = TIMEOUT; p->RemoveFromUpSet(pid); } else if (num_bytes == 0) { //connection closed // cout << "P" << p->get_pid() << ": Connection closed by P" << pid << endl; // if participant closes connection, it is equivalent to it crashing // can treat it as TIMEOUT // TODO: verify argument rcv_thread_arg->received_msg_type = TIMEOUT; p->RemoveFromUpSet(pid); //TODO: handle connection close based on different cases } else { buf[num_bytes] = '\0'; cout << "P" << p->get_pid() << ": ACK received from P" << pid << endl; string extracted_msg; int received_tid; // in this case, we don't care about the received_tid, // because it will surely be for the transaction under consideration p->ExtractMsg(string(buf), extracted_msg, received_tid); if (extracted_msg == msg1) { // it's an ACK rcv_thread_arg->received_msg_type = ACK; } else { //TODO: take actions appropriately, like check log for previous transaction decision. timeval timeofday; gettimeofday(&timeofday, NULL); cout << "P" << p->get_pid() << ": Expecting ack. Unexpected msg received from P" << pid << buf<< " at "<<timeofday.tv_sec<<"."<<timeofday.tv_usec<<endl; rcv_thread_arg->received_msg_type = ERROR; } } } // cout << "P" << p->get_pid() << ": Receive thread exiting for P" << pid << endl; return NULL; }