mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-07 21:51:23 +00:00
Merge pull request #309 from glyptodon/concurrency
GUAC-1427: Fix possible issues with concurrency.
This commit is contained in:
@@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
package org.glyptodon.guacamole.servlet;
|
package org.glyptodon.guacamole.servlet;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -65,8 +65,8 @@ class GuacamoleHTTPTunnelMap {
|
|||||||
/**
|
/**
|
||||||
* Map of all tunnels that are using HTTP, indexed by tunnel UUID.
|
* Map of all tunnels that are using HTTP, indexed by tunnel UUID.
|
||||||
*/
|
*/
|
||||||
private final Map<String, GuacamoleHTTPTunnel> tunnelMap =
|
private final ConcurrentMap<String, GuacamoleHTTPTunnel> tunnelMap =
|
||||||
Collections.synchronizedMap(new LinkedHashMap<String, GuacamoleHTTPTunnel>(16, 0.75f, true));
|
new ConcurrentHashMap<String, GuacamoleHTTPTunnel>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new GuacamoleHTTPTunnelMap which automatically closes and
|
* Creates a new GuacamoleHTTPTunnelMap which automatically closes and
|
||||||
@@ -124,9 +124,12 @@ class GuacamoleHTTPTunnelMap {
|
|||||||
|
|
||||||
// If tunnel is too old, close and remove it
|
// If tunnel is too old, close and remove it
|
||||||
if (age >= tunnelTimeout) {
|
if (age >= tunnelTimeout) {
|
||||||
|
|
||||||
|
// Remove old entry
|
||||||
logger.debug("HTTP tunnel \"{}\" has timed out.", entry.getKey());
|
logger.debug("HTTP tunnel \"{}\" has timed out.", entry.getKey());
|
||||||
entries.remove();
|
entries.remove();
|
||||||
|
|
||||||
|
// Attempt to close tunnel
|
||||||
try {
|
try {
|
||||||
tunnel.close();
|
tunnel.close();
|
||||||
}
|
}
|
||||||
@@ -136,14 +139,9 @@ class GuacamoleHTTPTunnelMap {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, this tunnel has been recently used, as have all
|
} // end for each tunnel
|
||||||
// other tunnels following this one within tunnelMap
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
} // end timeout task run()
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,10 +22,10 @@
|
|||||||
|
|
||||||
package org.glyptodon.guacamole.net.basic.rest.auth;
|
package org.glyptodon.guacamole.net.basic.rest.auth;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -57,8 +57,8 @@ public class BasicTokenSessionMap implements TokenSessionMap {
|
|||||||
/**
|
/**
|
||||||
* Keeps track of the authToken to GuacamoleSession mapping.
|
* Keeps track of the authToken to GuacamoleSession mapping.
|
||||||
*/
|
*/
|
||||||
private final Map<String, GuacamoleSession> sessionMap =
|
private final ConcurrentMap<String, GuacamoleSession> sessionMap =
|
||||||
Collections.synchronizedMap(new LinkedHashMap<String, GuacamoleSession>(16, 0.75f, true));
|
new ConcurrentHashMap<String, GuacamoleSession>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new BasicTokenGuacamoleSessionMap configured using the given
|
* Create a new BasicTokenGuacamoleSessionMap configured using the given
|
||||||
@@ -89,9 +89,7 @@ public class BasicTokenSessionMap implements TokenSessionMap {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Task which iterates through all active sessions, evicting those sessions
|
* Task which iterates through all active sessions, evicting those sessions
|
||||||
* which are beyond the session timeout. This is a fairly easy thing to do,
|
* which are beyond the session timeout.
|
||||||
* since the session storage structure guarantees that sessions are always
|
|
||||||
* in descending order of age.
|
|
||||||
*/
|
*/
|
||||||
private class SessionEvictionTask implements Runnable {
|
private class SessionEvictionTask implements Runnable {
|
||||||
|
|
||||||
@@ -114,11 +112,11 @@ public class BasicTokenSessionMap implements TokenSessionMap {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
// Get current time
|
// Get start time of session check time
|
||||||
long now = System.currentTimeMillis();
|
long sessionCheckStart = System.currentTimeMillis();
|
||||||
|
|
||||||
logger.debug("Checking for expired sessions...");
|
logger.debug("Checking for expired sessions...");
|
||||||
|
|
||||||
// For each session, remove sesions which have expired
|
// For each session, remove sesions which have expired
|
||||||
Iterator<Map.Entry<String, GuacamoleSession>> entries = sessionMap.entrySet().iterator();
|
Iterator<Map.Entry<String, GuacamoleSession>> entries = sessionMap.entrySet().iterator();
|
||||||
while (entries.hasNext()) {
|
while (entries.hasNext()) {
|
||||||
@@ -131,7 +129,7 @@ public class BasicTokenSessionMap implements TokenSessionMap {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get elapsed time since last access
|
// Get elapsed time since last access
|
||||||
long age = now - session.getLastAccessedTime();
|
long age = sessionCheckStart - session.getLastAccessedTime();
|
||||||
|
|
||||||
// If session is too old, evict it and check the next one
|
// If session is too old, evict it and check the next one
|
||||||
if (age >= sessionTimeout) {
|
if (age >= sessionTimeout) {
|
||||||
@@ -140,13 +138,11 @@ public class BasicTokenSessionMap implements TokenSessionMap {
|
|||||||
session.invalidate();
|
session.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, no other sessions can possibly be old enough
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("Session check complete.");
|
// Log completion and duration
|
||||||
|
logger.debug("Session check completed in {} ms.",
|
||||||
|
System.currentTimeMillis() - sessionCheckStart);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user