Ejemplo n.º 1
0
Archivo: mf.c Proyecto: shuowen/OpenNT
/* allocate new MF; retains pointer to pthReal!  Must free via FreeMf (or
   CloseMf which calls FreeMf).  mm set to mmNil.
*/
MF *
PmfAlloc(
    PTH pthReal[],
    char *szTemp,    /* 0 -> use base of pthReal */
    FX fx)
{
    register MF *pmf;

    AssertF(pthReal != 0);

    if (mf1.pthReal == 0)
        pmf = &mf1;
    else if (mf2.pthReal == 0)
        pmf = &mf2;
    else if (mf3.pthReal == 0)
        pmf = &mf3;
    else if (mf4.pthReal == 0)
        pmf = &mf4;
    else
        AssertF(fFalse);

    /* initialize contents which are not already initialized */
    pmf->fx = fx;
    pmf->pthReal = pthReal;
    pmf->fNoBuffering = fFalse;
    pmf->fWritten = fFalse;
    if (szTemp != 0)
        NmCopySz(pmf->nmTemp, szTemp, cchFileMax);

    AssertF(FIsClosedMf(pmf));

    return pmf;
}
// Inserts the reservation into the required track segments
static void reservation_insert(struct reservation_node* reservation, struct location* position, int length, int branch_safety) {
	int node_direction;
	struct track_node* node = location_to_node(track, position);
	if (node->type == NODE_BRANCH) {
		node_direction = switch_table[node->num] == SWITCH_STRAIGHT ? DIR_STRAIGHT : DIR_CURVED;
	} else {
		node_direction = DIR_AHEAD;
	}

	struct track_edge* occupied_edge = &(node->edge[node_direction]);
	int startOffset = position->offset;
	int r_index = 0;
	while (length > 0) {
		int stopOffset = MIN(length + startOffset, occupied_edge->dist);

		if (occupied_edge->src->type == NODE_BRANCH) {
			// The is an edge coming from a branch, so we must make sure we cover the whole
			// length of it so we don't get stuck on the switch
			stopOffset = occupied_edge->dist;
		}

		AssertF(r_index < SEGMENTS_PER_TRAIN, "Too many segments for train reservation");
		// Set the forward direction edge's occupied information
		reservation->reservations[r_index].start = startOffset;
		reservation->reservations[r_index].stop = stopOffset;
		reservation->reservations[r_index].edge = occupied_edge;
		reservation->reservations[r_index].next = occupied_edge->reservation_node;
		occupied_edge->reservation_node = &reservation->reservations[r_index];
		r_index++;

		// Set the reverse direction edge's occupied information
		AssertF(r_index < SEGMENTS_PER_TRAIN, "Too many segments for train reservation");
		reservation->reservations[r_index].start = occupied_edge->dist - stopOffset;
		reservation->reservations[r_index].stop = occupied_edge->dist - startOffset;
		reservation->reservations[r_index].edge = occupied_edge->reverse;
		reservation->reservations[r_index].next = occupied_edge->reverse->reservation_node;
		occupied_edge->reverse->reservation_node = &reservation->reservations[r_index];
		r_index++;


		length = length - (stopOffset - startOffset);

		// If this is a branch and the reservation ends somewhere in the next edge, make
		// sure we take branch safety into consideration
		if (occupied_edge->src->type == NODE_BRANCH) {
			length = MAX(length, branch_safety);
		}

		if (occupied_edge->dest->type == NODE_BRANCH) {
			node_direction = switch_table[occupied_edge->dest->num] == SWITCH_STRAIGHT ? DIR_STRAIGHT : DIR_CURVED;
		} else {
			node_direction = DIR_AHEAD;
		}

		occupied_edge = &occupied_edge->dest->edge[node_direction];
		startOffset = 0;
	}
}
int dist_between_nodes(int start_num, int end_num) {
	struct track_node *start = &track[start_num];
	struct track_node *end = &track[end_num];

	AssertF(track != 0 && start != 0 && end != 0, "BAD INPUT TO dist_betwen_nodes", 0);

	int distance = 0;
	struct track_node *current = start;

	while (current->num != end->num || current->type != end->type) {

		if (current->type == NODE_EXIT) {
			return 0;
		} else if (current->type == NODE_BRANCH) {
			int switch_direction = switch_table[current->num];
			int node_direction = (switch_direction == SWITCH_STRAIGHT ? DIR_STRAIGHT : DIR_CURVED);

			distance += current->edge[node_direction].dist;
			current = current->edge[node_direction].dest;
		} else {
			distance += current->edge[DIR_AHEAD].dist;
			current = current->edge[DIR_AHEAD].dest;
		}

		if (current == start) {
			// HORRY SHIITTu, WE ARE IN A ROOP!
			return -1;
		}

	}

	return distance;
}
Ejemplo n.º 4
0
Archivo: mf.c Proyecto: shuowen/OpenNT
/* Open one of the two static MF structures dedicated for local files.
*/
MF *
OpenLocalMf(
    char *pszLocalFileName)
{
    register MF *pmf;
    int wRetErr;

    if (mfLocal1.fdWrite == fdNil)
        pmf = &mfLocal1;
    else if (mfLocal2.fdWrite == fdNil)
        pmf = &mfLocal2;
    else
    {
        AssertF(fFalse);
        return NULL;
    }
    pmf->pthReal = malloc(strlen(pszLocalFileName) + 1);
    if (pmf->pthReal)
    {
        strcpy(pmf->pthReal, pszLocalFileName);
        pmf->fdWrite = _open(pmf->pthReal, O_APPEND|O_WRONLY|O_CREAT,
                             S_IREAD|S_IWRITE);
    }

    if (pmf->fdWrite == fdNil)
        FatalError("Unable to open file (%s) for write access\n",
                   pszLocalFileName);
    else {
        pmf->pos = SeekMf(pmf, (POS)0, 2);
        pmf->fWritten = fFalse;
    }

    return pmf;
}
int TrackSwitchDirection(int train, int switch_node, int next_node, int tid) {
	int reserved;

	struct track_request_message msg;
	msg.operation = TRACK_OP_SWITCH_DIRECTION;
	msg.train = train;
	msg.node1 = switch_node;
	msg.node2 = next_node;

	AssertF(Send(tid, (char*)&msg, sizeof(msg), (char*)&reserved, sizeof(reserved)) >= 0, "Send() failed in TrainSwitchDirection");
	return reserved;
}
Ejemplo n.º 6
0
Archivo: mf.c Proyecto: shuowen/OpenNT
/* return fTrue if the mf is allocated and otherwise valid */
F
FIsValidMf(
    MF *pmf)
{
    if (pmf != &mfStdin &&
            pmf != &mfStdout &&
            pmf != &mfStderr &&
            pmf != &mfStdlog &&
            pmf != &mfLocal1 &&
            pmf != &mfLocal2 &&
            pmf != &mf1 &&
            pmf != &mf2 &&
            pmf != &mf3 &&
            pmf != &mf4)
        return fFalse;

    if (pmf->pthReal == 0)
        return fFalse;

    /* check for proper configuration */
    switch(pmf->mm)
    {
    default:
        AssertF(fFalse);

    case mmNil:
        break;

    case mmDelTemp:
    case mmInstall:
    case mmInstall1Ed:
    case mmRenTemp:
    case mmRenTempRO:
    case mmRenReal:
    case mmAppToReal:
    case mmCreate:
        if (FEmptyNm(pmf->nmTemp))
            return fFalse;
        break;

    case mmDelReal:
    case mmSetRO:
    case mmSetRW:
        if (!FEmptyNm(pmf->nmTemp))
            return fFalse;
        break;
    }

    if (pmf->fFileLock && pmf->fdWrite < 0)
        return fFalse;

    return fTrue;
}
int next_sensor_node(int start_num,	int direction, int *target_distance) {
	struct track_node *start_node = &track[start_num];

	AssertF(track != 0 && start_node != 0 && target_distance != 0, "BAD INPUT TO NEXT_SENSOR_NODE", 0);

	struct track_node *current = start_node;
	*target_distance = 0;
	while (1) {
		if (current->type == NODE_EXIT) {
			break;
		} else if (current->type == NODE_BRANCH) {

			int switch_direction = switch_table[current->num];
			if (direction != -1) {
				switch_direction = direction;
			}

			AssertF(switch_direction != -1, "SwitchGetDirection returned -1\r");

			int node_direction = (switch_direction == SWITCH_STRAIGHT ? DIR_STRAIGHT : DIR_CURVED);

			*target_distance += current->edge[node_direction].dist;
			current = current->edge[node_direction].dest;
		} else {
			*target_distance += current->edge[DIR_AHEAD].dist;
			current = current->edge[DIR_AHEAD].dest;
		}

		// if the sensor is broken, we must skip this one!
		if (current->type == NODE_SENSOR) {
			return current->num;
		}
		if (current == start_node) {
			// we are in a loop!
			Assert("Next Sensor Node is in a loop!");
		}
	}

	return -1;
}
static int reservation_available(int train, struct track_edge* edge, int startOffset, int stopOffset) {
	// Check if this segment of track is occupied y a train
	AssertF(edge != 0, "res_avail: EDGE PASSED IN IS NULL!");
	struct reservation* r = edge->reservation_node;
	while (r != 0) {
		if (r->train != train &&
				((startOffset >= r->start && startOffset <= r->stop) ||
				(stopOffset >= r->start && stopOffset <= r->stop) ||
				(startOffset <= r->start && stopOffset >= r->stop))) {
			// Now we are really crossing the line. Report that
			// reservation failed!
			return 0;
		}
		r = r->next;
	}
	return 1;
}
static int dist_until_goal(int start_num, int start_offset, int end_num, int end_offset, int max_distance) {
	struct track_node *start = &track[start_num];
	struct track_node *end = &track[end_num];

	AssertF(track != 0 && start != 0 && end != 0, "BAD INPUT TO dist_until_goal", 0);

	int distance = 0 - start_offset;
	struct track_node *current = start;

	while (!(current->num == end->num && current->type == end->type)) {

		if (current->type == NODE_EXIT) {
			return 0;
		} else if (current->type == NODE_BRANCH) {
			int switch_direction = switch_table[current->num];
			int node_direction = (switch_direction == SWITCH_STRAIGHT ? DIR_STRAIGHT : DIR_CURVED);

			distance += current->edge[node_direction].dist;
			current = current->edge[node_direction].dest;
		} else {
			distance += current->edge[DIR_AHEAD].dist;
			current = current->edge[DIR_AHEAD].dest;
		}

		if (current == start) {
			// HORRY SHIITTu, WE ARE IN A ROOP!
			return max_distance;
		}

		if (distance >= max_distance) {
			return max_distance;
		}

	}

	distance += end_offset;

	// make sure distance is >= 0, and <= max_distance:
	return MIN(MAX(0, distance), max_distance);
}
Ejemplo n.º 10
0
Archivo: mf.c Proyecto: shuowen/OpenNT
/* Records the mf (if not already) and makes the mf available for use; we
   ensure that the mf is back the initial state
*/
void
FreeMf(
    MF *pmf)
{
    static char *mpmmsz[] =
    {
        "nil\n",                /* mmNil */
        "delete %@T\n",         /* mmDelTemp */
        "clear %@R\n",          /* mmDelReal */
        "rename %@T %@R\n",     /* mmRenTemp */
        "install %@T %@R\n",    /* mmInstall */
        "renreal %@T %@R\n",    /* mmRenReal */
        "append %@T %@R\n",     /* mmAppToReal */
        "makero %@R\n",         /* mmSetRO */
        "makerw %@R\n",         /* mmSetRW */
        "rename %@T %@R\n",     /* mmRenTempRO ( + makero) */
        "link %@R %@N\n",       /* mmLinkReal */
        "create %@R\n",         /* mmCreate */
        "install1Ed %@T %@R\n"  /* mmInstall1Ed */
    };

    AssertF(FIsClosedMf(pmf));

    if (pmf->mm != mmNil)
    {
        AppendScript(pmf->fx, mpmmsz[pmf->mm], pmf, pmf);
        if (pmf->mm == mmRenTempRO)
            AppendScript(pmf->fx, mpmmsz[mmSetRO], pmf, pmf);
    }

    pmf->mm         = mmNil;
    pmf->fx         = fxNil;
    pmf->pthReal    = 0;
    *pmf->nmTemp    = '\0';
    pmf->fdRead     = fdNil;
    pmf->fdWrite    = fdNil;
    pmf->fFileLock  = fFalse;
    pmf->fNoBuffering = fFalse;
    pmf->fWritten   = fFalse;
}
// Entry point of track-server
void track_server_entry() {

	RegisterAs(TRACK_SERVER);

	// Initialize the track
	track_init();

	// Initialize the reservation list
	reservation_init(train_reservations);

	// So we can update our own cached copy of the switch table
	int switch_courier_tid = CreateSwitchCourier(PRIORITY_HIGHEST - 1);

	int sender_tid;

	// Message buffer large enough to hold the largest message request
	char message_buffer[32];
	while (1) {
		Receive(&sender_tid, message_buffer, sizeof(message_buffer));

		if (sender_tid == switch_courier_tid) {
			// This is an update from the switch server, record the switch that changed
			// so that our cached table of switches is in sync
			int reply = 0;
			Reply(sender_tid, (char*)&reply, sizeof(reply));
			struct switch_report* report = (struct switch_report*)message_buffer;
			switch_table[(int)report->sw] = report->direction;
		} else {
			// API requests to the track_server

			struct track_reply_message reply = {-1, -1};
			int op = *(int*)message_buffer;

			switch(op) {

				// Handle track reservation requests
				case TRACK_OP_RESERVATION: {
					int reply = -1;
					struct reservation_request_message* reservation_msg = (struct reservation_request_message*)message_buffer;

					// Make the location be a sensor and positive offset that fits in the edge
					if (normalize_location(track, switch_table, &reservation_msg->position) != -1) {
						// Check if we can reserve this space for the train
						int status = reservation_verify(reservation_msg->train, &(reservation_msg->position), reservation_msg->length, reservation_msg->branch_safety);
						reply = status;

						if (status == 0) {
							// We succeeded. Reserve the track

							// Find the train's reservation_node
							struct reservation_node* train_r = get_reservation(train_reservations, reservation_msg->train);
							if (train_r != 0) {
								clear_train_reservations(train_r);

								// Add new reservation
								reservation_insert(train_r,
												&(reservation_msg->position),
												reservation_msg->length,
												reservation_msg->branch_safety);
							}
						} else if (status == -2) {
							// Reached max reservation
						}
					} else {
						Printf("Could not normalize\r");
					}

					Reply(sender_tid, (char*)&reply, sizeof(reply));
				} break;

				case TRACK_OP_RESERVATION_STRING: {
					struct reservation_request_message* reservation_msg = (struct reservation_request_message*)message_buffer;
					struct reservation_node* train_r = get_reservation(train_reservations, reservation_msg->train);

					char buf[300];
					*buf = 0; // null termination character
					int len = 0;
					if (train_r != 0) {
						len = reservation_print(train_r, buf);
					}

					Reply(sender_tid, (char*)buf, len); // +1 for null termination char
				} break;

				case TRACK_OP_NODE_IS_RESERVED: {

					struct reservation_request_message* reservation_msg = (struct reservation_request_message*)message_buffer;
					int reserved = node_is_reserved(reservation_msg->train, reservation_msg->position.node);

					Reply(sender_tid, (char*)&reserved, sizeof(reserved));
				} break;

				// Handle requests for calculating the distance between 2 nodes
				case TRACK_OP_TRACK_DISTANCE: {
					struct track_request_message* track_msg = (struct track_request_message*)message_buffer;
					if (track_msg->node1 < TRACK_MAX && track_msg->node2 < TRACK_MAX) {
						reply.distance = dist_between_nodes(track_msg->node1, track_msg->node2);
					}

					Reply(sender_tid, (char*)&reply, sizeof(reply));
				} break;

				case TRACK_OP_TRACK_DISTANCE_UNTIL_GOAL: {
					struct track_request_message* track_msg = (struct track_request_message*)message_buffer;
					int distance = 0;
					if (track_msg->node1 < TRACK_MAX && track_msg->node2 < TRACK_MAX) {
						distance = dist_until_goal(track_msg->node1, track_msg->offset1, track_msg->node2, track_msg->offset2, track_msg->distance);
					}

					Reply(sender_tid, (char*)&distance, sizeof(distance));
				} break;

				// Handle requests for getting the next sensor on the track
				case TRACK_OP_TRACK_NEXT_SENSOR: {
					struct track_request_message* track_msg = (struct track_request_message*)message_buffer;
					if (track_msg->node1 >= A1 && track_msg->node1 <= E16) {
						int distance;
						int next_sensor = next_sensor_node(track_msg->node1, track_msg->node2, &distance);

						reply.node = next_sensor;
						reply.distance = distance;
					}

					Reply(sender_tid, (char*)&reply, sizeof(reply));
				} break;

				case TRACK_OP_NORMALIZE: {
					struct track_request_message *msg = (struct track_request_message*)message_buffer;

					struct location loc;
					loc.node = msg->node1;
					loc.offset = msg->offset1;
					if (normalize_location(track, switch_table, &loc) == -1) {
						Reply(sender_tid, (char*)&loc, 0); // reply size 0 means error!
					}

					Reply(sender_tid, (char*)&loc, sizeof(loc));
				} break;

				// Handle requests for getting the reverse node of a given node
				case TRACK_OP_TRACK_REVERSE_NODE: {
					struct track_request_message* track_msg = (struct track_request_message*)message_buffer;
					if (track_msg->node1 < TRACK_MAX) {
						reply.node = track[track_msg->node1].reverse->num;
					}

					Reply(sender_tid, (char*)&reply, sizeof(reply));
				} break;

				case TRACK_OP_ROUTE: {
					struct track_request_message* track_msg = (struct track_request_message*)message_buffer;
					int train = track_msg->train;
					int start_node_num = track_msg->node1;
					int end_node_num = track_msg->node2;

					short path[TRACK_MAX];
					int num_nodes = 0;

					if (IS_SENSOR(start_node_num) && IS_SENSOR(end_node_num)) {
						struct track_node *start_node = &track[start_node_num];
						struct track_node *end_node = &track[end_node_num];
						mark_path(train, track, start_node, end_node);

						if (end_node->routing_info.visited == 1) {
							// we have a path!
							// store all nodes, from bottom up
							struct track_node *cur_node = end_node;
							struct location loc;
							while (cur_node->routing_info.previous != 0 && cur_node != start_node) {
								node_to_location(cur_node, &loc);
								path[num_nodes] = loc.node;
								num_nodes++;

								if (cur_node->routing_info.previous == cur_node->reverse) {
									// the next node is the reverse of this node, so we squeeze in a "REVERSE" in the path
									path[num_nodes] = -99; // magic number for REVERSE commands
									num_nodes++;
								}

								cur_node = cur_node->routing_info.previous;
							}

							// we didn't store the beginning node in our path, so we should do that now
							if (cur_node == start_node) {
								node_to_location(start_node, &loc);
								path[num_nodes] = loc.node;
								num_nodes++;
							}

						} else {
							Printf("Could not find route! num_nodes = %d\r", num_nodes);
						}

					}

					Reply(sender_tid, (char*)path, sizeof(short) * num_nodes);
				} break;

				case TRACK_OP_SWITCH_DIRECTION: {

					struct track_request_message* track_msg = (struct track_request_message*)message_buffer;

					int switch_node = track_msg->node1;
					int next_node = track_msg->node2;

					AssertF(track[switch_node].type == NODE_BRANCH, "TrackSwitchDirection not given a switch node! Given node num %d, type %d", track[switch_node].num, track[switch_node].type);

					int reserved = node_is_reserved(track_msg->train, switch_node);

					if (reserved) {
//						Printf("Attempting to switch %s if reserved .. \r", track[switch_node].name);
						int direction = -1;


						if (track[switch_node].edge[DIR_CURVED].dest == &(track[next_node])) {
							direction = SWITCH_CURVED;
						} else {
							direction = SWITCH_STRAIGHT;
						}

						SwitchSetDirection(track[switch_node].num, direction, WhoIs(SWITCH_SERVER));
						switch_table[track[switch_node].num] = direction;
					}

					Reply(sender_tid, (char*)&reserved, sizeof(reserved));
				} break;

				default:
					AssertF(0, "Invalid message %d to the track server from %d", op, sender_tid);
					Reply(sender_tid, (char*)&reply, sizeof(reply));
					break;
			}
		}
	}
	Assert("Track server is quitting");
	Exit();
}
int reservation_edge_available(int train, struct track_edge* edge) {
	AssertF(edge != 0, "res_edge_avail: EDGE PASSED IN IS NULL!");
	return reservation_available(train, edge, 0, edge->dist);
}
Ejemplo n.º 13
0
Archivo: mf.c Proyecto: shuowen/OpenNT
void
AssertNoMf(
    void)
{
    AssertF(mf1.pthReal == 0);
    AssertF(mf2.pthReal == 0);
    AssertF(mf3.pthReal == 0);
    AssertF(mf4.pthReal == 0);
    AssertF(FEmptyNm(mf1.nmTemp));
    AssertF(FEmptyNm(mf2.nmTemp));
    AssertF(FEmptyNm(mf3.nmTemp));
    AssertF(FEmptyNm(mf4.nmTemp));
    AssertF(mf1.fdRead == fdNil);
    AssertF(mf2.fdRead == fdNil);
    AssertF(mf3.fdRead == fdNil);
    AssertF(mf4.fdRead == fdNil);
    AssertF(mf1.fdWrite == fdNil);
    AssertF(mf2.fdWrite == fdNil);
    AssertF(mf3.fdWrite == fdNil);
    AssertF(mf4.fdWrite == fdNil);
    AssertF(!mf1.fFileLock);
    AssertF(!mf2.fFileLock);
    AssertF(!mf3.fFileLock);
    AssertF(!mf4.fFileLock);
    AssertF(mf1.mm == mmNil);
    AssertF(mf2.mm == mmNil);
    AssertF(mf3.mm == mmNil);
    AssertF(mf4.mm == mmNil);
}