isUsed/owner progress

This commit is contained in:
rusefi 2020-07-24 16:38:42 -04:00
parent e6f6868598
commit e2842e1191
4 changed files with 35 additions and 13 deletions

View File

@ -18,6 +18,8 @@ public class ProxyClient {
public static final String LIST_APPLICATIONS_PATH = "/list_applications"; public static final String LIST_APPLICATIONS_PATH = "/list_applications";
public static final String VERSION_PATH = "/version"; public static final String VERSION_PATH = "/version";
public static final String BACKEND_VERSION = "0.0001"; public static final String BACKEND_VERSION = "0.0001";
public static final String IS_USED = "isUsed";
public static final String OWNER = "owner";
public static List<PublicSession> getOnlineApplications(int httpPort) throws IOException { public static List<PublicSession> getOnlineApplications(int httpPort) throws IOException {
return getOnlineApplications(getHttpAddress(httpPort) + LIST_CONTROLLERS_PATH); return getOnlineApplications(getHttpAddress(httpPort) + LIST_CONTROLLERS_PATH);

View File

@ -41,7 +41,6 @@ public class Backend implements Closeable {
public static final int SERVER_PORT_FOR_CONTROLLERS = 8003; public static final int SERVER_PORT_FOR_CONTROLLERS = 8003;
private static final String MAX_PACKET_GAP = "MAX_PACKET_GAP"; private static final String MAX_PACKET_GAP = "MAX_PACKET_GAP";
private static final String IS_USED = "isUsed";
/** /**
* Application with exclusive access should connect tuning application within 3 minutes * Application with exclusive access should connect tuning application within 3 minutes
@ -180,7 +179,7 @@ public class Backend implements Closeable {
ControllerKey controllerKey = new ControllerKey(applicationRequest.getTargetUserId(), applicationRequest.getSessionDetails().getControllerInfo()); ControllerKey controllerKey = new ControllerKey(applicationRequest.getTargetUserId(), applicationRequest.getSessionDetails().getControllerInfo());
ControllerConnectionState state; ControllerConnectionState state;
synchronized (lock) { synchronized (lock) {
state = acquire(controllerKey); state = acquire(controllerKey, userDetails);
} }
if (state == null) { if (state == null) {
log.info("No controller for " + controllerKey); log.info("No controller for " + controllerKey);
@ -203,14 +202,14 @@ public class Backend implements Closeable {
}, serverPortForApplications, "ApplicationServer", serverSocketCreationCallback, BinaryProtocolServer.SECURE_SOCKET_FACTORY); }, serverPortForApplications, "ApplicationServer", serverSocketCreationCallback, BinaryProtocolServer.SECURE_SOCKET_FACTORY);
} }
private ControllerConnectionState acquire(ControllerKey controllerKey) { private ControllerConnectionState acquire(ControllerKey controllerKey, UserDetails userDetails) {
synchronized (lock) { synchronized (lock) {
ControllerConnectionState state = controllersByKey.get(controllerKey); ControllerConnectionState state = controllersByKey.get(controllerKey);
if (state == null) { if (state == null) {
// no such controller // no such controller
return null; return null;
} }
if (!state.getTwoKindSemaphore().acquireForLongTermUsage()) { if (!state.getTwoKindSemaphore().acquireForLongTermUsage(userDetails)) {
// someone is already talking to this controller // someone is already talking to this controller
return null; return null;
} }
@ -279,7 +278,8 @@ public class Backend implements Closeable {
JsonObject controllerObject = Json.createObjectBuilder() JsonObject controllerObject = Json.createObjectBuilder()
.add(UserDetails.USER_ID, client.getUserDetails().getUserId()) .add(UserDetails.USER_ID, client.getUserDetails().getUserId())
.add(UserDetails.USERNAME, client.getUserDetails().getUserName()) .add(UserDetails.USERNAME, client.getUserDetails().getUserName())
.add(IS_USED, client.getTwoKindSemaphore().isUsed()) .add(ProxyClient.IS_USED, client.getTwoKindSemaphore().isUsed())
.add(ProxyClient.OWNER, client.getTwoKindSemaphore().getOwner().getUserName())
.add(ControllerStateDetails.RPM, rpm) .add(ControllerStateDetails.RPM, rpm)
.add(ControllerStateDetails.CLT, clt) .add(ControllerStateDetails.CLT, clt)
.add(ControllerInfo.SIGNATURE, client.getSessionDetails().getControllerInfo().getSignature()) .add(ControllerInfo.SIGNATURE, client.getSessionDetails().getControllerInfo().getSignature())

View File

@ -8,9 +8,12 @@ public class TwoKindSemaphore {
private final static int LONG_TERM = 2; private final static int LONG_TERM = 2;
private final static int SHORT_TERM = 1; private final static int SHORT_TERM = 1;
private final Semaphore semaphore = new Semaphore(LONG_TERM); private final Semaphore semaphore = new Semaphore(LONG_TERM);
private UserDetails owner;
public void releaseFromLongTermUsage() { public void releaseFromLongTermUsage() {
semaphore.release(LONG_TERM); semaphore.release(LONG_TERM);
// not atomic but that's fine, isUsed is the source of truth
owner = null;
} }
public boolean acquireForShortTermUsage() { public boolean acquireForShortTermUsage() {
@ -28,16 +31,25 @@ public class TwoKindSemaphore {
/** /**
* @return true if acquired successfully, false if not * @return true if acquired successfully, false if not
* @param userDetails
*/ */
public boolean acquireForLongTermUsage() { public boolean acquireForLongTermUsage(UserDetails userDetails) {
return acquireForLongTermUsage(10); return acquireForLongTermUsage(userDetails, 10);
} }
public boolean acquireForLongTermUsage(int timeout) { public boolean acquireForLongTermUsage(UserDetails userDetails, int timeout) {
try { try {
return semaphore.tryAcquire(LONG_TERM, timeout, TimeUnit.SECONDS); boolean isAcquired = semaphore.tryAcquire(LONG_TERM, timeout, TimeUnit.SECONDS);
if (isAcquired) {
owner = userDetails;
}
return isAcquired;
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
} }
public UserDetails getOwner() {
return owner;
}
} }

View File

@ -2,8 +2,7 @@ package com.rusefi.server;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.*;
import static org.junit.Assert.assertTrue;
public class TwoKindSemaphoreTest { public class TwoKindSemaphoreTest {
@Test @Test
@ -15,11 +14,20 @@ public class TwoKindSemaphoreTest {
assertFalse(twoKindSemaphore.isUsed()); assertFalse(twoKindSemaphore.isUsed());
twoKindSemaphore.releaseFromShortTermUsage(); twoKindSemaphore.releaseFromShortTermUsage();
assertNull(twoKindSemaphore.getOwner());
assertTrue(twoKindSemaphore.acquireForLongTermUsage()); UserDetails userDetails = new UserDetails("xxx", 222);
assertTrue(twoKindSemaphore.acquireForLongTermUsage(userDetails));
assertNotNull(twoKindSemaphore.getOwner());
assertTrue(twoKindSemaphore.isUsed()); assertTrue(twoKindSemaphore.isUsed());
// //
assertFalse(twoKindSemaphore.acquireForLongTermUsage(1)); assertFalse(twoKindSemaphore.acquireForLongTermUsage(userDetails, 1));
assertFalse(twoKindSemaphore.acquireForShortTermUsage()); assertFalse(twoKindSemaphore.acquireForShortTermUsage());
twoKindSemaphore.releaseFromLongTermUsage();
assertNull(twoKindSemaphore.getOwner());
} }
} }