MP6 (Wearable) Due: Monday, December 1, 2014 at 11:59pm

This MP will be graded as follows:


Introduction

You are the creator of a new startup, WearIt, that creates clothing containing sensors to collect data from the user. This data includes 3 different data points, heart beats per minute, blood sugar, and body temperature. After years of prototyping you have created wearables that can collect and transmit all of the data. All that’s left is to create the server program, wearable_server.c, that a user can set up to hold their personal data. You have created a basic draft of how development should follow, and what you need to accomplish.

Your server will be run through command line, with two arguments that correspond to two port numbers - we will call these the ‘wearable port’ and ‘request port’ respectively. Your server must be able to handle numerous connections that can last an arbitrary amount of time, and as such should create a thread for each new connection on the wearable port.

TASKS

[Task 1] Setup the server

Before collecting data, you need to set up two servers to accept connections, on two ports (given by arguments 1 and 2 in the command line). The first port (‘wearable port’) will be used by the wearables to connect and send data to. The second port (‘request port’) will be used for an outside source to connect to and request a report on the current data collected; see task 3. Remember, your wearables may or may not connect all at once. We have provided the prototype open_server_socket() which you will need to implement. The code to setup the request server has been provided in the main function, but you must also accept continuous connections on the wearable port as well.

A reminder that setting REUSEPORT socket option can be useful.

[Task 2] Collect data

Once a connection has been established between a wearable and your server, the wearable will write to the file descriptor, in the form “<timestamp>:<value>:<type>”. Type will correspond to one of the three strings: "heart_beat", "blood_sugar", “body_temp", while timestamp and value will be an integer value. You are responsible for saving this data for later processing and analysis. We have provided the files queue.c and queue.h, which contain an implementation of a queue that stores timestamped data, and helper functions to get data between certain timestamp ranges (See queue.h on how to use the different methods). PLEASE NOTE: this queue is not thread safe so you will be responsible for synchronizing actions on it.

[Task 3] Analysis of data

Your server is useless if others cannot query it, so we will also open up a port where a user can send a request to. A request to your server will be done by the following:

Hints: Your initial implementation might try to use busy waiting (e.g. while a wearable has yet to send the server all of the data, do not send the request info). However it is relatively easy (and for this MP required!) to turn a busy-wait loop into a mutex and condition wait! If you do busy-wait you will not receive full points for this MP. We encourage you to review correct use of condition variables.

[Task 4] Close gracefully

Your server will stop accepting connections when you receive the interrupt signal (SIGINT), and will exit gracefully (ie freeing all memory and closing all ports) after all wearable connections have closed. In all of the tests you can assume the user has connected to the request socket and the SIGINT signal is only sent after the user has finished requesting all of its data.

A reminder that setting REUSEPORT socket option can be useful.

HOW TO RUN

While you will be responsible for creating the server, a simulator for wearables has already been created for you to test with. Recall that you server should take 2 ports, the first being wearable server, the second being the user server.

To compile, run the following commands from a command prompt on a Linux machine:

%> make clean
%> make

Starting your server should look like

%> ./wearable_server 8888 8889
Where 8888 and 8889 are arbitrary ports

Once your server has been started you can begin the simulator

%> ./wearable_sim 8888 8889 BASIC_TEST.ww

Where the 2 ports represent the ports you passed into your server, and the BASIC_TEST.ww is a test script. We have provided a few basic tests to check your output against.

While the simulator is running it will report back the data you sent from your server. Additionally it also generates the expected output, for you to compare against. After running the simulator you should see 3 files, _expected.rp, _received.rp, and _error_report.rp. _received.rp will hold the exact data sent from your server, so to see if your output is correct after running the simulator, you can use

diff _received.rp _expected.rp

Further, _error_report.rp will hold any errors that may have been encounter while running the simulator, (such as being unable to connect to your server)

The test scripts are human readable, so feel free to create your own or modify. Every command should be on its own line.

BEGIN - Signifies the beginning of a wearable definition.
START: - States how much time before this wearable begins transmitting information.
INTERVAL: - States the time delay between sending data points. <type>:<value> - One data point, where type is a string corresponding TYPE1, TYPE2, TYPE3. Value is an integer. Note all data points are transmitted sequentially by order in which they appear in a BEGIN-END wearable definition.
END - Signifies the end of a wearable definition

SAMPLE_INT:<wait time>:<timestamp1>:<timestamp2> - Simulates a user request. There can be multiple commands of this time, and the are simulated sequentially. <wait time> represents the time (in millis) to sleep before this request is sent. The timestamp values represent the range of timestamps requested.

A basic test that creates one wearable that starts 1 second after the simulator is started, with 3 data points (send every second) and requests timestamp between 0, 2000 (with the request started 2 seconds after) would look like:

SAMPLE_INT:2000:0:2000
BEGIN
START:1000
INTERVAL:1000
heart_beat:100
blood_sugar:104
body_temp:104
END

This test script would send the data:

1000:heart_beat:100
2000:blood_sugar:104
3000:body_temp:104

and the expected output would be:

Results for heart_beat:
Size:1
0 100
Median:100
Average:100
Results for blood_sugar:
Size:0
Median:0
Average:0
Results for body_temp:
Size:0
Median:0
Average:0