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 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; }