X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Forg%2Fvamsas%2Fclient%2Fsimpleclient%2FClientsFile.java;h=598bfdd2996724a557ad218175ce13c4f0677d23;hb=65a8158d49f3c25e78deba6ddd2f4a83fc695821;hp=132280e504cc0a36e8c4f83a62594216da7e87da;hpb=de5c431d734c37ef35afb58a849a321010df1a99;p=vamsas.git diff --git a/src/org/vamsas/client/simpleclient/ClientsFile.java b/src/org/vamsas/client/simpleclient/ClientsFile.java index 132280e..598bfdd 100644 --- a/src/org/vamsas/client/simpleclient/ClientsFile.java +++ b/src/org/vamsas/client/simpleclient/ClientsFile.java @@ -1,4 +1,5 @@ package org.vamsas.client.simpleclient; + import org.vamsas.client.*; import java.io.BufferedInputStream; @@ -16,71 +17,246 @@ import java.io.OutputStream; import java.util.Vector; /** - * @author jim - * Handler for the clientsFile within a vamsas session. + * Handler for the clientsFile within a vamsas session thread. + * @author jim */ -public class ClientsFile { - private File filelist; +public class ClientsFile extends ListFile { /** - * number of my client in list - * (not known at start but used when known to make lock) + * number of my client in list - passed back when a client + * is added to list, and used (if valid) for quickly + * looking up presence of client handle in the list. */ - private int syncnum=1; - - ClientsFile(File filelist) { - this.filelist=filelist; + private int syncnum = 1; + + public ClientsFile(File filelist) throws IOException { + super(filelist); } + + /** + * internal method for getting clientList - ensures a lock has been made but + * does not release it. + * + * @return list of clients + */ + private ClientHandle[] retrieveClientHandles() { + if (lockFile()) { + try { + ClientHandle[] clients=null; + if (this.fileLock.rafile.length()>0) { + ObjectInputStream is = new ObjectInputStream(new BufferedInputStream( + new java.io.FileInputStream(sessionFile))); + Object o; + o=is.readObject(); + if (o!=null) { + try { + clients = (ClientHandle[]) o; + } + catch (Exception e) { + System.err.println("Garbage in the clientHandle list "+this.sessionFile); + } + } + } + return clients; + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(System.err); + } catch (Exception e) { + e.printStackTrace(System.err); + } + } + return null; + } + /** + * get the clientList from the file. May return null if lock failed! + * @return clientList + */ public ClientHandle[] retrieveClientList() { - if (filelist!=null) { - if (filelist.exists()) { - Lock listlock; - do { - listlock = new Lock(filelist); // TODO: wait around if we can't get the lock. - } while (!listlock.isLocked()); - try { - ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(new java.io.FileInputStream(filelist))); - ClientHandle[] clients; - clients = (ClientHandle[]) ((Vector) is.readObject()).toArray(); - return clients; + if (lockFile()) { + ClientHandle[] clients = retrieveClientHandles(); + unlockFile(); + return clients; + } + return null; + } + /** + * get list from the locked ClientList. + * @param extantlock + * @return clientList or null if lock failed (or file was empty) + */ + public ClientHandle[] retrieveClientList(Lock extantlock) { + if (lockFile(extantlock)) { + ClientHandle[] clients = retrieveClientHandles(); + unlockFile(); + return clients; + } + return null; + } + /** + * adds clientHandle me to the clientList under an existing lock extantLock. + * @param me + * @param extantLock + * @return client index in list or 0 if lock was invalid or addClient operation failed. + */ + public int addClient(ClientHandle me, Lock extantLock) { + return addClient(me, true, extantLock); + } + + /** + * adds clientHandle me to the clientList under an existing lock. + * @param me - clientHandle + * @param disambig - if true then add will fail if an identical clientHandle already exists + * @param extantLock - existing lock + * @return client index in list or 0 if addClient (or the lock) failed. + */ + + public int addClient(ClientHandle me, boolean disambig, Lock extantLock) { + if (lockFile(extantLock)) { + syncnum = addClient(me, disambig); + unlockFile(); + return syncnum; + } + return 0; + } + + /** + * adds the ClientHandle to the list - if it is not unique, then the + * ClientHandle object is modified to make it unique in the list. returns the + * clientNumber for the client in the session. + * + * @param me + * @return + */ + + public int addClient(ClientHandle me) { + syncnum = addClient(me, true); + unlockFile(); + return syncnum; + } + + /** + * removes 'me' from the session ClientList without complaint if 'me' isn't in the clientList already. + * @param me client handle to be removed + * @param clientlock existing lock passed from watcher. + */ + public void removeClient(ClientHandle me, Lock clientlock) { + int mynum=-1; + if (lockFile(clientlock)) { + ClientHandle[] clients = retrieveClientHandles(); + if (clients != null) { + if ((syncnum<=0 || syncnum>clients.length) || clients[syncnum-1]!=me) { + for (int i = 0, j = clients.length; i < j; i++) + if (clients[i].equals(me)) { + mynum=i; + break; + } + } else { + mynum=syncnum-1; } - catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); + if (mynum>-1) { + ClientHandle[] newlist = new ClientHandle[clients.length - 1]; + for (int k=0,i = 0, j = clients.length; i < j; i++) + if (i!=mynum) + newlist[k++] = clients[i]; + if (!putClientList(newlist)) + throw new Error("Failed to write new clientList!"); // failed to put the clientList to disk. } } - // else return null. + unlockFile(); } else { - throw new Error("Tried to retrieve a clientList without specifying client list filename"); + throw new Error("Couldn't get lock for "+((sessionFile==null) ? "Unitialised sessionFile in ClientsFile" : sessionFile.getAbsolutePath())); } - return null; - } - public boolean putClientList(ClientHandle[] clients) { - if (filelist!=null) { - if (filelist.exists()) { - Lock listlock; - do { - listlock = new Lock(filelist); // TODO: wait around if we can't get the lock? should return and make client wait until write has finished so it can read new client info... - } while (!listlock.isLocked()); + /** + * Adds a ClientHandle to the ClientList file - optionally disambiguating + * the ClientHandle (modifes the URN). + * Note: Caller is left to release the lock on the ClientList. + * @param me + * @param disambiguate - + * flag indicating if the URN for me should be disambiguated to + * differentiate between sessions. + * @return index of clientHandle in new list, or -1-position of existing + * clientHandle (if disambiguate is true) + */ + protected int addClient(ClientHandle me, boolean disambiguate) { + int newclient = 0; + if (lockFile()) { + ClientHandle[] clients = retrieveClientHandles(); + if (me.getClientUrn()==null) { + // TODO: move this into ClientUrn as a standard form method. + me.setClientUrn("vamsas://"+me.getClientName()+":"+me.getVersion()+"/"); + } + if (clients == null) { + clients = new ClientHandle[1]; + clients[0] = me; + newclient = 1; + } else { + int k = 0; + for (int i = 0, j = clients.length; i < j; i++) { + if (clients[i].equals(me)) { + if (disambiguate) { + while (clients[i].equals(me)) { + me.setClientUrn(me.getClientUrn() + k++); // TODO: make a better + // disambiguation of + // urn. + } + } else { + // will not write the ambiguous clientHandle to disk, just return + // its index. + return -1 - i; + } + } + } + int i, j; + ClientHandle[] newlist = new ClientHandle[clients.length + 1]; + for (i = 0, j = clients.length; i < j; i++) + newlist[i] = clients[i]; + newlist[j] = me; + clients = newlist; + newclient = j+1; + } + if (!putClientList(clients)) + return 0; // failed to put the clientList to disk. + } + return newclient; + } + + /** + * safely writes clients array to the file referred to by sessionFile. + * + * @param clients + * @return true if successful write. Throws Errors otherwise. + */ + protected boolean putClientList(ClientHandle[] clients) { + if (lockFile()) { + File templist = backupSessionFile(); + if (templist != null) { try { - File templist=File.createTempFile(filelist.getName(),".temp",filelist); - ObjectOutputStream os = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(templist))); + fileLock.rafile.setLength(0); + ObjectOutputStream os = new ObjectOutputStream( + new BufferedOutputStream(new FileOutputStream(this.sessionFile))); os.writeObject(clients); os.close(); - } - catch (FileNotFoundException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + // All done - remove the backup. + templist.delete(); + templist = null; } catch (Exception e) { - e.printStackTrace(); + if (templist != null) { + System.err + .println("Serious - problems writing to sessionFile. Backup in " + + templist.getAbsolutePath()); + e.printStackTrace(System.err); + } } + } else { + throw new Error( + "Couldn't create backup of the clientList before writing to it!"); } - // else return null. } else { - throw new Error("Tried to retrieve a clientList without specifying client list filename"); + throw new Error("Could not lock the clientList: " + + ((sessionFile == null) ? "Unitialized ClientsFile" + : " failed to get lock on " + sessionFile.getAbsolutePath())); } - return false; + // successful! + return true; } }