Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/catrope/netcomp
- Loading branch information
Showing
8 changed files
with
251 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import java.rmi.RemoteException; | ||
import java.rmi.server.UnicastRemoteObject; | ||
|
||
/** | ||
* RMI wrapper for a cache server | ||
*/ | ||
public class CacheServer extends UnicastRemoteObject implements ICache | ||
{ | ||
private static final long serialVersionUID = 1L; | ||
|
||
final ICache localCache; | ||
|
||
public CacheServer(ICache localCache) throws RemoteException | ||
{ | ||
this.localCache = localCache; | ||
} | ||
|
||
public void clear() | ||
{ | ||
localCache.clear(); | ||
} | ||
|
||
public String get(String key) | ||
{ | ||
return localCache.get(key); | ||
} | ||
|
||
public void set(String key, String val) | ||
{ | ||
localCache.set(key, val); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import java.math.BigInteger; | ||
import java.security.*; | ||
import java.util.Arrays; | ||
import java.util.Random; | ||
import java.util.Vector; | ||
|
||
/** | ||
* Manages a set of caching servers and load balances them using key hashing | ||
* @author Roan Kattouw | ||
*/ | ||
public class HashBalancer { | ||
protected Vector<String> servers; | ||
|
||
/** | ||
* Constructor | ||
* @param servers Vector of server names | ||
*/ | ||
public HashBalancer(Vector<String> servers) { | ||
this.servers = new Vector<String>(servers); | ||
} | ||
|
||
/** | ||
* Constructor | ||
* @param servers Array of server names | ||
*/ | ||
public HashBalancer(String[] servers) { | ||
this.servers = new Vector<String>(Arrays.asList(servers)); | ||
} | ||
|
||
/** | ||
* Get a list of all servers managed by this object | ||
* @return Vector of server names | ||
*/ | ||
public Vector<String> getServers() { | ||
return servers; | ||
} | ||
|
||
/** | ||
* Get the number of servers managed by this object. | ||
*/ | ||
public int getNumberOfServers() { | ||
return servers.size(); | ||
} | ||
|
||
/** | ||
* Add a server to be managed by this object | ||
* @param srv Server name | ||
*/ | ||
public void addServer(String srv) { | ||
servers.add(srv); | ||
} | ||
|
||
/** | ||
* Remove a server from this object | ||
* @param srv Server name | ||
*/ | ||
public void removeServer(String srv) { | ||
servers.remove(srv); | ||
} | ||
|
||
/** | ||
* Find out which server should have a given key. This is the | ||
* hash-based load balancing part | ||
* @param key Cache key | ||
* @return Server name | ||
*/ | ||
public String getServerForKey(String key) { | ||
return servers.get(getIndexForKey(key)); | ||
} | ||
|
||
protected int getIndexForKey(String key) { | ||
try { | ||
byte[] byteArr = key.getBytes("UTF-8"); | ||
MessageDigest md = MessageDigest.getInstance("MD5"); | ||
byte[] hash = md.digest(byteArr); | ||
BigInteger h = new BigInteger(1, hash); | ||
return h.mod(BigInteger.valueOf(servers.size())).intValue(); | ||
} catch(Exception e) { | ||
// Java throws some stupid exceptions in case UTF-8 or MD5 | ||
// aren't supported. This is never realistically gonna happen, | ||
// but just in case let's use a randomized balancer in that case. | ||
Random generator = new Random(); | ||
return generator.nextInt(servers.size()); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import junit.framework.TestCase; | ||
|
||
|
||
public class HashBalancerTest extends TestCase { | ||
|
||
public void testGetIndexForKey() { | ||
// Use 16 servers, so the server name is equal to | ||
// the final hex digit of the MD5 hash of the key | ||
String[] servers = {"0", "1", "2", "3", "4", "5", "6", | ||
"7", "8", "9", "a", "b", "c", "d", "e", "f" | ||
}; | ||
|
||
HashBalancer hb = new HashBalancer(servers); | ||
assertEquals("8", hb.getServerForKey("foo")); | ||
assertEquals("2", hb.getServerForKey("bar")); | ||
assertEquals("8", hb.getServerForKey("baz")); | ||
assertEquals("e", hb.getServerForKey("Roan")); | ||
assertEquals("f", hb.getServerForKey("Jan Paul")); | ||
assertEquals("8", hb.getServerForKey("Roy")); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import java.io.FileInputStream; | ||
import java.io.FileNotFoundException; | ||
import java.util.Scanner; | ||
import java.util.Vector; | ||
|
||
public class Main | ||
{ | ||
ICache cache; | ||
|
||
/** | ||
* Init using "java Main configfile.txt serverId cacheSize" | ||
* where configfile.txt is a newline separated list of RMI | ||
* paths, serverId is an integer that denotes the current | ||
* instance (by referring to a line in configfile.txt) and | ||
* cacheSize is the size of the local cache. | ||
* | ||
* If anything fails, a basic cache is used that doesn't use | ||
* RMI. | ||
*/ | ||
public Main(String[] args) | ||
{ | ||
try { | ||
Scanner scanner = new Scanner(new FileInputStream(args[1])); | ||
Vector<String> serverNames = new Vector<String>(); | ||
|
||
while (scanner.hasNextLine()) { | ||
serverNames.add(scanner.nextLine()); | ||
} | ||
|
||
cache = new RemoteCache((String[])serverNames.toArray(), Integer.parseInt(args[2]), new BasicCache(Integer.parseInt(args[3]))); | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
System.out.println("Using basic cache..."); | ||
cache = new BasicCache(); | ||
} | ||
|
||
// TODO: instantiate HTTP server | ||
} | ||
|
||
public static void main(String[] args) | ||
{ | ||
new Main(args); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import java.net.MalformedURLException; | ||
import java.rmi.Naming; | ||
import java.rmi.RemoteException; | ||
|
||
public class RemoteCache implements ICache | ||
{ | ||
CacheServer cache; | ||
HashBalancer hb; | ||
|
||
public RemoteCache(String[] serverNames, int localId, ICache localCache) | ||
{ | ||
try { | ||
cache = new CacheServer(localCache); | ||
Naming.rebind(serverNames[localId], cache); | ||
hb = new HashBalancer(serverNames); | ||
} catch (RemoteException e) { | ||
e.printStackTrace(); | ||
} catch (MalformedURLException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
|
||
public void clear() | ||
{ | ||
for (String server : hb.getServers()) | ||
{ | ||
try { | ||
((ICache)Naming.lookup(server)).clear(); | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
} | ||
|
||
public String get(String key) | ||
{ | ||
return getCacheServer(key).get(key); | ||
} | ||
|
||
public void set(String key, String val) | ||
{ | ||
getCacheServer(key).set(key, val); | ||
} | ||
|
||
private ICache getCacheServer(String key) | ||
{ | ||
try { | ||
return (ICache)Naming.lookup(hb.getServerForKey(key)); | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
|
||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters