Example #1
0
int dsm_send_msg(int nodefd, dsm_message_t *msg)
{
	binn *obj;
	
	obj = binn_object();
	binn_object_set_int32(obj, DSM_MSG_KEY_TYPE, msg->type);

	switch (msg->type) {
		case CONNECT:
			binn_object_set_int32(obj, DSM_MSG_KEY_BITNESS, msg->connect_args.bitness);
			binn_object_set_int32(obj, DSM_MSG_KEY_PAGESIZE, msg->connect_args.pagesize);
			break;
		case CONNECT_ACK:
			binn_object_set_int16(obj, DSM_MSG_KEY_BITNESS, msg->connect_ack_args.bitness_ok);
			binn_object_set_int16(obj, DSM_MSG_KEY_PAGESIZE, msg->connect_ack_args.pagesize_ok);
			binn_object_set_int32(obj, DSM_MSG_KEY_PAGECOUNT, msg->connect_ack_args.page_count);
			break;
		case LOCKPAGE:
			binn_object_set_int32(obj, DSM_MSG_KEY_PAGEID, msg->lockpage_args.page_id);
			binn_object_set_int16(obj, DSM_MSG_KEY_RIGHTS, msg->lockpage_args.access_rights);
			break;
		case INVALIDATE:
			binn_object_set_int32(obj, DSM_MSG_KEY_PAGEID, msg->invalidate_args.page_id);
			break;
		case INVALIDATE_ACK:
			binn_object_set_int32(obj, DSM_MSG_KEY_PAGEID, msg->invalidate_ack_args.page_id);
			break;
		case GIVEPAGE:
			binn_object_set_int32(obj, DSM_MSG_KEY_PAGEID, msg->givepage_args.page_id);
			binn_object_set_int16(obj, DSM_MSG_KEY_RIGHTS, msg->givepage_args.access_rights);
			binn_object_set_blob(obj, DSM_MSG_KEY_DATA, msg->givepage_args.data, dsm_g->mem->pagesize);
			break;
		case SYNC_BARRIER:
			binn_object_set_int16(obj, DSM_MSG_KEY_BARRIER, msg->sync_barrier_args.slave_to_wait);
		case BARRIER_ACK:
			break;
		case TERMINATE:
			break;
		default:
        	log("Unknown message type to send !\n");
        	return -1;
	}

	if(dsm_send(nodefd, binn_ptr(obj), binn_size(obj)) < 0) {
		log("Could not send to node %d message type: %d\n", nodefd, msg->type);
		return -1;
	}
	binn_free(obj);

	return 0;
}
void commit_comes(int sessionfd, const char* msg, int RW){
	long pageaddr = *(long*)msg;
	block_signal(SIGALRM);
	// printf(" invalidation responce at %lx\n", pageaddr);
	q_dta_t* the_queue = &req_queues[addr_to_pagenum (dsm_heaptop, pageaddr, dsm_pagesize)];
	if (RW == QUEUE_WRITE){
		memcpy((void*)pageaddr, msg + sizeof(long), dsm_pagesize);
		assert(the_queue->update_pending);

		if (the_queue->listlen){
			if (the_queue->num_parallel_readers){
				for (int i = 0;i < the_queue->num_parallel_readers;i++){
					int posval = the_queue->fd_queue[(i + the_queue->currhead) % (2*NumNode)];
					dsm_send(0,dsm_pagesize,SERVER_PAGE,(char*)pageaddr,ABS(posval));
				}
			}else{
					dsm_send(0, dsm_pagesize, SERVER_PAGE, (char*)pageaddr, ABS(queue_top(the_queue)));		
			}
		}
	}	
	the_queue->update_pending = 0;
	unblock_signal(SIGALRM);
}
/*
 *	This function executes in signal handler context
 */
static void timerhandler(int whatever){
	// printf("timer tick\n");	

	if (clock_state == TIMER_STOPPED) return;
	long invalbuf[NUM_PAGES];
	int numinval = 0;
	int posval;
	clock_stop();

	for (int i = 0; i < NumNode; ++i){
		numinval = 0;
		for (int curr = activehead, last = curr;curr != -1; 
				 last = curr,curr = req_queues[curr].next_active){
			if (curr == activehead){
				last = curr;
			}
			if (curr_owners[curr] != i){	
				continue;
			}
			q_dta_t* the_queue = &(req_queues[curr]);
			if (the_queue->update_pending){	
				continue;
			}
			if (!the_queue->num_writers) continue;
			if (popped[curr]) continue;
			//better be true
			
			assert(the_queue->num_writers);
			qaddr = pagenum_to_addr(dsm_heaptop, curr, dsm_pagesize);
			int sessionfd = pop_queue(the_queue);
			popped[curr] = 1;
			
			if (!READ_REQ(sessionfd)){
				the_queue->num_writers--;
				//was writing; need to wait for update

				if (the_queue->listlen && !the_queue->num_writers){
					for (int i = 0;i < the_queue->listlen;i++){		
						the_queue->num_parallel_readers++;
					}
				}
				the_queue->update_pending = 1;
			}else{
				
				if (the_queue->num_parallel_readers > 0){
					//read requests granted before any writers came along
					//always at front of queue
					the_queue->num_parallel_readers --;		
				}
				
				if (the_queue->listlen && !the_queue->num_parallel_readers){
					int nextsessionfd = queue_top(the_queue);	
					dsm_send(0, dsm_pagesize, SERVER_PAGE,(char*)pagenum_to_addr(dsm_heaptop,curr,dsm_pagesize) , ABS(nextsessionfd));
				}
			}
			
			if ((!the_queue->listlen) || ABS(queue_top(the_queue)) != nid_to_sessionfd[i]){ 
				invalbuf[numinval++] = curr * dsm_pagesize + dsm_heaptop;
			}
			if (the_queue->listlen){
				//transfer ownership
				int tmp;
				posval = queue_top(the_queue);
				curr_owners[curr] = (short)(long)hash_get((void*)(long)ABS(posval),sessionfd_to_nid,&tmp);
				assert(tmp);
			}else{
				curr_owners[curr] = -1;
			}

			if (!the_queue->num_writers){
				if (the_queue->listlen){
					the_queue->q_state = QUEUE_READERS; 
				}else{
					the_queue->q_state = QUEUE_EMPTY;
				}
				//take off the active list
				if (curr == last){
					//delete from head
					activehead = req_queues[curr].next_active;

				}else{
					req_queues[last].next_active = req_queues[curr].next_active;
					curr = last;
				}
			}
		}
		//TODO: send invalidation message to client
		
		if (numinval) {
			//printf("about to send %d inv to %d\n",numinval, nid_to_sessionfd[i]);	
			dsm_send(0, sizeof(long)*numinval,SERVER_INVALIDATE, (char*)invalbuf, nid_to_sessionfd[i]);
		}	
	}
	if (activehead != -1){
		clock_start();
	}

	our_memset (popped, 0, sizeof(char)*NUM_PAGES);	

	//printf("END timer tick\n");
}
void queue_for_page(int sessionfd, long pagenum, int RW){
    block_signal(SIGALRM);
    
    q_dta_t* the_queue = &(req_queues[pagenum]);
	assert(the_queue->num_parallel_readers <= the_queue->listlen);
	int make_active = 0;
	qaddr = pagenum_to_addr(dsm_heaptop, pagenum, dsm_pagesize);	
	add_to_queue(RW*sessionfd, the_queue);

    if (RW == QUEUE_READ){
        switch (the_queue->q_state){
            case QUEUE_EMPTY:
            {
				int found;
				curr_owners[pagenum] = (short)(long)hash_get((void*)(long)sessionfd, sessionfd_to_nid,&found);
			
				assert(found);	
				the_queue->q_state = QUEUE_READERS;
				if (!the_queue->update_pending){
					long pagebegin = pagenum_to_addr(dsm_heaptop,pagenum, dsm_pagesize); 
					dsm_send(0,dsm_pagesize,SERVER_PAGE,(char*)pagebegin,sessionfd);
				}	
				the_queue->num_parallel_readers = 1;
				break;
            }
            case QUEUE_WRITERS:
			{
				break;
            }
            case QUEUE_READERS:
            {
				if (!the_queue->update_pending){
					long pagebegin = pagenum_to_addr(dsm_heaptop,pagenum, dsm_pagesize);
					dsm_send(0,dsm_pagesize,SERVER_PAGE,(char*)pagebegin,sessionfd);
					
				}
				the_queue->num_parallel_readers++;
				break;
            }
            default:break;
        }
    }else{
		the_queue->num_writers ++;
		switch (the_queue->q_state){
            case QUEUE_EMPTY:
            {
			
				int found;
				curr_owners[pagenum] = (short)(long)hash_get((void*)(long)sessionfd, sessionfd_to_nid,&found);
					
				assert(found);	
				the_queue->q_state = QUEUE_WRITERS;
				make_active = 1;
				if (!the_queue->update_pending){
					long pagebegin = pagenum_to_addr(dsm_heaptop,pagenum, dsm_pagesize);
					dsm_send(0,dsm_pagesize,SERVER_PAGE,(char*)pagebegin,sessionfd);
				}
				break;
            }
            case QUEUE_WRITERS:
			{		
				break;
            }
            case QUEUE_READERS:
            {
				the_queue->q_state = QUEUE_WRITERS;
				make_active = 1;
				break;
            }
            default:break;
        }
    }
	
	if (make_active){
		req_queues[pagenum].next_active = activehead;
		activehead = pagenum;
		clock_start();
	}
    unblock_signal(SIGALRM);
}