コード例 #1
0
ファイル: skier.c プロジェクト: vincentvanbush/ski-lift
void mcast_accept_msg(struct state_info info) {
	char diag[200];
	GQueue *waiting_req_q = (*info.my_lift_number == LIFT_1) ? info.waiting_req_q1 : info.waiting_req_q2;
	int len = g_queue_get_length(waiting_req_q);
	// diag_msg(info.mstrtid, info.mytid, "*** 0");
	int *tids = malloc(len * sizeof(int));
	int i = 0;
	sprintf(diag, "*** %d processes awaiting accepts", g_queue_get_length(info.waiting_req_q));
	diag_msg(info.mstrtid, info.mytid, diag);
	while (!g_queue_is_empty(waiting_req_q)) {
		int *tid = g_queue_pop_head(waiting_req_q);
		int *sender_weight_ptr = g_hash_table_lookup(info.skiers_weights, tid);
		int *lift_free = (*info.my_lift_number == LIFT_1) ? info.lift1_free : info.lift2_free;
		*lift_free -= *sender_weight_ptr;
		tids[i] = *tid;
		i++;
		sprintf(diag, "*** mcast MSG_ACCEPT to %d [weight=%d]", *tid, *sender_weight_ptr);
		diag_msg(info.mstrtid, info.mytid, diag);
	}
	*info.local_clock += 1;

	int tag = MSG_ACCEPT;
	pvm_initsend(PvmDataDefault);
	pvm_pkint(&tag, 1, 1);
	pvm_pkint(&info.mytid, 1, 1);
	pvm_pkint(info.local_clock, 1, 1);
	pvm_mcast(tids, len, tag);

	sprintf(diag, "mcast MSG_ACCEPT to %d waiting processes [timestamp=%d]", len, *info.local_clock);
	diag_msg(info.mstrtid, info.mytid, diag);
}
コード例 #2
0
ファイル: skier.c プロジェクト: vincentvanbush/ski-lift
void handle_request(struct msg incoming_msg, struct state_info info) {
	// handle Lamport clocks
	char diag[200];
	update_lamport_recv(incoming_msg.timestamp, info.local_clock);

	int *my_weight_ptr = g_hash_table_lookup(info.skiers_weights, &info.mytid);
	int my_weight = *my_weight_ptr;
	int *sender_weight_ptr = g_hash_table_lookup(info.skiers_weights, &incoming_msg.sender_tid);
	int sender_weight = *sender_weight_ptr;

	if (info.phase != PHASE_WAIT_ACCEPTS) {
		// Always send ACCEPT, don't care about priorities in those phases
		send_accept_msg(incoming_msg.sender_tid, info);
	} else {
		// Send ACCEPT only if:
		// a) my priority is worse than the sender's priority,
		// b) or my priority is better but we both can fit
		// c) or I want the other lift
		if (*info.my_lift_number != incoming_msg.lift_number) { // I want the other lift
			send_accept_msg(incoming_msg.sender_tid, info); return;
		}
		// my priority is worse
		else if (*info.my_request_timestamp > incoming_msg.timestamp) {
			send_accept_msg(incoming_msg.sender_tid, info); return;
		}
		else if (*info.my_request_timestamp == incoming_msg.timestamp) {
			if (incoming_msg.timestamp % 2 == 0) { // admit the heavier skier
				if (my_weight > sender_weight) {
					send_accept_msg(incoming_msg.sender_tid, info); return;
				}
			}
			else { // admit the lighter skier
				if (my_weight <= sender_weight) {
					send_accept_msg(incoming_msg.sender_tid, info);	return;
				}
			}
		}

		// my priority is better
		// ELSE
		if (my_weight + sender_weight <= *info.lift_free) {
			send_accept_msg(incoming_msg.sender_tid, info);
		}
		else { // add the sender to the queue of waiting requests for the lift
			int *tid = malloc(sizeof(int));
			memcpy(tid, &incoming_msg.sender_tid, sizeof(int));
			g_queue_push_tail(info.waiting_req_q, tid);
			int *pushed = g_queue_peek_tail(info.waiting_req_q);
			sprintf(diag, "*** pushed tid=%d", *pushed);
			diag_msg(info.mstrtid, info.mytid, diag);
		}

	}
};
コード例 #3
0
ファイル: skier.c プロジェクト: vincentvanbush/ski-lift
void handle_message(struct msg incoming_msg, struct state_info info) {
	char diag[200];
	sprintf(diag,"receive %s from %d [phase=%s, timestamp=%d, lift_number=%s]",
					stringify(incoming_msg.tag), incoming_msg.sender_tid, stringify(info.phase),
					incoming_msg.timestamp, stringify(incoming_msg.tag == MSG_ACCEPT ? -1 : incoming_msg.lift_number));
	diag_msg(info.mstrtid, info.mytid, diag);

  switch (incoming_msg.tag) {
    case MSG_REQUEST:	handle_request(incoming_msg, info); break;
    case MSG_ACCEPT:	handle_accept (incoming_msg, info); break;
    case MSG_RELEASE:	handle_release(incoming_msg, info); break;
  }
}
コード例 #4
0
ファイル: skier.c プロジェクト: vincentvanbush/ski-lift
void handle_accept (struct msg incoming_msg, struct state_info info) {
	char diag[200];

	update_lamport_recv(incoming_msg.timestamp, info.local_clock);

	int *my_weight_ptr = g_hash_table_lookup(info.skiers_weights, &info.mytid);
	int my_weight = *my_weight_ptr;
	int *sender_weight_ptr = g_hash_table_lookup(info.skiers_weights, &incoming_msg.sender_tid);
	int sender_weight = *sender_weight_ptr;

	// decrement the pending_accepts_sum by sender weight
	*info.pending_accepts_sum -= sender_weight;
	*info.accepts_received += 1;

	sprintf(diag, "*** my_lift_number=%s", stringify(*info.my_lift_number));
	diag_msg(info.mstrtid, info.mytid, diag);
	int *lift_free = (*info.my_lift_number == LIFT_1 ? info.lift1_free : info.lift2_free);

	sprintf(diag, "free space on lift %d, pending accepts sum %d, accepts received %d, my weight %d",
					*lift_free, *info.pending_accepts_sum, *info.accepts_received, my_weight);
	diag_msg(info.mstrtid, info.mytid, diag);

	if (*lift_free - *info.pending_accepts_sum >= my_weight) {
		sprintf(diag, "can enter lift now");
		*lift_free -= my_weight;
    *info.can_enter_lift = 1;
	} else if (g_hash_table_size(info.skiers_weights) - 1 == *info.accepts_received) {
		sprintf(diag, "n-1 accepts - can enter lift now");
		*lift_free -= my_weight;
		*info.can_enter_lift = 1;
	}	else {
		sprintf(diag, "not entering the lift yet");
		*info.can_enter_lift = 0;
	}
	diag_msg(info.mstrtid, info.mytid, diag);
};
コード例 #5
0
ファイル: skier.c プロジェクト: vincentvanbush/ski-lift
void bcast_request_msg(struct state_info info) {
	int tag = MSG_REQUEST;
	*info.local_clock += 1;
	pvm_initsend(PvmDataDefault);
	pvm_pkint(&tag, 1, 1);
	pvm_pkint(&info.mytid, 1, 1);
	pvm_pkint(info.local_clock, 1, 1);
	pvm_pkint(info.my_lift_number, 1, 1);
	pvm_bcast(GROUP, MSG_REQUEST);

	*info.my_request_timestamp = *info.local_clock;

	char diag[200];
	sprintf(diag, "bcast MSG_REQUEST [timestamp=%d, lift_number=%s]", *info.local_clock, stringify(*info.my_lift_number));
	diag_msg(info.mstrtid, info.mytid, diag);
}
コード例 #6
0
ファイル: skier.c プロジェクト: vincentvanbush/ski-lift
void send_accept_msg(int dest_tid, struct state_info info) {
	int *sender_weight_ptr = g_hash_table_lookup(info.skiers_weights, &dest_tid);
	int old_free = *info.lift_free;
	*info.lift_free -= *sender_weight_ptr;
	*info.local_clock += 1;

	int tag = MSG_ACCEPT;
	pvm_initsend(PvmDataDefault);
	pvm_pkint(&tag, 1, 1);
	pvm_pkint(&info.mytid, 1, 1);
	pvm_pkint(info.local_clock, 1, 1);
	pvm_send(dest_tid, tag);

	char diag[200];
	sprintf(diag, "sent MSG_ACCEPT to %d [timestamp=%d], was %d now %d",
					dest_tid, *info.local_clock, old_free, *info.lift_free);
	diag_msg(info.mstrtid, info.mytid, diag);
}
コード例 #7
0
ファイル: skier.c プロジェクト: vincentvanbush/ski-lift
void bcast_release_msg(struct state_info info) {
	int tag = MSG_RELEASE;
	*info.local_clock += 1;
	pvm_initsend(PvmDataDefault);
	pvm_pkint(&tag, 1, 1);
	pvm_pkint(&info.mytid, 1, 1);
	pvm_pkint(info.local_clock, 1, 1);
	pvm_pkint(info.my_lift_number, 1, 1);
	pvm_bcast(GROUP, MSG_RELEASE);

	// Unallocate space on the lift
	int *my_weight_ptr = g_hash_table_lookup(info.skiers_weights, &info.mytid);
	int my_weight = *my_weight_ptr;
	int *lift_free = (*info.my_lift_number == LIFT_1 ? info.lift1_free : info.lift2_free);
	*lift_free += my_weight;

	char diag[200];
	sprintf(diag, "bcast MSG_RELEASE [timestamp=%d, lift_number=%s]", *info.local_clock, stringify(*info.my_lift_number));
	diag_msg(info.mstrtid, info.mytid, diag);
}
コード例 #8
0
ファイル: hash.c プロジェクト: apiou/cogen
static void
hash_table_resize(hash_table * hash_t)
{
	hash_node **new_nodes;
	hash_node *node;
	hash_node *next;
	long hash_val;
	long new_size;
	long i;

	if ((hash_t->size >= 3 * hash_t->nnodes && hash_t->size > HASH_TABLE_MIN_SIZE)
	    || (3 * hash_t->size <= hash_t->nnodes && hash_t->size < HASH_TABLE_MAX_SIZE))
	{

		new_size = get_closest(hash_t->nnodes);

		new_nodes = (hash_node **) diag_malloc(sizeof(hash_node *) * new_size);
		if (new_nodes == NULL)
		{
			diag_msg("Unable to allocate memory\n");
			return;
		}
		memset(new_nodes, 0, sizeof(hash_node *) * new_size);

		for (i = 0; i < hash_t->size; i++)
			for (node = hash_t->nodes[i]; node; node = next)
			{
				next = node->next;

				hash_val = (*hash_t->hash_func) (node->key, new_size);

				node->next = new_nodes[hash_val];
				new_nodes[hash_val] = node;
			}

		diag_free(hash_t->nodes);
		hash_t->nodes = new_nodes;
		hash_t->size = new_size;
	}
}
コード例 #9
0
ファイル: skier.c プロジェクト: vincentvanbush/ski-lift
main()
{
	GHashTable* skiers_weights = g_hash_table_new(g_str_hash, g_str_equal);
	GQueue *waiting_req_q1 = g_queue_new();
	GQueue *waiting_req_q2 = g_queue_new();

	int first_lift_free, second_lift_free;
	int mytid, mstrtid, myind, number_of_skiers, *tids, first_lift_capacity,
			second_lift_capacity, i, phase, local_clock;
	time_t t;
	char slave_name[NAMESIZE];
	char diag[200];

	struct state_info info;

	mytid = pvm_mytid();
	srand(time(NULL) + mytid);
	gethostname(slave_name, NAMESIZE);
	pvm_joingroup(GROUP);

	get_initial_values(&mstrtid, &number_of_skiers, &tids, &skiers_weights, &first_lift_capacity, &second_lift_capacity);
	info.mstrtid = mstrtid;
	first_lift_free = first_lift_capacity;
	second_lift_free = second_lift_capacity;
	int *my_weight_ptr = g_hash_table_lookup(skiers_weights, &mytid);
	int my_weight = *my_weight_ptr;

	int all_skiers_weight = 0;
	for(i=0; i<number_of_skiers; i++) {
		int *lookup = g_hash_table_lookup(skiers_weights, &tids[i]);
		all_skiers_weight += *lookup;
	}
	all_skiers_weight -= my_weight;
	sprintf(diag, "sum of all other skiers' weights = %d", all_skiers_weight);
	diag_msg(mstrtid, mytid, diag);

	i=0;
	while (tids[i] != mytid) {
		i++;
	}

	pvm_initsend(PvmDataDefault);
	pvm_pkint(&mytid, 1, 1);
	pvm_pkstr(slave_name);

	int *wat_to_send = g_hash_table_lookup(skiers_weights, &mytid);
	pvm_pkint(wat_to_send, 1, 1);
	pvm_send(mstrtid, MSG_SLV);

	// bariera
	local_clock = 0;
	pvm_barrier(GROUP, number_of_skiers);

	int time_to_wait;

	// main loop

	diag_msg(mstrtid, mytid, "entering main loop");
	while (1) {
  	int can_enter_lift = 0;
  	int chosen_lift = -1;
		int accepts_received = 0;
		int my_request_timestamp = -1;
		info.accepts_received = &accepts_received;
		info.my_request_timestamp = &my_request_timestamp;

		phase = PHASE_DOWNHILL;

		struct timeval timeout;
		random_timeout(&timeout, 3, 10);

		struct timeval start_time;
		gettimeofday(&start_time, NULL);

		struct timeval elapsed;
		elapsed.tv_sec = 0;
		elapsed.tv_usec = 0;

		sprintf(diag, "entered %s, time=%zu.%zu", stringify(phase), timeout.tv_sec, timeout.tv_usec);
		diag_msg(mstrtid, mytid, diag);
		while (1) {


			int bufid = pvm_trecv(-1, -1, &timeout);

			if (bufid) {
				// diag_msg(mstrtid, mytid, "Got message in PHASE_DOWNHILL");
				struct msg incoming_msg;
				unpack(&incoming_msg);

				int *sender_weight = g_hash_table_lookup(skiers_weights, &incoming_msg.sender_tid);

				// handle the message accordingly
        		prepare_info(&info, mytid, &local_clock, phase, &chosen_lift, &can_enter_lift,
                     &first_lift_free, &second_lift_free, incoming_msg,
										 waiting_req_q1, waiting_req_q2);
        		info.skiers_weights = skiers_weights;
        		handle_message(incoming_msg, info);
			}


			// break the loop if time elapsed is more than the timeout, else wait for another message
			struct timeval current_time;
			gettimeofday(&current_time, NULL);

			timeval_subtract(&elapsed, &current_time, &start_time);
			if (elapsed.tv_sec * 1000000 + elapsed.tv_usec >= timeout.tv_sec * 1000000 + timeout.tv_usec)
				break;
			else
				timeval_subtract(&timeout, &timeout, &elapsed);
		}

		// want to go up
		diag_msg(mstrtid, mytid, "");
		phase = PHASE_WAIT_REQUEST;

		// choose the lift (1 or 2)
		// determine if we can fit on the lift (based on our knowledge from the accepts we had sent)

		sprintf(diag, "entered PHASE_WAIT_REQUEST, weight=%d, LIFT_1=%d, LIFT_2=%d",my_weight,first_lift_free,second_lift_free);
		diag_msg(mstrtid, mytid, diag);

		if (my_weight > first_lift_free && my_weight > second_lift_free) {
			// no lift for us
			// wait for RELEASE messages until we can fit in the lift
			// meanwhile: handle all incoming messages, responding accordingly (ALWAYS respond with accepts)
			while (1) {
				sprintf(diag, "no space in lifts, weight=%d, LIFT_1=%d, LIFT_2=%d",my_weight,first_lift_free,second_lift_free);
				diag_msg(mstrtid, mytid, diag);

				int bufid = pvm_recv(-1, -1);
				struct msg incoming_msg;
				unpack(&incoming_msg);

				prepare_info(&info, mytid, &local_clock, phase, &chosen_lift, &can_enter_lift,
                     &first_lift_free, &second_lift_free, incoming_msg,
										 waiting_req_q1, waiting_req_q2);
				info.skiers_weights = skiers_weights;
        handle_message(incoming_msg, info);

				// now check if we should break the loop and go to the next phase!
				if (chosen_lift == LIFT_1 || chosen_lift == LIFT_2) {
					sprintf(diag, "weight=%d, LIFT_1=%d, LIFT_2=%d, choosing %s",
									my_weight, first_lift_free, second_lift_free, stringify(chosen_lift));
					diag_msg(mstrtid, mytid, diag);

					// broadcast a request with our chosen lift and go to (*)
					bcast_request_msg(info);
					break;
				}
			}

		}
		else { // if there is a fitting lift
			if (my_weight <= first_lift_free && my_weight > second_lift_free) { // can only go to first lift
				chosen_lift = LIFT_1;
			}
			else if (my_weight > first_lift_free && my_weight <= second_lift_free) { // can only go to second lift
				chosen_lift = LIFT_2;
			}
			else {	// can go to either lift - worst fit
				if (first_lift_free > second_lift_free)
					chosen_lift = LIFT_1;
				else if (first_lift_free < second_lift_free)
					chosen_lift = LIFT_2;
				else // equal
					chosen_lift = (rand() % 2 == 1) ? LIFT_1 : LIFT_2;
			}

			info.my_lift_number = &chosen_lift;
			info.mytid = mytid;
			info.local_clock = &local_clock;
			info.skiers_weights = skiers_weights;

			// broadcast a request with our chosen lift and go to (*)
			bcast_request_msg(info);
			// sprintf(diag,"So I am here just before broadcasting REQUEST and I choose lift %d and in info %d",chosen_lift, *info.my_lift_number);
			sprintf(diag, "weight=%d, LIFT_1=%d, LIFT_2=%d, choosing %s",
							my_weight, first_lift_free, second_lift_free, stringify(chosen_lift));
			diag_msg(mstrtid, mytid, diag);
		}

		sprintf(diag, "*** chosen_lift=%s", stringify(chosen_lift));

		// waiting for accepts (*)
    // wait for enough accepts or just as much as required to be sure that we can get in
    // meanwhile: handle all incoming messages, responding accordingly (not send back accept only to those with worse priority that can't fit together with us)
		// diag_msg(mstrtid, mytid, "entering PHASE_WAIT_ACCEPTS");
		phase = PHASE_WAIT_ACCEPTS;
		int pending = all_skiers_weight;
		info.pending_accepts_sum = &pending;

		sprintf(diag, "entered PHASE_WAIT_ACCEPTS, lift=%s", stringify(chosen_lift));
		diag_msg(mstrtid, mytid, diag);

		while (1) {
			int bufid = pvm_recv(-1, -1);
			struct msg incoming_msg;
			unpack(&incoming_msg);

			prepare_info(&info, mytid, &local_clock, phase, &chosen_lift, &can_enter_lift,
									&first_lift_free, &second_lift_free, incoming_msg,
									waiting_req_q1, waiting_req_q2);
      handle_message(incoming_msg, info);

			// check if there are enough amount of acceptes - can break the loop and go to the critical section
			if (can_enter_lift) {
				break;
			}
		}

		// random waiting up to the hill - critical section
		phase = PHASE_CRITICAL;

		random_timeout(&timeout, 3, 10);

		gettimeofday(&start_time, NULL);

		elapsed.tv_sec = 0;
		elapsed.tv_usec = 0;

		sprintf(diag, "entered PHASE_CRITICAL, lift=%s, time=%zu.%zu",
						stringify(chosen_lift), timeout.tv_sec, timeout.tv_usec);
		diag_msg(mstrtid, mytid, diag);

		while (1) {
			int bufid = pvm_trecv(-1, -1, &timeout);
			if (bufid) {
				// unpack the received message
				struct msg incoming_msg;
				// int msgtag = -1, sender_tid = -1, lift_number = -1, timestamp = -1;
				unpack(&incoming_msg);

				// handle the message accordingly
				prepare_info(&info, mytid, &local_clock, phase, &chosen_lift, &can_enter_lift,
                     &first_lift_free, &second_lift_free, incoming_msg,
										 waiting_req_q1, waiting_req_q2);
        handle_message(incoming_msg, info);
			}

			// break the loop if time elapsed is more than the timeout, else wait for another message
			struct timeval current_time;
			gettimeofday(&current_time, NULL);

			timeval_subtract(&elapsed, &current_time, &start_time);
			if (elapsed.tv_sec * 1000000 + elapsed.tv_usec >= timeout.tv_sec * 1000000 + timeout.tv_usec)
				break;
			else
				timeval_subtract(&timeout, &timeout, &elapsed);
		}

		// release - broadcast the RELEASE message to all others
		info.mytid = mytid;
		info.local_clock = &local_clock;
		info.my_lift_number = &chosen_lift;
		bcast_release_msg(info);

		// send all the requests stored in the queue (mcast automatically clears it)
		mcast_accept_msg(info);
	}

	pvm_exit();
}