Added some algorithms and moved some files and fixed some comments

This commit is contained in:
Ziver Koc 2009-02-26 17:10:57 +00:00
parent 017a27931a
commit 9297bea93d
25 changed files with 1043 additions and 192 deletions

View file

@ -7,6 +7,8 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.BitSet;
import zutil.struct.DynamicByteArrayStream;
public class Converter {
/**
@ -14,19 +16,42 @@ public class Converter {
*
* @param object the object to convert.
* @return the associated byte array.
* @throws IOException
*/
public static byte[] toBytes(Object object){
public static byte[] toBytes(Object object) throws IOException{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try{
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.flush();
oos.close();
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.flush();
oos.close();
return baos.toByteArray();
}
/**
* Converts a Integer to an byte array
*
* @param num is the number to convert
* @return an byte array of four bytes
*/
public static byte[] toBytes(int num){
return new byte[]{
(byte)(num & 0xff),
(byte)((num >> 8)& 0xff),
(byte)((num >> 16)& 0xff),
(byte)((num >> 24)& 0xff)};
}
/**
* Converts a Integer to an byte
*
* @param num is the number to convert
* @return an byte
*/
public static byte toByte(int num){
return (byte)(num & 0xff);
}
/**
* Converts an array of bytes back to its constituent object. The
@ -34,20 +59,33 @@ public class Converter {
*
* @param bytes the byte array to convert.
* @return the associated object.
* @throws Exception
*/
public static Object toObject(byte[] bytes) {
public static Object toObject(byte[] bytes) throws Exception{
Object object = null;
try{
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois= new ObjectInputStream(bais);
object = ois.readObject();
ois.close();
bais.close();
}catch(IOException ioe){
System.out.println(ioe.getMessage());
}catch(ClassNotFoundException cnfe){
System.out.println(cnfe.getMessage());
}
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
object = ois.readObject();
ois.close();
return object;
}
/**
* Converts an array of bytes back to its constituent object. The
* input array is assumed to have been created from the original object.
*
* @param bytes the byte array to convert.
* @return the associated object.
* @throws Exception
*/
public static Object toObject(DynamicByteArrayStream bytes) throws Exception{
Object object = null;
ObjectInputStream ois = new ObjectInputStream(bytes);
object = ois.readObject();
ois.close();
return object;
}
@ -69,25 +107,70 @@ public class Converter {
return false;
}
// array neaded for byteToHex
/** array needed for byteToHex */
private static char[] HEX_CHARS = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
/**
* Converts a byte Array to a Hex String
*
* @param raw the byte arrat to convert
* @param raw the byte array to convert
* @return a Hex String
*/
public static String toHexString(byte[][] raw){
StringBuffer ret = new StringBuffer();
for(byte[] a : raw){
for(byte b : a){
ret.append(HEX_CHARS[(int) (b >>> 0x04)& 0x0F ]);
ret.append(HEX_CHARS[(int) b & 0x0F ]);
}
}
return ret.toString();
}
public static String toHexStringByColumn(byte[][] raw){
StringBuffer ret = new StringBuffer();
for(int col=0; col<raw[0].length ;col++){
for(int row=0; row<raw.length ;row++){
ret.append(HEX_CHARS[(int) (raw[row][col] >>> 0x04)& 0x0F ]);
ret.append(HEX_CHARS[(int) raw[row][col] & 0x0F ]);
}
}
return ret.toString();
}
/**
* Converts a byte Array to a Hex String
*
* @param raw the byte array to convert
* @return a Hex String
*/
public static String toHexString(byte[] raw){
StringBuffer ret = new StringBuffer();
for(byte b : raw){
ret.append(HEX_CHARS[(int) b & 0x0F ]);
ret.append(HEX_CHARS[(int) (b >>> 0x04)& 0x0F ]);
ret.append(HEX_CHARS[(int) b & 0x0F ]);
}
return ret.toString();
}
/**
* Converts a byte to a Hex String
*
* @param raw the byte to convert
* @return a Hex String
*/
public static String toHexString(byte raw){
String ret = ""+HEX_CHARS[(int) (raw >>> 0x04)& 0x0F ];
ret += ""+HEX_CHARS[(int) raw & 0x0F ];
return ret;
}
/**
* Converts the given byte to a String with 1's and 0's
*
@ -101,7 +184,7 @@ public class Converter {
}
return ret.toString();
}
/**
* Converts the given byte array to a String with 1's and 0's
*
@ -117,7 +200,7 @@ public class Converter {
}
return ret.toString();
}
/**
* Converts a BitSet to a Integer
*
@ -126,14 +209,30 @@ public class Converter {
*/
public static int toInt(BitSet bits){
int ret = 0;
for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i+1)) {
ret += Math.pow(2, i);
}
for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i+1)) {
ret += Math.pow(2, i);
}
return ret;
}
/**
* Converts a boolean array(bit sequence whit most significant bit at index 0) to a Integer
*
* @param bits the boolean array to convert
* @return a Integer
*/
public static int toInt(boolean[] bits){
int ret = 0;
for (int i = bits.length-1; i >= 0; i--) {
if(bits[i])ret += Math.pow(2, bits.length-i-1);
}
return ret;
}
/**
* Converts a Integer to a BitSet
*

View file

@ -52,7 +52,7 @@ public class Hasher {
public static String MD5(Serializable object){
try {
return hash(object, "MD5");
} catch (NoSuchAlgorithmException e) {
} catch (Exception e) {
e.printStackTrace();
}
return null;
@ -67,7 +67,7 @@ public class Hasher {
public static String SHA1(Serializable object){
try {
return hash(object, "SHA-1");
} catch (NoSuchAlgorithmException e) {
} catch (Exception e) {
e.printStackTrace();
}
return null;
@ -80,8 +80,9 @@ public class Hasher {
* @param hashType The hash method (MD2, MD5, SHA-1, SHA-256, SHA-384, SHA-512 )
* @return String containing the hash
* @throws NoSuchAlgorithmException
* @throws IOException
*/
public static String hash(Serializable object, String hashType) throws NoSuchAlgorithmException {
public static String hash(Serializable object, String hashType) throws Exception {
MessageDigest md = null;
md = MessageDigest.getInstance(hashType); //MD5 || SHA
md.update(Converter.toBytes(object));
@ -97,8 +98,9 @@ public class Hasher {
* @param object The Key
* @param seed Seed
* @return A MurmurHash of the key
* @throws Exception
*/
public static int MurmurHash(Serializable object, int seed){
public static int MurmurHash(Serializable object, int seed) throws Exception{
byte[] data = Converter.toBytes(object);
int length = data.length;

View file

@ -202,6 +202,7 @@ public class MultiPrintStream extends PrintStream {
*/
@SuppressWarnings("unchecked")
private String dump( Object o , boolean print) {
if(o == null) return "NULL";
StringBuffer buffer = new StringBuffer();
Class oClass = o.getClass();
buffer.append( oClass.getName() );

View file

@ -0,0 +1,117 @@
package zutil.algo;
import java.math.BigInteger;
import java.util.LinkedList;
import zutil.MultiPrintStream;
/**
* Euclidean algorithm is an algorithm to determine
* the greatest common divisor (GCD)
*
* @author Ziver
*
*/
public class EuclideansAlgo {
/**
* Simple Test
* @param args
*/
public static void main(String[] args){
MultiPrintStream.out.println("*** Correct Answer: ");
MultiPrintStream.out.println("java.util.LinkedList{0, 2, 1, 1, 1, 4, 12, 102, 1, 1, 2, 3, 2, 2, 36}");
MultiPrintStream.out.println("GCD: 1");
MultiPrintStream.out.println("*** Integer:");
MultiPrintStream.out.dump(calcGenerators(60728973, 160523347));
MultiPrintStream.out.println("GCD: "+calc(60728973, 160523347));
MultiPrintStream.out.println("*** BigInteger: ");
MultiPrintStream.out.dump(calcGenerators(new BigInteger("60728973"), new BigInteger("160523347")));
MultiPrintStream.out.println("GCD: "+calc(new BigInteger("60728973"), new BigInteger("160523347")));
}
/**
* Runs the Euclidean algorithm on the two input
* values.
*
* @param a is the first integer
* @param b is the second integer
* @return a integer containing the GCD of the integers
*/
public static int calc(int a, int b){
int t;
while( b != 0 ){
t = b;
b = a % b;
a = t;
}
return a;
}
/**
* Runs the Euclidean algorithm on the two input
* values.
*
* @param a is the first BigInteger
* @param b is the second BigInteger
* @return a BigInteger containing the GCD of the BigIntegers
*/
public static BigInteger calc(BigInteger a, BigInteger b){
BigInteger t;
while( !b.equals(BigInteger.ZERO) ){
t = b;
b = a.mod( b );
a = t;
}
return a;
}
/**
* Runs the Euclidean algorithm on the two input
* values to find the generators for the values.
*
* @param a is the first integer
* @param b is the second integer
* @return a list of integers that is generators for a and b
*/
public static LinkedList<Integer> calcGenerators(int a, int b){
LinkedList<Integer> list = new LinkedList<Integer>();
int t;
while( b != 0 ){
list.add( a/b );
t = b;
b = a % b;
a = t;
}
return list;
}
/**
* Runs the Euclidean algorithm on the two input
* values to find the generators for the values.
*
* @param a is the first BigInteger
* @param b is the second BigInteger
* @return a list of BigIntegers that is generators of a and b
*/
public static LinkedList<BigInteger> calcGenerators(BigInteger a, BigInteger b){
LinkedList<BigInteger> list = new LinkedList<BigInteger>();
BigInteger t;
while( !b.equals(BigInteger.ZERO) ){
list.add( new BigInteger("0").add( a.divide( b ) ) );
t = b;
b = a.mod( b );
a = t;
}
return list;
}
}

View file

@ -0,0 +1,68 @@
package zutil.algo;
import java.math.BigInteger;
import java.util.LinkedList;
import zutil.math.ZMath;
/**
* The Wieners algorithm factorizes two big numbers a and b.
* It uses the Euclidien algorithm to calculate the generator of the
* numbers and then uses them to calculate the factorization.
*
* @author Ziver
*
*/
public class WienersAlgo {
/**
* Runs the Wieners algorithm for the given values.
*
* @param n is the first value
* @param e is the second value
* @return a BigInteger array of length two.
* First index is p and second is q.
* If no value was found then it returns null.
*/
public static BigInteger[] calc(BigInteger n, BigInteger e){
BigInteger[] ret = null;
LinkedList<BigInteger> gen = EuclideansAlgo.calcGenerators(e, n);
BigInteger c0 = BigInteger.ONE;
BigInteger c1 = gen.poll();
BigInteger d0 = BigInteger.ZERO;
BigInteger d1 = BigInteger.ONE;
BigInteger t, n1, g;
while(!gen.isEmpty()){
g = gen.poll();
t = c1;
c1 = g.multiply( c1 ).add( c0 );
c0 = t;
t = d1;
d1 = g.multiply( d1 ).add( d0 );
d0 = t;
n1 = d1.multiply( e ).subtract( BigInteger.ONE );
if( n1.mod( c1 ).equals( BigInteger.ZERO ) ){
n1 = n1.divide( c1 );
// x^2 - ( n - n1 +1 )x + n = 0
ret = ZMath.pqFormula(
n.subtract( n1 ).add( BigInteger.ONE ).negate(),
n);
if(ret[0].compareTo( BigInteger.ZERO ) >= 0 &&
ret[1].compareTo( BigInteger.ZERO ) >= 0 &&
ret[0].multiply( ret[1] ).equals( n )){
return ret;
}
}
}
return null;
}
}

View file

@ -1,39 +0,0 @@
package zutil.algo.path;
import java.util.LinkedList;
public class DijkstraPathFinder {
public static LinkedList<PathNode> find(PathNode start, PathNode stop){
// TODO
/*
1
5 dist[source] := 0 // Distance from source to source
6 Q := copy(Graph) // All nodes in the graph are unoptimized - thus are in Q
7 while Q is not empty: // The main loop
8 u := extract_min(Q) // Remove and return best vertex from nodes in two given nodes
// we would use a path finding algorithm on the new graph, such as depth-first search.
9 for each neighbor v of u: // where v has not yet been considered
10 alt = dist[u] + length(u, v)
11 if alt < dist[v] // Relax (u,v)
12 dist[v] := alt
13 previous[v] := u
14 return previous[]
*/
LinkedList<PathNode> path = new LinkedList<PathNode>();
PathNode current = stop;
while(true){
path.addFirst(current);
current = current.getSourceNeighbor();
if(current.equals(start)){
path.addFirst(start);
break;
}
}
return path;
}
}

View file

@ -1,4 +1,4 @@
package zutil.algo;
package zutil.algo.search;
import zutil.algo.sort.sortable.SortableDataList;

View file

@ -12,14 +12,11 @@ public class MySQLConnection {
/**
* Connects to a MySQL server
* @param url The URL of the MySQL server
* @param db The database to connect to
* @param user The user name
* @param password The password
* @throws SQLException
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*
* @param url is the URL of the MySQL server
* @param db is the database to connect to
* @param user is the user name
* @param password is the password
*/
public MySQLConnection(String url,String db,String user, String password) throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException{
Class.forName ("com.mysql.jdbc.Driver").newInstance();
@ -27,11 +24,11 @@ public class MySQLConnection {
}
/**
* Runs a query and returns the result
* NOTE: Don't forget to close the ResultSet and the Statement or it can lead to memory leak tex: rows.getStatement().close();
* @param sql The query to execute
* @return The data that the DB returned
* @throws SQLException
* Runs a query and returns the result.<br>
* <b>NOTE:</b> Don't forget to close the ResultSet and the Statement or it can lead to memory leak tex: rows.getStatement().close();
*
* @param sql is the query to execute
* @return the data that the DB returned
*/
public synchronized ResultSet returnQuery(String sql) throws SQLException{
Statement s = conn.createStatement ();
@ -41,9 +38,9 @@ public class MySQLConnection {
/**
* Runs a query in the MySQL server and returns effected rows
* @param sql The query to execute
* @return Number of rows effected
* @throws SQLException
*
* @param sql is the query to execute
* @return the number of rows effected
*/
public synchronized int updateQuery(String sql) throws SQLException{
Statement s = conn.createStatement ();
@ -53,11 +50,10 @@ public class MySQLConnection {
}
/**
* Runs a Prepared Statement
* NOTE: Don't forget to close the PreparedStatement or it can lead to memory leak
* @param sql The SQL to run
* Runs a Prepared Statement.<br>
* <b>NOTE:</b> Don't forget to close the PreparedStatement or it can lead to memory leak
* @param sql is the SQL query to run
* @return The PreparedStatement
* @throws SQLException
*/
public synchronized PreparedStatement prepareStatement(String sql) throws SQLException{
return conn.prepareStatement(sql);
@ -65,8 +61,6 @@ public class MySQLConnection {
/**
* Disconnects from the database
* @throws SQLException
*
*/
public synchronized void close() throws SQLException{
if (conn != null){

View file

@ -1,5 +1,7 @@
package zutil.math;
import java.math.BigInteger;
/**
* Very Simple math functions
*
@ -8,9 +10,68 @@ package zutil.math;
public class ZMath {
/**
* Calculates the percentige the value has
* Calculates the percentage of the values
*/
public static double percent(int min, int max, int value){
return ((double)(value-min)/(max-min))*100;
}
/**
* Solves the equation: x^2 + px + q = 0
*
* @return the two values of x as an array
*/
public static double[] pqFormula(double p, double q){
double[] ret = new double[2];
double t = (p/2);
ret[0] = Math.sqrt( t*t - q );
ret[1] = -ret[0];
t *= -1;
ret[0] += t;
ret[1] += t;
return ret;
}
/**
* Solves the equation: x^2 + px + q = 0.
* WARNING: This uses only BigInteger, thereby removing the decimals in the calculation
*
* @return the two values of x as an array
*/
public static BigInteger[] pqFormula(BigInteger p, BigInteger q){
BigInteger[] ret = new BigInteger[2];
BigInteger t = p.divide( BigInteger.valueOf(2) );
ret[0] = ZMath.sqrt( t.multiply( t ).subtract( q ) );
ret[1] = ret[0].negate();
t = t.negate();
ret[0] = ret[0].add( t );
ret[1] = ret[1].add( t );
return ret;
}
/**
* Calculates the square root of a big number
*
*/
public static BigInteger sqrt(BigInteger value){
BigInteger op = value;
BigInteger res = BigInteger.ZERO;
BigInteger one = BigInteger.ONE;
while( one.compareTo( op ) < 0 ){
one = one.shiftLeft( 2 );
}
one = one.shiftRight(2);
while( !one.equals( BigInteger.ZERO ) ){
if( op.compareTo( res.add( one ) ) >= 0 ){
op = op.subtract( res.add( one ) );
res = res.add( one.shiftLeft( 1 ) );
}
res = res.shiftRight( 1 );
one = one.shiftRight( 2 );
}
return res;
}
}

View file

@ -14,11 +14,11 @@ public interface HttpPage{
* This method is called when a client wants a response
* from this specific page.
*
* @param out The PrintStream to the client
* @param client_info Information about the client
* @param session Session values for the client
* @param cookie Cookie information from the client
* @param request POST and GET requests from the client
* @param out is the PrintStream to the client
* @param client_info is information about the client
* @param session is session values for the client
* @param cookie is cookie information from the client
* @param request is POST and GET requests from the client
*/
public abstract void respond(HttpPrintStream out,
HashMap<String,String> client_info,

View file

@ -38,8 +38,8 @@ public class HttpPrintStream extends PrintStream{
/**
* Adds a cookie that will be sent to the client
*
* @param key The name of the cookie
* @param value The value of the cookie
* @param key is the name of the cookie
* @param value is the value of the cookie
* @throws Exception Throws exception if the header has already been sent
*/
public void setCookie(String key, String value) throws Exception{
@ -52,7 +52,7 @@ public class HttpPrintStream extends PrintStream{
* Sends the given header directly to the client.
* No buffering involved.
*
* @param header The header to send
* @param header is the header to send
* @throws Exception Throws exception if the header has already been sent
*/
public void sendHeader(String header) throws Exception{
@ -62,7 +62,7 @@ public class HttpPrintStream extends PrintStream{
}
/**
* prints whit a new line
* Prints with a new line
*/
public void println(String s){
printOrBuffer(s+"\n");
@ -97,7 +97,7 @@ public class HttpPrintStream extends PrintStream{
}
/**
* Sends out all the buffer and clears it
* Sends out the buffer and clears it
*/
public void flush(){
if(buffer_enabled){

View file

@ -1,7 +1,6 @@
package zutil.network.nio;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
@ -26,6 +25,7 @@ import zutil.network.nio.server.ChangeRequest;
import zutil.network.nio.server.ClientData;
import zutil.network.nio.worker.SystemWorker;
import zutil.network.nio.worker.Worker;
import zutil.struct.DynamicByteArrayStream;
public abstract class NioNetwork implements Runnable {
@ -36,7 +36,7 @@ public abstract class NioNetwork implements Runnable {
* 2 = message debug
* 3 = selector debug
*/
public static final int DEBUG = 1;
public static final int DEBUG = 2;
public static enum NetworkType {SERVER, CLIENT};
private NetworkType type;
@ -60,7 +60,8 @@ public abstract class NioNetwork implements Runnable {
// A list of PendingChange instances
private List<ChangeRequest> pendingChanges = new LinkedList<ChangeRequest>();
// Maps a SocketChannel to a list of ByteBuffer instances
private Map<SocketChannel, List<ByteBuffer>> pendingData = new HashMap<SocketChannel, List<ByteBuffer>>();
private Map<SocketChannel, List<ByteBuffer>> pendingWriteData = new HashMap<SocketChannel, List<ByteBuffer>>();
private Map<SocketChannel, DynamicByteArrayStream> pendingReadData = new HashMap<SocketChannel, DynamicByteArrayStream>();
// The encrypter
private Encrypter encrypter;
@ -102,11 +103,11 @@ public abstract class NioNetwork implements Runnable {
(encrypter != null ? "Enabled("+encrypter.getAlgorithm()+")" : "Disabled")+"!!");
}
public void send(SocketChannel socket, Object data) {
public void send(SocketChannel socket, Object data) throws IOException{
send(socket, Converter.toBytes(data));
}
public void send(InetSocketAddress address, Object data){
public void send(InetSocketAddress address, Object data) throws IOException{
send(address, Converter.toBytes(data));
}
@ -140,11 +141,11 @@ public abstract class NioNetwork implements Runnable {
protected void queueSend(SocketChannel socket, byte[] data){
if(DEBUG>=3)MultiPrintStream.out.println("Sending Queue...");
// And queue the data we want written
synchronized (pendingData) {
List<ByteBuffer> queue = pendingData.get(socket);
synchronized (pendingWriteData) {
List<ByteBuffer> queue = pendingWriteData.get(socket);
if (queue == null) {
queue = new ArrayList<ByteBuffer>();
pendingData.put(socket, queue);
pendingWriteData.put(socket, queue);
}
//encrypts
if(encrypter != null)
@ -266,8 +267,10 @@ public abstract class NioNetwork implements Runnable {
key.cancel();
socketChannel.close();
clients.remove(remoteAdr);
pendingReadData.remove(socketChannel);
pendingWriteData.remove(socketChannel);
if(DEBUG>=1)MultiPrintStream.out.println("Connection Forced Close("+remoteAdr+")!!! Connection Count: "+clients.size());
if(type == NetworkType.CLIENT) throw new ConnectException("Server Closed The Connection!!!");
if(type == NetworkType.CLIENT) throw new IOException("Server Closed The Connection!!!");
return;
}
@ -277,8 +280,10 @@ public abstract class NioNetwork implements Runnable {
key.channel().close();
key.cancel();
clients.remove(remoteAdr);
pendingReadData.remove(socketChannel);
pendingWriteData.remove(socketChannel);
if(DEBUG>=1)MultiPrintStream.out.println("Connection Close("+remoteAdr+")!!! Connection Count: "+clients.size());
if(type == NetworkType.CLIENT) throw new ConnectException("Server Closed The Connection!!!");
if(type == NetworkType.CLIENT) throw new IOException("Server Closed The Connection!!!");
return;
}
@ -286,8 +291,28 @@ public abstract class NioNetwork implements Runnable {
// to the client
byte[] rspByteData = new byte[numRead];
System.arraycopy(readBuffer.array(), 0, rspByteData, 0, numRead);
if(encrypter != null)// Encryption
rspByteData = encrypter.decrypt(rspByteData);
handleRecivedMessage(socketChannel, rspByteData);
/*
if(!pendingReadData.containsKey(socketChannel)){
pendingReadData.put(socketChannel, new DynamicByteArrayStream());
}
if(encrypter != null)// Encryption
rspByteData = encrypter.decrypt(rspByteData);
pendingReadData.get(socketChannel).add(rspByteData);
*/
Object rspData = null;
try{
rspData = Converter.toObject(rspByteData);
//rspData = Converter.toObject(pendingReadData.get(socketChannel));
handleRecivedMessage(socketChannel, rspData);
//pendingReadData.get(socketChannel).clear();
}catch(Exception e){
e.printStackTrace();
}
}
/**
@ -296,18 +321,22 @@ public abstract class NioNetwork implements Runnable {
private void write(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
synchronized (pendingData) {
List<ByteBuffer> queue = pendingData.get(socketChannel);
synchronized (pendingWriteData) {
List<ByteBuffer> queue = pendingWriteData.get(socketChannel);
if(queue == null){
queue = new ArrayList<ByteBuffer>();
}
int i = 0;
// Write until there's not more data ...
while (!queue.isEmpty()) {
ByteBuffer buf = queue.get(0);
i += buf.remaining();
socketChannel.write(buf);
i -= buf.remaining();
if (buf.remaining() > 0) {
// ... or the socket's buffer fills up
if(DEBUG>=3)MultiPrintStream.out.println("Write Buffer Full!!");
break;
}
queue.remove(0);
@ -323,14 +352,8 @@ public abstract class NioNetwork implements Runnable {
}
}
private void handleRecivedMessage(SocketChannel socketChannel, byte[] rspByteData){
//Encryption
Object rspData;
if(encrypter != null)
rspData = Converter.toObject(encrypter.decrypt(rspByteData));
else rspData = Converter.toObject(rspByteData);
private void handleRecivedMessage(SocketChannel socketChannel, Object rspData){
if(DEBUG>=2)MultiPrintStream.out.println("Handling incomming message...");
if(rspData instanceof SystemMessage){
if(systemWorker != null){
if(DEBUG>=3)MultiPrintStream.out.println("System Message!!!");
@ -347,13 +370,13 @@ public abstract class NioNetwork implements Runnable {
worker.processData(this, socketChannel, rspData);
}
else{
if(DEBUG>=1)MultiPrintStream.out.println("Unhandled Message!!!");
if(DEBUG>=1)MultiPrintStream.out.println("Unhandled Worker Message!!!");
}
}
}
/**
* Initializes a socket to the server
* Initializes a socket to a server
*/
protected SocketChannel initiateConnection(InetSocketAddress address) throws IOException {
// Create a non-blocking socket channel

View file

@ -0,0 +1,84 @@
package zutil.network.nio.message;
public class GridMessage<T> extends Message{
private static final long serialVersionUID = 1L;
// Client type messages
/** Computation job return right answer **/
public static final int COMP_SUCCESSFUL = 1; //
/** Initial static data **/
public static final int COMP_INCORRECT = 2; //
/** Computation job return wrong answer **/
public static final int COMP_ERROR = 3; //
/** There was an error computing **/
public static final int REGISTER = 4; //
/** Register at the server **/
public static final int UNREGISTER = 5; //
/** Request new computation data **/
public static final int NEW_DATA = 6; //
// Server type messages
/** Sending initial static data **/
public static final int INIT_DATA = 100;
/** Sending new dynamic data **/
public static final int COMP_DATA = 101;
private int type;
private int jobID;
private T data;
/**
* Creates a new GridMessage
*
* @param type is the type of message
* @param jobID is the id of the job
*/
public GridMessage(int type){
this(type, 0, null);
}
/**
* Creates a new GridMessage
*
* @param type is the type of message
* @param jobID is the id of the job
*/
public GridMessage(int type, int jobID){
this(type, jobID, null);
}
/**
* Creates a new GridMessage
*
* @param type is the type of message
* @param jobID is the id of the job
* @param data is the data to send with this message
*/
public GridMessage(int type, int jobID, T data){
this.type = type;
this.jobID = jobID;
this.data = data;
}
/**
* @return the type of message
*/
public int messageType(){
return type;
}
/**
* @return the job id for this message
*/
public int getJobQueueID(){
return jobID;
}
/**
* @return the data in this message, may not always carry any data.
*/
public T getData(){
return data;
}
}

View file

@ -21,38 +21,42 @@ public class ChatService extends NetworkService{
@Override
public void handleMessage(Message message, SocketChannel socket) {
// New message
if(message instanceof ChatMessage){
ChatMessage chatmessage = (ChatMessage)message;
//is this a new message
if(chatmessage.type == ChatMessage.ChatMessageType.MESSAGE){
// Is this the server
if(nio.getType() == NioNetwork.NetworkType.SERVER){
if(rooms.containsKey(chatmessage.room)){
LinkedList<SocketChannel> tmpList = rooms.get(chatmessage.room);
try {
// New message
if(message instanceof ChatMessage){
ChatMessage chatmessage = (ChatMessage)message;
//is this a new message
if(chatmessage.type == ChatMessage.ChatMessageType.MESSAGE){
// Is this the server
if(nio.getType() == NioNetwork.NetworkType.SERVER){
if(rooms.containsKey(chatmessage.room)){
LinkedList<SocketChannel> tmpList = rooms.get(chatmessage.room);
// Broadcast the message
for(SocketChannel s : tmpList){
if(s.isConnected()){
nio.send(s, chatmessage);
}
else{
unRegisterUser(chatmessage.room, s);
// Broadcast the message
for(SocketChannel s : tmpList){
if(s.isConnected()){
nio.send(s, chatmessage);
}
else{
unRegisterUser(chatmessage.room, s);
}
}
}
}
if(NioNetwork.DEBUG>=2)MultiPrintStream.out.println("New Chat Message: "+chatmessage.msg);
listener.messageAction(chatmessage.msg, chatmessage.room);
}
// register to a room
else if(chatmessage.type == ChatMessage.ChatMessageType.REGISTER){
registerUser(chatmessage.room, socket);
}
// unregister to a room
else if(chatmessage.type == ChatMessage.ChatMessageType.UNREGISTER){
unRegisterUser(chatmessage.room, socket);
}
if(NioNetwork.DEBUG>=2)MultiPrintStream.out.println("New Chat Message: "+chatmessage.msg);
listener.messageAction(chatmessage.msg, chatmessage.room);
}
// register to a room
else if(chatmessage.type == ChatMessage.ChatMessageType.REGISTER){
registerUser(chatmessage.room, socket);
}
// unregister to a room
else if(chatmessage.type == ChatMessage.ChatMessageType.UNREGISTER){
unRegisterUser(chatmessage.room, socket);
}
} catch (Exception e) {
e.printStackTrace();
}
}

View file

@ -1,14 +1,20 @@
package zutil.network.nio.worker;
import java.io.IOException;
import zutil.MultiPrintStream;
public class EchoWorker extends ThreadedEventWorker {
@Override
public void messageEvent(WorkerDataEvent dataEvent) {
// Return to sender
MultiPrintStream.out.println("Recived Msg: "+dataEvent.data);
dataEvent.network.send(dataEvent.socket, dataEvent.data);
try {
// Return to sender
MultiPrintStream.out.println("Recived Msg: "+dataEvent.data);
dataEvent.network.send(dataEvent.socket, dataEvent.data);
} catch (IOException e) {
e.printStackTrace();
}
}

View file

@ -33,27 +33,31 @@ public class SystemWorker extends ThreadedEventWorker {
@Override
public void messageEvent(WorkerDataEvent event) {
if(NioNetwork.DEBUG>=2)MultiPrintStream.out.println("System Message: "+event.data.getClass().getName());
if(event.data instanceof Message){
if(event.data instanceof EchoMessage && ((EchoMessage)event.data).echo()){
// Echos back the recived message
((EchoMessage)event.data).recived();
if(NioNetwork.DEBUG>=3)MultiPrintStream.out.println("Echoing Message: "+event.data);
nio.send(event.socket, event.data);
}
else if(event.data instanceof ResponseRequestMessage &&
rspEvents.get(((ResponseRequestMessage)event.data).getResponseId()) != null){
// Handle the response
handleResponse(((ResponseRequestMessage)event.data).getResponseId(), event.data);
if(NioNetwork.DEBUG>=3)MultiPrintStream.out.println("Response Request Message: "+event.data);
}
else{
//Services
if(services.containsKey(event.data.getClass()) ||
!services.containsKey(event.data.getClass()) && defaultServices(event.data)){
services.get(event.data.getClass()).handleMessage((Message)event.data, event.socket);
try {
if(NioNetwork.DEBUG>=2)MultiPrintStream.out.println("System Message: "+event.data.getClass().getName());
if(event.data instanceof Message){
if(event.data instanceof EchoMessage && ((EchoMessage)event.data).echo()){
// Echos back the recived message
((EchoMessage)event.data).recived();
if(NioNetwork.DEBUG>=3)MultiPrintStream.out.println("Echoing Message: "+event.data);
nio.send(event.socket, event.data);
}
else if(event.data instanceof ResponseRequestMessage &&
rspEvents.get(((ResponseRequestMessage)event.data).getResponseId()) != null){
// Handle the response
handleResponse(((ResponseRequestMessage)event.data).getResponseId(), event.data);
if(NioNetwork.DEBUG>=3)MultiPrintStream.out.println("Response Request Message: "+event.data);
}
else{
//Services
if(services.containsKey(event.data.getClass()) ||
!services.containsKey(event.data.getClass()) && defaultServices(event.data)){
services.get(event.data.getClass()).handleMessage((Message)event.data, event.socket);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

View file

@ -0,0 +1,114 @@
package zutil.network.nio.worker.grid;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;
import zutil.MultiPrintStream;
import zutil.network.nio.NioClient;
import zutil.network.nio.message.GridMessage;
import zutil.network.nio.worker.ThreadedEventWorker;
import zutil.network.nio.worker.WorkerDataEvent;
/**
* This class is the client part of the grid.
* It connects to a grid server and requests new job.
* And then sends back the result to the server.
*
* @author Ziver
*/
@SuppressWarnings("unchecked")
public class GridClient extends ThreadedEventWorker {
private static LinkedList<GridJob> jobQueue;
private static GridThread thread;
private static NioClient network;
/**
* Creates a new GridClient object and registers itself at the server
* and sets itself as a worker in NioClient
*
* @param thread the Thread interface to run for the jobs
* @param network the NioClient to use to communicate to the server
*/
public GridClient(GridThread thread, NioClient network){
jobQueue = new LinkedList<GridJob>();
GridClient.thread = thread;
GridClient.network = network;
}
/**
* Starts up the client and a couple of GridThreads.
* And registers itself as a worker in NioClient
* @throws IOException
*/
public void initiate() throws IOException{
network.setDefaultWorker(this);
network.send(new GridMessage(GridMessage.REGISTER));
for(int i=0; i<Runtime.getRuntime().availableProcessors() ;i++){
Thread t = new Thread(thread);
t.start();
}
}
@Override
public void messageEvent(WorkerDataEvent e) {
// ignores other messages than GridMessage
if(e.data instanceof GridMessage){
GridMessage msg = (GridMessage)e.data;
switch(msg.messageType()){
// Receive data from Server
case GridMessage.INIT_DATA:
thread.setInitData(msg.getData());
break;
case GridMessage.COMP_DATA:
jobQueue.add(new GridJob(msg.getJobQueueID(), (Queue)msg.getData()));
break;
}
}
}
/**
* Register whit the server that the job is done
*
* @param jobID is the job id
* @param correct if the answer was right
* @param result the result of the computation
* @throws IOException
*/
public static void jobDone(int jobID, boolean correct, Object result) throws IOException{
if(correct)
network.send(new GridMessage(GridMessage.COMP_SUCCESSFUL, jobID, result));
else
network.send(new GridMessage(GridMessage.COMP_INCORRECT, jobID, result));
}
/**
* Registers with the server that there was an
* error when computing this job
*
* @param jobID is the job id
*/
public static void jobError(int jobID){
try{
network.send(new GridMessage(GridMessage.COMP_SUCCESSFUL, jobID));
}catch(Exception e){e.printStackTrace();}
}
/**
* @return a new job to compute
* @throws IOException
*/
public static synchronized GridJob getNextJob() throws IOException{
if(jobQueue.isEmpty()){
network.send(new GridMessage(GridMessage.NEW_DATA));
while(jobQueue.isEmpty()){
try{Thread.sleep(100);}catch(Exception e){}
}
}
MultiPrintStream.out.println("Starting job");
return jobQueue.poll();
}
}

View file

@ -0,0 +1,22 @@
package zutil.network.nio.worker.grid;
/**
* A internal class for handling the jobs
*
* @author Ziver
*/
public class GridJob{
public int jobID;
public Object job;
public long timestamp;
public GridJob(int jobID, Object job){
this.jobID = jobID;
this.job = job;
renewTimeStamp();
}
public void renewTimeStamp(){
timestamp = System.currentTimeMillis();
}
}

View file

@ -0,0 +1,18 @@
package zutil.network.nio.worker.grid;
/**
* Generates new jobs for the grid to compute
*
* @author Ziver
*/
public interface GridJobGenerator<T> {
/**
* @return static and final values that do not change for every job
*/
public Object initValues();
/**
* @return a new generated job
*/
public T generateJob();
}

View file

@ -0,0 +1,10 @@
package zutil.network.nio.worker.grid;
/**
* Handles the incoming results from the grid
*
* @author Ziver
*/
public interface GridResultHandler<T> {
public void resultEvent(int jobID, boolean correct, T result);
}

View file

@ -0,0 +1,111 @@
package zutil.network.nio.worker.grid;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import zutil.network.nio.message.GridMessage;
import zutil.network.nio.worker.ThreadedEventWorker;
import zutil.network.nio.worker.WorkerDataEvent;
/**
* Implements a simple network computing server
*
* @author Ziver
*/
@SuppressWarnings("unchecked")
public class GridServerWorker extends ThreadedEventWorker{
// Job timeout after 30 min
public static int JOB_TIMEOUT = 1000*60*30;
private HashMap<Integer, GridJob> jobs; // contains all the ongoing jobs
private Queue<GridJob> reSendjobQueue; // Contains all the jobs that will be recalculated
private GridJobGenerator jobGenerator; // The job generator
private GridResultHandler resHandler;
private int nextJobID;
public GridServerWorker(GridResultHandler resHandler, GridJobGenerator jobGenerator){
this.resHandler = resHandler;
this.jobGenerator = jobGenerator;
nextJobID = 0;
jobs = new HashMap<Integer, GridJob>();
reSendjobQueue = new LinkedList<GridJob>();
GridMaintainer maintainer = new GridMaintainer();
maintainer.start();
}
@Override
public void messageEvent(WorkerDataEvent e) {
try {
// ignores other messages than GridMessage
if(e.data instanceof GridMessage){
GridMessage msg = (GridMessage)e.data;
GridJob job = null;
switch(msg.messageType()){
case GridMessage.REGISTER:
e.network.send(e.socket, new GridMessage(GridMessage.INIT_DATA, 0, jobGenerator.initValues()));
break;
// Sending new data to compute to the client
case GridMessage.NEW_DATA:
if(!reSendjobQueue.isEmpty()){ // checks first if there is a job for recalculation
job = reSendjobQueue.poll();
job.renewTimeStamp();
}
else{ // generates new job
job = new GridJob(nextJobID,
jobGenerator.generateJob());
jobs.put(job.jobID, job);
nextJobID++;
}
GridMessage newMsg = new GridMessage(GridMessage.COMP_DATA, job.jobID, job.job);
e.network.send(e.socket, newMsg);
break;
// Received computation results
case GridMessage.COMP_SUCCESSFUL:
resHandler.resultEvent(msg.getJobQueueID(), true, msg.getData());
break;
case GridMessage.COMP_INCORRECT:
resHandler.resultEvent(msg.getJobQueueID(), false, msg.getData());
break;
case GridMessage.COMP_ERROR: // marks the job for recalculation
job = jobs.get(msg.getJobQueueID());
reSendjobQueue.add(job);
break;
}
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
/**
* Changes the job timeout value
* @param min is the timeout in minutes
*/
public static void setJobTimeOut(int min){
JOB_TIMEOUT = 1000*60*min;
}
class GridMaintainer extends Thread{
/**
* Runs some behind the scenes stuff
* like job timeout.
*/
public void run(){
while(true){
long time = System.currentTimeMillis();
for(int jobID : jobs.keySet()){
if(time-jobs.get(jobID).timestamp > JOB_TIMEOUT){
reSendjobQueue.add(jobs.get(jobID));
}
}
try{Thread.sleep(1000*60*1);}catch(Exception e){};
}
}
}
}

View file

@ -0,0 +1,38 @@
package zutil.network.nio.worker.grid;
/**
* This interface is the thread that will do
* all the computation in the grid
*
* @author Ziver
*/
public abstract class GridThread implements Runnable{
/**
* The initial static and final data will be sent to this
* method.
*
* @param data is the static and or final data
*/
public abstract void setInitData(Object data);
public void run(){
while(true){
GridJob tmp = null;
try {
tmp = GridClient.getNextJob();
compute(tmp);
} catch (Exception e) {
e.printStackTrace();
if(tmp != null){
GridClient.jobError(tmp.jobID);
}
}
}
}
/**
* Compute the given data and return
* @param data
*/
public abstract void compute(GridJob data) throws Exception;
}

View file

@ -41,12 +41,16 @@ public class BloomFilter<T extends Serializable> implements Set<T>, Serializable
* @return If the optimal size has been reached
*/
public boolean add(T e) {
content_size++;
int hash = 0;
for(int i=0; i<k ;i++){
hash = Hasher.MurmurHash(e, hash);
hash = Math.abs(hash) % bits.size();
bits.set(hash, true);
try {
content_size++;
int hash = 0;
for(int i=0; i<k ;i++){
hash = Hasher.MurmurHash(e, hash);
hash = Math.abs(hash) % bits.size();
bits.set(hash, true);
}
} catch (Exception e1) {
e1.printStackTrace();
}
return isFull();
}
@ -77,13 +81,17 @@ public class BloomFilter<T extends Serializable> implements Set<T>, Serializable
* if the Object is not Serializable
*/
public boolean contains(Object o) {
if(!(o instanceof Serializable))return false;
int hash = 0;
for(int i=0; i<k ;i++){
hash = Hasher.MurmurHash((Serializable)o, hash);
hash = Math.abs(hash) % bits.size();
if(!bits.get(hash))
return false;
try {
if(!(o instanceof Serializable))return false;
int hash = 0;
for(int i=0; i<k ;i++){
hash = Hasher.MurmurHash((Serializable)o, hash);
hash = Math.abs(hash) % bits.size();
if(!bits.get(hash))
return false;
}
} catch (Exception e) {
e.printStackTrace();
}
return true;

View file

@ -0,0 +1,106 @@
package zutil.struct;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
public class DynamicByteArrayStream extends InputStream{
/** The byte array container */
private ArrayList<byte[]> bytes;
/** The current size of the stream */
private int size;
/** points to the current index in the Arraylist */
private int globalPointer;
/** points localy in the current index in the ArrayList */
private int localPointer;
/** The current position */
private int currentPos;
/**
* Create a new instance of DynamicByteArrayStream
*/
public DynamicByteArrayStream(){
bytes = new ArrayList<byte[]>();
size = 0;
globalPointer = 0;
localPointer = 0;
currentPos = 0;
}
/**
* Append an byte array to the stream
* @param b The byte array to add
*/
public synchronized void add(byte[] b){
bytes.add(b);
size += b.length;
}
/**
* Clears this stream from the byte arrays
*/
public synchronized void clear(){
size = 0;
globalPointer = 0;
localPointer = 0;
currentPos = 0;
bytes.clear();
}
@Override
public synchronized int read() throws IOException {
if(currentPos >= size){
return -1;
}
int ret = bytes.get(globalPointer)[localPointer] & 0xff;
currentPos++;
localPointer++;
if(localPointer >= bytes.get(globalPointer).length){
globalPointer++;
localPointer = 0;
}
return ret;
}
/*
public synchronized int read(byte b[], int off, int len) {
System.out.println("read off:"+off+" len: "+len);
if(currentPos+off >= size){
return -1;
}
off += localPointer;
while(off>0){
if(bytes.get(globalPointer).length < off){
globalPointer++;
off -= bytes.get(globalPointer).length;
}
else break;
}
int length;
int oldLen = len;
while(len > 0){
length = bytes.get(globalPointer).length;
System.arraycopy(b, 0, bytes.get(globalPointer), 0, (length<len ? length : len));
len -= length;
if(len > 0) globalPointer++;
if(bytes.size() <= globalPointer) break;
}
localPointer = 0;
currentPos += ( len<0 ? oldLen : oldLen-len);
return ( len<0 ? oldLen : oldLen-len);
}*/
public synchronized int available() {
return size - currentPos;
}
public synchronized void reset() {
globalPointer = 0;
localPointer = 0;
currentPos = 0;
}
public void close() throws IOException {
}
}

View file

@ -2,7 +2,7 @@ package zutil.test;
import java.util.Arrays;
import zutil.algo.QuickSelect;
import zutil.algo.search.QuickSelect;
import zutil.algo.sort.sortable.SortableIntArray;
public class QuickSelectTest {