예제 #1
0
void* rms_manager(void* arg) {
	//init
	int 	nfound;
	int 	ret;
	int		err;
	int		itr;
	int		ipc_read;
	int		count;
	int 	gottime;
	char 	*data;
	float   t1;
	float   t2;
	fd_set	readset;
	struct 	timeval timeout;
	struct 	timeval ratechk;
	unsigned long 	*keys;
	unsigned long 	*seq;

	rms_meta_msg *msg;
	rms_meta_peer *peer;
	int		addr_len;
	rms_msg_hbeat *hbeat;

	rmscb *rmsb = (rmscb*)arg;

	gottime = 0;

	while(rmsb->active) {
		FD_ZERO(&readset);
		FD_SET(rmsb->ipc_sock, &readset);
		FD_SET(rmsb->mcast_sock, &readset);

		timeout.tv_sec	= 1;
		timeout.tv_usec = 0;

		nfound= select(rmsb->maxsock, &readset, (fd_set*)0, (fd_set*)0, &timeout);

		if(nfound > 0) {
			//available to read on mcast port
			if((nfound = FD_ISSET(rmsb->mcast_sock, &readset)) > 0) {
				msg = alloc_meta_msg();
				ret = recvfrom(rmsb->mcast_sock,
						&msg->buf,
						msg->size,
						0,
						(struct sockaddr*)&rmsb->recv_addr,
						&addr_len);
				printf("\n\tRMC: recvd %d bytes from %ld",
					ret,
					rmsb->recv_addr.sin_addr.s_addr);
				if(ret < sizeof(rms_msg_hdr)) {
					//not enough data
					continue;
				}
				msg->hdr->length = ntohs(msg->hdr->length);
				msg->hdr->sequence = ntohl(msg->hdr->sequence);
				msg->hdr->id  = ntohl(msg->hdr->id);
				if(ret < msg->hdr->length + sizeof(rms_msg_hdr)) {
					//not enough data
					continue;
				}
				switch(msg->hdr->type) {
				case RMS_DATA:
					if(!htbl_get(rmsb->ht_peers, msg->hdr->id, (void*)&peer)) {
						//peer not registered, drop packet
						release_meta_msg(msg);
					}
					else {
					peer->sequence_sent = msg->hdr->sequence;
					if(peer->sequence_rcvd + 1 != msg->hdr->sequence) {
						//gap in sequence num
						if(peer->sequence_rcvd < msg->hdr->sequence) {
							//cache msg
							htbl_put(peer->ht_unseq_msgs, msg->hdr->sequence, msg);

							//send NACK
							msg = alloc_meta_msg();
							send_nack(rmsb, peer, msg);
						}
						//else retransmitted data, drop packet
						release_meta_msg(msg);
					}
					else {
						//in sequence
						//syncqueue_signal_data(rmsb->inmsgq, msg);
						nfound = msg->hdr->length;
						ret = send(rmsb->ipc_sock, &nfound, sizeof(int),0);
						ret = 0;
						while(ret < nfound) {
							ret+=send(rmsb->ipc_sock, msg->data+ret, nfound-ret, 0);
						}
						peer->sequence_rcvd++;

						//release out of sequence data if any
						while(htbl_remove(peer->ht_unseq_msgs, peer->sequence_sent, (void*)&msg)) {
							//syncqueue_signal_data(rmsb->inmsgq, msg);
							nfound = msg->hdr->length;
							ret = send(rmsb->ipc_sock, &nfound, sizeof(int),0);
							ret = 0;
							while(ret < nfound) {
								ret+=send(rmsb->ipc_sock, msg->data+ret, nfound-ret, 0);
							}
							peer->sequence_rcvd++;
						}
					}}
					break;

				case RMS_HEARTBEAT:
					hbeat = (rms_msg_hbeat*) msg->data;
					data = msg->data + sizeof(rms_msg_hbeat);
					if(!htbl_get(rmsb->ht_peers, msg->hdr->id, (void*)&peer)) {
						//peer not registered, register it
						if(hbeat->namelen) {
							rms_meta_peer_init(&peer, msg->data, msg->hdr->id);
						}
						else {
							rms_meta_peer_init(&peer, "noname", msg->hdr->id);
						}

						htbl_put(rmsb->ht_peers, peer->id, peer);
						mqueue_add(rmsb->mq_peers, peer);
					}

					peer->lost = ntohs(hbeat->lost);
					//check for namelen
					if(hbeat->namelen) {
						hbeat->namelen = htonl(hbeat->namelen);
						data+=hbeat->namelen;
					}

					//check for acks
					if(hbeat->acks) {
						seq = (unsigned long*)data;
						hbeat->acks = ntohs(hbeat->acks);
						for(itr=0;itr < hbeat->acks; itr++) {
							if(ntohl(seq[itr*2])== rmsb->self->id) {
								peer->sequence_sync = ntohl(seq[itr*2 + 1]);
								break;
							}
						}
						data+=hbeat->acks*2*sizeof(long);
					}

					//check for piggybacked data
					if(hbeat->pgback) {
						hbeat->pgback = ntohs(hbeat->pgback);
					}

					gettimeofday(&timeout, NULL);
					gottime=1;
					peer->last_hbeat.tv_sec = timeout.tv_sec;
					peer->last_hbeat.tv_usec = timeout.tv_usec;
					if(peer->sequence_sent + 1 != msg->hdr->sequence) {
						//gap in sequence num
						if(peer->sequence_sent < msg->hdr->sequence) {
							//send NACK
							send_nack(rmsb, peer, msg);
						}
					}
					release_meta_msg(msg);
					break;

				case RMS_NACK:
					seq = (unsigned long*)msg->data;
					count = seq[0];
					rmsb->ucast_addr.sin_addr.s_addr = htonl(msg->hdr->id);
					for(itr=1; itr <= count; itr++) {
						seq[itr]=ntohl(seq[itr]);
						if(htbl_get(rmsb->outmsgbuf, seq[itr], (void*)&msg)) {
							ret = sendto(rmsb->mcast_sock,
									msg->buf,
									msg->length + sizeof(rms_msg_hdr),
									0,
									(struct sockaddr*) &rmsb->ucast_addr,
									sizeof(rmsb->ucast_addr));
						}
					}
					break;

				case RMS_LEAVE:
					if(htbl_remove(rmsb->ht_peers, msg->hdr->id, (void*)&peer)) {
						//clean up unseq msgs buffer
						count = htbl_count(peer->ht_unseq_msgs);
						keys = (unsigned long*)malloc(count*sizeof(unsigned long));
						memset(keys,0,count*sizeof(unsigned long));
						count = htbl_enum_keys(peer->ht_unseq_msgs, (void*)keys, count);
						for(itr = 0; itr < count; itr++) {
							if(htbl_remove(peer->ht_unseq_msgs, keys[itr], (void*)&msg)) {
								release_meta_msg(msg);
							}
						}
						free(keys);
						mqueue_remove_item(rmsb->mq_peers, peer);
						rms_meta_peer_free(peer);
					}
					break;

				case RMS_ACK:
				case RMS_JOIN:
				case RMS_CERT:
				default:
					//unimplemented options, drop packet
					release_meta_msg(msg);
					break;
				}
			}

			//available to read on ipc port
			if((nfound = FD_ISSET(rmsb->ipc_sock, &readset)) > 0) {
				err = 1;
				ret = recv(rmsb->ipc_sock,
						&ipc_read,
						sizeof(int),
						0);
				if(ret > 0) {
					//alloc buffer
					msg = alloc_meta_msg();
					if(ipc_read > rmsb->bufsize) {
						rmsb->bufsize =  ipc_read * 1.5;
						msg->size = rmsb->bufsize;
						msg->buf = realloc(msg->buf,msg->size);
						msg->hdr = (rms_msg_hdr*)msg->buf;
						msg->data = msg->buf + sizeof(rms_msg_hdr);
					}
					ret = recv(rmsb->ipc_sock,
							&msg->data,
							ipc_read,
							0);
					if(ret == ipc_read) {
						msg->length =  ipc_read;
						msg->hdr->type = RMS_DATA;
						msg->hdr->length = htons(msg->length);
						msg->hdr->sequence = htonl(rmsb->self->sequence_sent);
						msg->hdr->id  = htonl(rmsb->self->id);
						ret = sendto(rmsb->mcast_sock,
								msg->buf,
								ret + sizeof(rms_msg_hdr),
								0,
								(struct sockaddr*) &rmsb->mcast_addr,
								sizeof(rmsb->mcast_addr));
						if (ret > 0) {
							htbl_put(rmsb->outmsgbuf, rmsb->self->sequence_sent, msg);
							rmsb->self->sequence_sent++;
							rmsb->msg_this_sec++;
							err = 0;
						}
					}
				}
				if(err) {
					release_meta_msg(msg);
				}
			}
		}

		//do periodic things
		if(!gottime)
			gettimeofday(&timeout, NULL);
		gottime=0;

		//heartbeat
		if(timeout.tv_sec - rmsb->self->last_hbeat.tv_sec >= rmsb->hbeat_rate) {
			//time for hbeat
			send_hbeat(rmsb, NULL,0);

			//check msg send rate
			t1 = (float)timeout.tv_sec + ((float)timeout.tv_usec)/1000000;
			t2 = (float)rmsb->self->last_hbeat.tv_sec
				+ ((float)rmsb->self->last_hbeat.tv_usec)/1000000;

			rmsb->msg_per_sec = rmsb->msg_this_sec/(t1-t2);

			//calculate heartbeat rate
			rmsb->hbeat_rate  = RMS_RATE_FACTOR / rmsb->msg_per_sec;

			//clamp
			if(rmsb->hbeat_rate > 5)
				rmsb->hbeat_rate = 5;
			else if(rmsb->hbeat_rate < 1)
				rmsb->hbeat_rate = 1;

			rmsb->msg_this_sec = 0;

			rmsb->self->last_hbeat.tv_sec = timeout.tv_sec;
			rmsb->self->last_hbeat.tv_usec = timeout.tv_usec;
		}

		//if acks are used
		if(rmsb->hb_ack) {
			//clear buffers
			count = mqueue_size(rmsb->mq_peers);
			for(itr=0; itr < count; itr++) {
				peer = (rms_meta_peer*) mqueue_peek_at_index(rmsb->mq_peers, itr);
				if(peer->sequence_sync < rmsb->self->sequence_sync);
					rmsb->self->sequence_sync = peer->sequence_sync;
			}
			while(rmsb->oldest_seq < rmsb->self->sequence_sync){
				if(htbl_remove(rmsb->outmsgbuf, rmsb->oldest_seq, (void*)&msg)) {
					release_meta_msg(msg);
				}
				rmsb->oldest_seq++;
			}
		}
	}
	//send leave message
	msg = alloc_meta_msg();
	msg->hdr->type = RMS_LEAVE;
	msg->hdr->length = 0;
	msg->hdr->sequence = htonl(rmsb->self->sequence_sent);
	msg->hdr->id  = htonl(rmsb->self->id);
	ret = sendto(rmsb->mcast_sock,
			msg->buf,
			sizeof(rms_msg_hdr),
			0,
			(struct sockaddr*) &rmsb->mcast_addr,
			sizeof(rmsb->mcast_addr));
	release_meta_msg(msg);
	return 0;
}
예제 #2
0
int  send_hbeat(rmscb *rmsb, void *pgback, int len) {
	int itr;
	int ret;
	int offset;
	rms_msg_hbeat 	*hbeat;
	rms_meta_msg 		*msg;
	char 			*data;
	offset = 0;
	msg = alloc_meta_msg();

	msg->hdr->type = RMS_HEARTBEAT;
	msg->hdr->sequence = htonl(rmsb->self->sequence_sent);
	msg->hdr->id  = htonl(rmsb->self->id);

	hbeat = (rms_msg_hbeat*)msg->data;
	data = msg->data + sizeof(rms_msg_hbeat);
	hbeat->lost = htonl(rmsb->self->lost);

	if(rmsb->hostname) {
		hbeat->namelen = htons(strlen(rmsb->hostname));
		data += sprintf(data,"%s",rmsb->hostname);
		data+=offset;
	}
	else
		hbeat->namelen = 0;

	if(rmsb->hb_ack) {
		rms_meta_peer 		*peer;
		unsigned long *nums = (unsigned long*)data;
		hbeat->acks = mqueue_size(rmsb->mq_peers);
		for(itr=0; itr < hbeat->acks; itr++) {
			peer = (rms_meta_peer*) mqueue_peek_at_index(rmsb->mq_peers, itr);
			nums[itr*2]   = htonl(peer->id);
			nums[itr*2+1] = htonl(peer->sequence_rcvd);
			offset+=2*sizeof(long);
		}
		hbeat->acks = htons(hbeat->acks);
		data+=offset;
	}
	else
		hbeat->acks = 0;

	if(pgback) {
		if(len < (msg->size - (int)(data - msg->buf))) {
			memcpy(data,pgback,len);
			offset+=len;
		}
	}
	else
		hbeat->pgback = 0;

	msg->hdr->length = htons(sizeof(rms_msg_hbeat) + offset);
	ret = sendto(rmsb->mcast_sock,
			msg->buf,
			sizeof(rms_msg_hdr) + sizeof(rms_msg_hbeat) + offset,
			0,
			(struct sockaddr*) &rmsb->mcast_addr,
			sizeof(rmsb->mcast_addr));
	release_meta_msg(msg);

	//clear out out buffer
	rmsb->hb_seq_p3 = rmsb->hb_seq_p2;
	rmsb->hb_seq_p2 = rmsb->hb_seq_p1;
	rmsb->hb_seq_p1 = rmsb->self->sequence_sent;

	while(rmsb->oldest_seq < rmsb->hb_seq_p3){
		if(htbl_remove(rmsb->outmsgbuf,rmsb->oldest_seq,(void*)&msg)) {
			release_meta_msg(msg);
		}
		rmsb->oldest_seq++;
	}
	return ret;
}
예제 #3
0
int main()
{
 void *data;
 char *command1, *command2, *def;
 int result;
 FILE *fp = fopen("hashlog.txt", "w");
 CHTbl *htbl = malloc(sizeof(CHTbl));
 chtbl_init(htbl, 4, g3, vstrcmp, NULL);
 fprintf(fp, "Load factor\tOccupancy\n", (float)(htbl->size/htbl->buckets), htbl->buckets);
 while(1)
 {
  printf(">");
  command1 = malloc(sizeof(char)*10);
  command2 = malloc(sizeof(char)*50);
  def = malloc(sizeof(char)*1000);
  result = (parseline(command1, command2, def));


  switch(result){
   case -1:
    printf("Error: invalid use of 'add'\n");
    free(command2);
    free(def);
    break;
   case -2:
    printf("Error: invalid use of 'delete'\n");
    free(command2);
    free(def);
    break;
   case -3:
    printf("Error: invalid use of 'find'\n");
    free(command2);
    free(def);
    break;
   case -4:
    printf("Error: command not recognized\n");
    free(command2);
    free(def);
    break;
   case -5:
    printf("Error: no filename given");
    free(command2);
    free(def);
   case 1:
    if(!(chtbl_insert(&htbl, command2, def)))
    {
     printf("Added %s to dictionary\n", command2);
     printtolog(fp, htbl);
    }
    else printf("Error - %s not added to dictionary\n", command2);
    break;
   case 2:
    free(def);
    if(!htbl_remove(htbl, command2))
    {
     printf("Deleted %s from dictionary\n", command2);
     printtolog(fp, htbl);
    }
    else printf("Error - %s not found\n", command2);
    free(command2);
    break;
   case 3:
    free(def);
    if(!chtbl_lookup(htbl, command2, &data))
    {
     printf("%s\n", command2);
     printf("%s\n", (char *)data);
    }
    else printf("%s not found in dictionary\n", command2);
    free(command2);
    break;
   case 4:
    free(command2);
    free(def);
    print_table(htbl);
    break;
   case 5:
    free(command1);
    free(command2);
    free(def);
    destroy_table(htbl);
    free(htbl);
    fclose(fp);
    return 0;
    break; 
   case 6:
    if(!readfile(htbl, command2, fp))
     printf("File scanned to dictionary\n");
    else printf("Error - file not scanned\n");
    free(command2);
    break;
   case 7:
    find2(htbl, command2, def);
    free(command2);
    free(def);
    break;
   case 8:
    ptest(htbl, command2, fp);
    break;
   }
 
 free(command1);
 }
}