~ better sync.

pull/1/head
Ivan Olexyn 5 years ago
parent 4cb9858907
commit a871e3cf2f

@ -14,8 +14,9 @@ public class BridgeServlet extends HttpServlet {
protected static final String MISP_CLIENT_URL = "http://localhost:9090/mispclient/core";
public final Map<Long, Ride> rideMap = new HashMap<>();
protected RideMapHelper mapHelper = new RideMapHelper(rideMap);
public final Map<Long, Ride> available = new HashMap<>();
public final Map<Long, Ride> booked = new HashMap<>();
public final Map<Long, Ride> loaded = new HashMap<>();
// #######
//

@ -9,8 +9,6 @@ import java.util.HashMap;
import java.util.Map;
public class ClientServlet extends HttpServlet {
protected static final String MISP_BRIDGE_URL = "http://localhost:9090/mispbridge/core";
@ -20,8 +18,10 @@ public class ClientServlet extends HttpServlet {
public static final int AVAILABLE_RIDES_OVERHEAD = 32;
public final Map<Long, Ride> rideMap = new HashMap<>();
protected RideMapHelper mapHelper = new RideMapHelper(rideMap);
public final Map<Long, Ride> available = new HashMap<>();
public final Map<Long, Ride> booked = new HashMap<>();
public final Map<Long, Ride> loaded = new HashMap<>();
public ClientServlet() {
@ -41,8 +41,7 @@ public class ClientServlet extends HttpServlet {
HttpURLConnection connection = ConnectionHelper.make("POST", MISP_BRIDGE_URL);
// send POST (Ride)
rideMap.put(ride.getID(), ride.setState(State.AVAILABLE));
available.put(ride.getID(), ride);
connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(ride.json());
@ -61,7 +60,6 @@ public class ClientServlet extends HttpServlet {
}
/**
* # send GET (Request) to App
*/
@ -100,7 +98,7 @@ public class ClientServlet extends HttpServlet {
if (connection.getResponseCode() == 200) {
Ride shellIdRide = ConnectionHelper.parseRide(connection);
if (shellIdRide.getID() != null) {
rideMap.remove(oldRide.getID());
loaded.remove(oldRide.getID());
}
}
}
@ -125,18 +123,8 @@ class PostRideRunnable implements Runnable {
@Override
public void run() {
while (true) {
long availableRides = 0L;
for (Map.Entry<Long,Ride> entry : clientServlet.rideMap.entrySet()){
if (entry.getValue().getState() == State.AVAILABLE){
availableRides++;
}
}
if (availableRides< ClientServlet.AVAILABLE_RIDES_OVERHEAD_TRIGGER) {
for (int i=0; i<ClientServlet.AVAILABLE_RIDES_OVERHEAD;i++) {
if (clientServlet.available.size() < ClientServlet.AVAILABLE_RIDES_OVERHEAD_TRIGGER) {
for (int i = 0; i < ClientServlet.AVAILABLE_RIDES_OVERHEAD; i++) {
try {clientServlet.sendPostRide(new Ride());} catch (IOException | ServletException | InterruptedException e) { e.printStackTrace(); }
}
}

@ -9,7 +9,7 @@ public class Ride {
private static long count = 0L;
private Long id;
final private Long id;
private String request;
private String data;
private State state;
@ -24,6 +24,7 @@ public class Ride {
}
public Ride(String jsonString) {
JSONObject obj = new JSONObject();
try {
obj = new JSONObject(jsonString);
@ -32,13 +33,14 @@ public class Ride {
}
Long _id;
try {
id = obj.getLong("id");
_id = obj.getLong("id");
}catch (JSONException e){
id = count++;
_id = count++;
}
id = _id;
try{
request = obj.getString("request");
} catch (JSONException e){

@ -28,51 +28,61 @@ public class BridgeMock extends BridgeServlet {
@Override
protected void handleGetRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
ExchangeMock exchange;
Ride ride = null;
final ExchangeMock exchange;
final Ride ride;
synchronized (exchange = ((RequestMock) request).exchange) {
String parsedRequest = IOUtils.toString(request.getReader());
JSONObject obj = new JSONObject(parsedRequest);
final JSONObject obj = new JSONObject(parsedRequest);
parsedRequest = obj.getString("request");
synchronized (available) {
synchronized (rideMap) {
// TODO make 3 maps
while (mapHelper.containsLess(1, State.AVAILABLE)) { Thread.sleep(Main.WAIT_SPEED); }
while (ride == null) {
ride = mapHelper.pickAvailable();
while (available.size() < 1) {
available.notify();
Thread.sleep(Main.WAIT_SPEED);
available.wait();
}
// ride exists only locally, thus safe
ride = available.entrySet().iterator().next().getValue();
// ride exists only in "available", access through which is sync, thus safe
available.remove(ride.getID());
// needed because POST (Ride) wait()s
available.notify();
}
synchronized (booked) {
// ride exists only locally, thus safe
booked.put(ride.getID(), ride);
// ride exists only in "booked", access through which is sync, thus safe
ride.setRequest(parsedRequest);
ride.setState(State.BOOKED);
// POST (Ride) wait()s
booked.notify();
}
while (ride.getState() != State.LOADED) {
rideMap.notify();
synchronized (loaded) {
while (!loaded.containsKey(ride.getID())) {
loaded.notify();
Thread.sleep(Main.WAIT_SPEED);
rideMap.wait();
loaded.wait();
}
rideMap.remove(ride.getID());
// WIP this is tricky
// what if ride exists in another map, e.g. "available'
// in that case illegal access is possible
// be carefull to removing ride from all other references, when adding it to "loaded".
ride.setData(loaded.remove(ride.getID()).getData());
}
exchange.response.setStatus(200);
PrintWriter writer = exchange.response.getWriter();
final PrintWriter writer = exchange.response.getWriter();
writer.write(ride.getData());
writer.flush();
writer.close();
rideMap.notify();
}
exchange.notify();
}
}
@ -91,34 +101,24 @@ public class BridgeMock extends BridgeServlet {
*/
protected void handleGetRideRequestData(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
ExchangeMock exchange;
Ride thisRide;
final ExchangeMock exchange;
synchronized (exchange = ((RequestMock) request).exchange) {
String jsonPayload = IOUtils.toString(request.getReader());
Ride parsedRide = new Ride(jsonPayload);
synchronized (rideMap) {
synchronized (thisRide = rideMap.get(parsedRide.getID())) {
final String jsonPayload = IOUtils.toString(request.getReader());
final Ride ride = new Ride(jsonPayload);
thisRide.setData(parsedRide.getData());
thisRide.setState(State.LOADED);
exchange.response.setStatus(200);
PrintWriter writer = response.getWriter();
writer.write(thisRide.json());
writer.flush();
writer.close();
rideMap.remove(thisRide.getID());
thisRide.notify();
synchronized (booked) {
booked.remove(ride.getID());
}
rideMap.notify();
synchronized (loaded) {
loaded.put(ride.getID(), ride);
loaded.notify();
}
exchange.notify();
}
}
@ -130,24 +130,28 @@ public class BridgeMock extends BridgeServlet {
@Override
protected void handlePostRide(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
ExchangeMock exchange;
Ride ride;
final ExchangeMock exchange;
synchronized (exchange = ((RequestMock) request).exchange) {
String jsonPayload = IOUtils.toString(request.getReader());
ride = new Ride(jsonPayload);
synchronized (rideMap) {
final Ride ride = new Ride(jsonPayload);
rideMap.put(ride.getID(), ride.setState(State.AVAILABLE));
synchronized (ride = rideMap.get(ride.getID())) {
synchronized (available) {
available.put(ride.getID(), ride);
available.notify();
}
while (ride.getState() == State.AVAILABLE) {
rideMap.notify();
// ID is final/threadsafe
while(!(booked.containsKey(ride.getID()))){
Thread.sleep(Main.WAIT_SPEED);
rideMap.wait();
}
synchronized (booked) {
//booked.notify();
//booked.wait();
ride.setRequest(booked.get(ride.getID()).getRequest());
}
exchange.response.setStatus(200);
@ -156,10 +160,6 @@ public class BridgeMock extends BridgeServlet {
writer.flush();
writer.close();
ride.notify();
}
rideMap.notify();
}
exchange.notify();
}
}

@ -24,11 +24,16 @@ public class ClientMock extends ClientServlet {
@Override
void sendPostRide(Ride ride) throws IOException, ServletException, InterruptedException {
rideMap.put(ride.getID(), ride.setState(State.AVAILABLE));
// Mock Exchange
ExchangeMock exchange = new ExchangeMock();
synchronized (available){
available.put(ride.getID(),ride);
}
// Mock Exchange
final ExchangeMock exchange = new ExchangeMock();
exchange.request.setMethod("POST");
exchange.request.setContentType("application/json");
exchange.request.setContent(ride.json().getBytes());
@ -45,7 +50,8 @@ public class ClientMock extends ClientServlet {
exchange.notify();
}
ride.setState(State.BOOKED);
available.remove(ride.getID());
booked.put(ride.getID(),ride);
sendGetRequest(ride);
}
@ -74,7 +80,8 @@ public class ClientMock extends ClientServlet {
ride.setData(parsedRide.getData());
exchange.notify();
}
ride.setState(State.LOADED);
booked.remove(ride.getID());
loaded.put(ride.getID(),ride);
sendGetRideRequestData(ride);
}
@ -100,7 +107,7 @@ public class ClientMock extends ClientServlet {
// handle OK (Ride)
Ride parsedRide = new Ride(exchange.response.getContentAsString());
rideMap.remove(parsedRide.getID());
loaded.remove(parsedRide.getID());
exchange.notify();
}
}

@ -5,7 +5,7 @@ import actor.UserMock;
public class Main {
final public static int WAIT_SPEED = 10;
final public static int WAIT_SPEED = 0;

Loading…
Cancel
Save