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 VERSION_PATH = "/version";
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 {
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;
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
@ -180,7 +179,7 @@ public class Backend implements Closeable {
ControllerKey controllerKey = new ControllerKey(applicationRequest.getTargetUserId(), applicationRequest.getSessionDetails().getControllerInfo());
ControllerConnectionState state;
synchronized (lock) {
state = acquire(controllerKey);
state = acquire(controllerKey, userDetails);
}
if (state == null) {
log.info("No controller for " + controllerKey);
@ -203,14 +202,14 @@ public class Backend implements Closeable {
}, serverPortForApplications, "ApplicationServer", serverSocketCreationCallback, BinaryProtocolServer.SECURE_SOCKET_FACTORY);
}
private ControllerConnectionState acquire(ControllerKey controllerKey) {
private ControllerConnectionState acquire(ControllerKey controllerKey, UserDetails userDetails) {
synchronized (lock) {
ControllerConnectionState state = controllersByKey.get(controllerKey);
if (state == null) {
// no such controller
return null;
}
if (!state.getTwoKindSemaphore().acquireForLongTermUsage()) {
if (!state.getTwoKindSemaphore().acquireForLongTermUsage(userDetails)) {
// someone is already talking to this controller
return null;
}
@ -279,7 +278,8 @@ public class Backend implements Closeable {
JsonObject controllerObject = Json.createObjectBuilder()
.add(UserDetails.USER_ID, client.getUserDetails().getUserId())
.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.CLT, clt)
.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 SHORT_TERM = 1;
private final Semaphore semaphore = new Semaphore(LONG_TERM);
private UserDetails owner;
public void releaseFromLongTermUsage() {
semaphore.release(LONG_TERM);
// not atomic but that's fine, isUsed is the source of truth
owner = null;
}
public boolean acquireForShortTermUsage() {
@ -28,16 +31,25 @@ public class TwoKindSemaphore {
/**
* @return true if acquired successfully, false if not
* @param userDetails
*/
public boolean acquireForLongTermUsage() {
return acquireForLongTermUsage(10);
public boolean acquireForLongTermUsage(UserDetails userDetails) {
return acquireForLongTermUsage(userDetails, 10);
}
public boolean acquireForLongTermUsage(int timeout) {
public boolean acquireForLongTermUsage(UserDetails userDetails, int timeout) {
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) {
throw new IllegalStateException(e);
}
}
public UserDetails getOwner() {
return owner;
}
}

View File

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