~ 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"; protected static final String MISP_CLIENT_URL = "http://localhost:9090/mispclient/core";
public final Map<Long, Ride> rideMap = new HashMap<>(); public final Map<Long, Ride> available = new HashMap<>();
protected RideMapHelper mapHelper = new RideMapHelper(rideMap); 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; import java.util.Map;
public class ClientServlet extends HttpServlet { public class ClientServlet extends HttpServlet {
protected static final String MISP_BRIDGE_URL = "http://localhost:9090/mispbridge/core"; 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 static final int AVAILABLE_RIDES_OVERHEAD = 32;
public final Map<Long, Ride> rideMap = new HashMap<>(); public final Map<Long, Ride> available = new HashMap<>();
protected RideMapHelper mapHelper = new RideMapHelper(rideMap); public final Map<Long, Ride> booked = new HashMap<>();
public final Map<Long, Ride> loaded = new HashMap<>();
public ClientServlet() { public ClientServlet() {
@ -41,8 +41,7 @@ public class ClientServlet extends HttpServlet {
HttpURLConnection connection = ConnectionHelper.make("POST", MISP_BRIDGE_URL); HttpURLConnection connection = ConnectionHelper.make("POST", MISP_BRIDGE_URL);
// send POST (Ride) // send POST (Ride)
available.put(ride.getID(), ride);
rideMap.put(ride.getID(), ride.setState(State.AVAILABLE));
connection.setDoOutput(true); connection.setDoOutput(true);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(ride.json()); outputStream.writeBytes(ride.json());
@ -61,7 +60,6 @@ public class ClientServlet extends HttpServlet {
} }
/** /**
* # send GET (Request) to App * # send GET (Request) to App
*/ */
@ -100,7 +98,7 @@ public class ClientServlet extends HttpServlet {
if (connection.getResponseCode() == 200) { if (connection.getResponseCode() == 200) {
Ride shellIdRide = ConnectionHelper.parseRide(connection); Ride shellIdRide = ConnectionHelper.parseRide(connection);
if (shellIdRide.getID() != null) { if (shellIdRide.getID() != null) {
rideMap.remove(oldRide.getID()); loaded.remove(oldRide.getID());
} }
} }
} }
@ -125,17 +123,7 @@ class PostRideRunnable implements Runnable {
@Override @Override
public void run() { public void run() {
while (true) { while (true) {
if (clientServlet.available.size() < ClientServlet.AVAILABLE_RIDES_OVERHEAD_TRIGGER) {
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++) { for (int i = 0; i < ClientServlet.AVAILABLE_RIDES_OVERHEAD; i++) {
try {clientServlet.sendPostRide(new Ride());} catch (IOException | ServletException | InterruptedException e) { e.printStackTrace(); } 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 static long count = 0L;
private Long id; final private Long id;
private String request; private String request;
private String data; private String data;
private State state; private State state;
@ -24,6 +24,7 @@ public class Ride {
} }
public Ride(String jsonString) { public Ride(String jsonString) {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
try { try {
obj = new JSONObject(jsonString); obj = new JSONObject(jsonString);
@ -32,13 +33,14 @@ public class Ride {
} }
Long _id;
try { try {
id = obj.getLong("id"); _id = obj.getLong("id");
}catch (JSONException e){ }catch (JSONException e){
id = count++; _id = count++;
} }
id = _id;
try{ try{
request = obj.getString("request"); request = obj.getString("request");
} catch (JSONException e){ } catch (JSONException e){

@ -28,51 +28,61 @@ public class BridgeMock extends BridgeServlet {
@Override @Override
protected void handleGetRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { protected void handleGetRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
ExchangeMock exchange; final ExchangeMock exchange;
Ride ride = null; final Ride ride;
synchronized (exchange = ((RequestMock) request).exchange) { synchronized (exchange = ((RequestMock) request).exchange) {
String parsedRequest = IOUtils.toString(request.getReader()); String parsedRequest = IOUtils.toString(request.getReader());
JSONObject obj = new JSONObject(parsedRequest); final JSONObject obj = new JSONObject(parsedRequest);
parsedRequest = obj.getString("request"); parsedRequest = obj.getString("request");
synchronized (available) {
synchronized (rideMap) { while (available.size() < 1) {
available.notify();
// TODO make 3 maps
while (mapHelper.containsLess(1, State.AVAILABLE)) { Thread.sleep(Main.WAIT_SPEED); }
while (ride == null) {
ride = mapHelper.pickAvailable();
Thread.sleep(Main.WAIT_SPEED); 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.setRequest(parsedRequest);
ride.setState(State.BOOKED); // POST (Ride) wait()s
booked.notify();
}
while (ride.getState() != State.LOADED) { synchronized (loaded) {
rideMap.notify();
while (!loaded.containsKey(ride.getID())) {
loaded.notify();
Thread.sleep(Main.WAIT_SPEED); 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); exchange.response.setStatus(200);
PrintWriter writer = exchange.response.getWriter(); final PrintWriter writer = exchange.response.getWriter();
writer.write(ride.getData()); writer.write(ride.getData());
writer.flush(); writer.flush();
writer.close(); writer.close();
rideMap.notify();
}
exchange.notify(); exchange.notify();
} }
} }
@ -91,34 +101,24 @@ public class BridgeMock extends BridgeServlet {
*/ */
protected void handleGetRideRequestData(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { protected void handleGetRideRequestData(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
ExchangeMock exchange; final ExchangeMock exchange;
Ride thisRide;
synchronized (exchange = ((RequestMock) request).exchange) { synchronized (exchange = ((RequestMock) request).exchange) {
String jsonPayload = IOUtils.toString(request.getReader()); final String jsonPayload = IOUtils.toString(request.getReader());
Ride parsedRide = new Ride(jsonPayload); final Ride ride = new Ride(jsonPayload);
synchronized (rideMap) {
synchronized (thisRide = rideMap.get(parsedRide.getID())) {
thisRide.setData(parsedRide.getData()); synchronized (booked) {
thisRide.setState(State.LOADED); booked.remove(ride.getID());
exchange.response.setStatus(200);
PrintWriter writer = response.getWriter();
writer.write(thisRide.json());
writer.flush();
writer.close();
rideMap.remove(thisRide.getID());
thisRide.notify();
} }
rideMap.notify();
synchronized (loaded) {
loaded.put(ride.getID(), ride);
loaded.notify();
} }
exchange.notify(); exchange.notify();
} }
} }
@ -130,24 +130,28 @@ public class BridgeMock extends BridgeServlet {
@Override @Override
protected void handlePostRide(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException { protected void handlePostRide(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
ExchangeMock exchange; final ExchangeMock exchange;
Ride ride;
synchronized (exchange = ((RequestMock) request).exchange) { synchronized (exchange = ((RequestMock) request).exchange) {
String jsonPayload = IOUtils.toString(request.getReader()); String jsonPayload = IOUtils.toString(request.getReader());
ride = new Ride(jsonPayload); final Ride ride = new Ride(jsonPayload);
synchronized (rideMap) {
rideMap.put(ride.getID(), ride.setState(State.AVAILABLE)); synchronized (available) {
available.put(ride.getID(), ride);
synchronized (ride = rideMap.get(ride.getID())) { available.notify();
}
while (ride.getState() == State.AVAILABLE) { // ID is final/threadsafe
rideMap.notify(); while(!(booked.containsKey(ride.getID()))){
Thread.sleep(Main.WAIT_SPEED); Thread.sleep(Main.WAIT_SPEED);
rideMap.wait(); }
synchronized (booked) {
//booked.notify();
//booked.wait();
ride.setRequest(booked.get(ride.getID()).getRequest());
} }
exchange.response.setStatus(200); exchange.response.setStatus(200);
@ -156,10 +160,6 @@ public class BridgeMock extends BridgeServlet {
writer.flush(); writer.flush();
writer.close(); writer.close();
ride.notify();
}
rideMap.notify();
}
exchange.notify(); exchange.notify();
} }
} }

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

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

Loading…
Cancel
Save