* @author jim
*/
public class ClientsFile extends ListFile {
+ private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(ClientsFile.class);
/**
* number of my client in list - passed back when a client
* is added to list, and used (if valid) for quickly
if (lockFile()) {
try {
ClientHandle[] clients=null;
- if (this.fileLock.rafile.length()>0) {
+ if (fileLock.length()>0) {
ObjectInputStream is = new ObjectInputStream(fileLock.getBufferedInputStream(true));
Object o;
}
return newclient;
}
-
+ /**
+ * when set true - get FileNotFoundExceptions on WinXP when writing to locked stream after the backup has been made (via the backupFile method)
+ */
+ boolean backup=false;
/**
* safely writes clients array to the file referred to by sessionFile.
*
*/
protected boolean putClientList(ClientHandle[] clients) {
if (lockFile()) {
- File templist = backupSessionFile();
- if (templist != null) {
- try {
- // fileLock.rafile.setLength(0);
- ObjectOutputStream os =
- new ObjectOutputStream(fileLock.getBufferedOutputStream(true));
-
-// new BufferedOutputStream(new FileOutputStream(this.sessionFile)));
- // new BufferedOutputStream(new FileOutputStream(this.fileLock.rafile.getFD())));
- os.writeObject(clients);
- os.close(); // close destroys lock!
+ File templist=null;
+ if (!backup || (templist = backupSessionFile()) != null) {
+ int retries=3;
+ while (retries-->0) {
+ try {
+ ObjectOutputStream os =
+ new ObjectOutputStream(fileLock.getBufferedOutputStream(true));
+ log.debug("About to write "+clients.length+" clientHandles to output stream.");
+ os.writeObject(clients);
+ os.close();
// All done - remove the backup.
- templist.delete();
+ if (backup)
+ templist.delete();
templist = null;
- } catch (Exception e) {
- if (templist != null) {
+ retries=-1;
+ } catch (Exception e) {
System.err
- .println("Serious - problems writing to sessionFile. Backup in "
- + templist.getAbsolutePath());
+ .println("Serious - problems writing to sessionFile.");
+ if (retries>0 && templist != null) {
+ System.err.println("Recovering from Backup in "
+ + templist.getAbsolutePath());
+ templist.renameTo(fileLock.target);
+ }
e.printStackTrace(System.err);
}
}
+ if (retries>-2) {
+ System.err
+ .println("Serious - problems writing to sessionFile. Giving Up.");
+ return false;
+ }
} else {
throw new Error(
"Couldn't create backup of the clientList before writing to it!");
// successful!
return true;
}
+
+ public void clearList() {
+ if (lockFile()) {
+ try {
+ FileOutputStream fout = fileLock.getFileOutputStream(true);
+ fout.flush();
+ fout.close();
+ } catch (Exception e) {
+ throw new Error("Problems trying to clear clientlist!",e);
+
+ }
+ }
+
+ }
}
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
-
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+/**
+ * File based Locking mechanism to get around some bizarre limitations of JarEntry seeking.
+ * Abstract locks have a target file, to which access is controlled when a lock is held. Native locks on WindowsXP seem to conflict with Jar seek operations, so a file lock creates an advisory lock.
+ * Method:
+ * A lock file is created, if it doesn't already exist - the naming convention is TargetFile+suffixSeparator+_LockSuffix.
+ * A lock is obtained by locking the lock file with a native lock. The NativeLock is used for this.
+ * @author JimP
+ *
+ */
public class FileLock extends Lock {
- File _lock = null;
+ private File _lock = null;
protected static String _LockSuffix="lck";
+ private NativeLock advisory=null;
+ /**
+ * ensure that the _lock file exists
+ * and create a lock
+ */
+ private boolean ensureLockFile(boolean block) {
+ if (_lock==null)
+ return false;
+ if (advisory!=null && advisory.isLocked())
+ return true;
+ try {
+ advisory=new NativeLock(_lock, block);
+ } catch (Exception e) {
+ log.fatal("Failed to create advisory lock file "+_lock,e);
+ throw new Error("Failed to create advisory lock file "+_lock);
+ }
+ return advisory.isLocked();
+ }
/**
* call to clear up a filelock file after its been made
*
*/
private void tidy() {
- if (_lock!=null) {
- _lock.delete();
+ if (_lock!=null) {
+ if ( advisory!=null)
+ advisory.release(true);
+ advisory=null;
_lock=null;
}
}
/**
* @param lockfile
+ * @param block true means thread blocks until FileLock is obtained.
*/
- public FileLock(File lockfile) {
+ public FileLock(File lockfile, boolean block) {
super(lockfile);
// try and get a lock.
try {
_lock = new File(lockfile.getParentFile(), lockfile.getName()+"."+_LockSuffix);
- if (_lock.exists() || !_lock.createNewFile()) {
- log.debug("Failed to get lock for "+lockfile+" using lockfile "+_lock);
- _lock=null;
+ if (!ensureLockFile(block)) {
+ log.debug("Couldn't get lock on "+_lock);
+ tidy();
return;
}
- _lock.deleteOnExit(); // safe - all locks should be removed on finalization.
// create target file ready to be written to if necessary.
if (!lockfile.exists())
if (!lockfile.createNewFile()) {
log.warn("Failed to create locked file "+lockfile);
return;
}
- openRaFile();
+ //openRaFile();
} catch (FileNotFoundException e) {
//
log.debug("FileLock failed with target="+lockfile+" and lockfile suffix of "+_LockSuffix);
private boolean openRaFile() throws IOException {
if (target==null)
return false;
- if (_lock==null || !_lock.exists())
+ if (advisory==null || !advisory.isLocked())
return false;
- if (rafile==null)
+ if (rafile==null || rafile.getFD()==null || !rafile.getFD().valid()) {
rafile=new RandomAccessFile(target,"rw");
+ } else {
+ if (log.isDebugEnabled())
+ log.debug("Reusing existing RandomAccessFile on "+target);
+ }
return (rafile.getChannel()!=null) && rafile.getChannel().isOpen();
}
public boolean isLocked() {
- if (_lock != null) {
- if (_lock.exists())
+ if (advisory != null) {
+ if (advisory.isLocked())
return true;
- _lock=null;
+ advisory=null;
if (log.isDebugEnabled())
log.debug("Lockfile "+_lock+" unexpectedly deleted ?");
}
}
public void release(boolean closeChannel) {
- if (_lock==null)
+ if (!isLocked())
return;
+ if (log.isDebugEnabled())
+ log.debug("Releasing advisory lock on "+target);
if (closeChannel) {
if (rafile!=null)
try {
}
public FileInputStream getFileInputStream(boolean atStart) throws IOException {
- if (!isLocked())
+ if (!isLocked()) {
+ log.debug("Don't hold lock on "+target+" to get locked FileInputStream.");
return null;
+ }
openRaFile();
if (atStart)
rafile.seek(0);
public FileOutputStream getFileOutputStream(boolean clear) throws IOException {
- if (!isLocked())
+ if (!isLocked()) {
+ log.debug("Don't hold lock on "+target+" to get locked FileOutputStream.");
return null;
+ }
openRaFile();
- if (clear)
+ if (clear) {
+ rafile.seek(0);
rafile.setLength(0);
- else
+ } else
rafile.seek(rafile.length());
return new LockedFileOutputStream(rafile.getFD());
}
public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException {
+ log.debug("Getting BufferedOutputStream (clear="+clear+")");
FileOutputStream fos = getFileOutputStream(clear);
if (fos!=null)
return new BufferedOutputStream(fos);
return null;
}
+ /* (non-Javadoc)
+ * @see org.vamsas.client.simpleclient.Lock#getLength()
+ */
+ public long length() {
+ if (isLocked()) {
+ if (!target.exists()) {
+ try {
+ target.createNewFile();
+ } catch (Exception e) {
+ log.error("Invalid lock:Failed to create target file "+target);
+ tidy();
+ return -1;
+ }
+ return 0;
+ }
+ return target.length();
+ }
+ return -1;
+ }
protected void finalize() throws Throwable {
release(true); // we explicitly lose the lock here.
super.finalize();
}
-
+ public RandomAccessFile getRaFile() throws IOException {
+ if (isLocked() && openRaFile()) {
+ return rafile;
+ }
+ log.debug("Failed to getRaFile on target "+target);
+ return null;
+ }
+ public FileChannel getRaChannel() throws IOException {
+ if (isLocked() && openRaFile()) {
+ return rafile.getChannel();
+ }
+ log.debug("Failed to getRaChannel on target "+target);
+ return null;
+ }
}
if (subjectLock!=null) {
subjectLock.release();
}
- subjectLock = LockFactory.getLock(subject);
+ subjectLock = LockFactory.tryLock(subject);
if (subjectLock.isLocked()) {
return false;
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.RandomAccessFile;
+import java.nio.channels.ByteChannel;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
import org.apache.commons.logging.LogFactory;
return new BufferedInputStream(fis);
return null;
}
+ /**
+ * safe lock target length() function.
+ * @return -1 for non-lockable target, otherwise target's file length
+ */
+ public abstract long length();
+ public abstract RandomAccessFile getRaFile() throws IOException;
+ public abstract FileChannel getRaChannel() throws IOException;
}
package org.vamsas.client.simpleclient;
+import java.io.File;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
log.warn("System property vamsas.locktype takes one of "+lt);
log.warn("Defaulting to Locktype of "+locktypes[locktype]);
}
- }
+ } else
+ log.debug("Defaulting to Locktype of "+locktypes[locktype]);
}
-
+ /**
+ * lock target (blocks until lock is obtained)
+ * @param target
+ * @return lock
+ */
public static Lock getLock(java.io.File target) {
+ return getLock(target, true);
+ }
+ public static Lock getLock(java.io.File target, boolean block) {
if (locktype==0)
- return new FileLock(target);
+ return new FileLock(target, block);
if (locktype==1)
- return new NativeLock(target);
+ return new NativeLock(target, block);
log.fatal("Implementation Error! No valid Locktype value");
return null;
}
+ /**
+ * try to lock target
+ * @param target
+ * @return null if lock was not possible
+ */
+ public static Lock tryLock(File target) {
+ return getLock(target, false);
+ }
}
import java.io.FileNotFoundException;\r
import java.io.FileOutputStream;\r
import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.nio.channels.FileChannel;\r
+\r
+import org.apache.commons.logging.LogFactory;\r
\r
/**\r
* @author Jim\r
*\r
*/\r
public class LockedFileOutputStream extends FileOutputStream {\r
- \r
+ private static org.apache.commons.logging.Log log = LogFactory.getLog(LockedFileOutputStream.class);\r
+ //FileOutputStream ostream=null;\r
+ boolean closed=true;\r
+ private void init() {\r
+ FileChannel ch = super.getChannel();\r
+ if (ch!=null) {\r
+ try { closed = !ch.isOpen();\r
+ } catch (Exception e) {\r
+ closed=true;\r
+ log.debug("Invalid LockedOutputStream marked closed.",e);\r
+ }\r
+ }\r
+ }\r
/**\r
* @param file\r
* @throws FileNotFoundException\r
*/\r
public LockedFileOutputStream(File file) throws FileNotFoundException {\r
- super(file);\r
+ super(file); // super(file);\r
+ init();\r
}\r
\r
/**\r
public LockedFileOutputStream(File file, boolean append)\r
throws FileNotFoundException {\r
super(file, append);\r
+ init();\r
}\r
\r
/**\r
*/\r
public LockedFileOutputStream(FileDescriptor fdObj) {\r
super(fdObj);\r
+ init();\r
+ if (fdObj.valid())\r
+ closed=false;\r
}\r
\r
/**\r
*/\r
public LockedFileOutputStream(String name) throws FileNotFoundException {\r
super(name);\r
+ init();\r
}\r
\r
/**\r
public LockedFileOutputStream(String name, boolean append)\r
throws FileNotFoundException {\r
super(name, append);\r
- // TODO Auto-generated constructor stub\r
+ init();\r
}\r
/**\r
* closes - actually just flushes the stream instead.\r
*/\r
public void close() throws IOException {\r
- // TODO Auto-generated method stub\r
- super.flush();\r
+ if (!closed) {\r
+ super.flush();\r
+ super.getChannel().force(true);\r
+ log.debug("Marking Lockedoutputstream closed.");\r
+ } else\r
+ throw new IOException("Close on already closed FileOutputStream.");\r
+ closed=true;\r
+ }\r
+\r
+\r
+ /**\r
+ * @throws IOException\r
+ * @see java.io.OutputStream#flush()\r
+ */\r
+ public void flush() throws IOException {\r
+ if (!closed)\r
+ super.flush();\r
+ else\r
+ throw new IOException("flush on closed FileOutputStream");\r
+ }\r
+\r
+ /**\r
+ * @return\r
+ * @see java.io.FileOutputStream#getChannel()\r
+ */\r
+ public FileChannel getChannel() {\r
+ if (!closed)\r
+ return super.getChannel();\r
+ else\r
+ return null;\r
+ }\r
+\r
+\r
+\r
+ /**\r
+ * @param b\r
+ * @param off\r
+ * @param len\r
+ * @throws IOException\r
+ * @see java.io.FileOutputStream#write(byte[], int, int)\r
+ */\r
+ public void write(byte[] b, int off, int len) throws IOException {\r
+ if (!closed)\r
+ super.write(b, off, len);\r
+ else\r
+ throw new IOException("write on Closed FileOutputStream");\r
+ }\r
+\r
+ /**\r
+ * @param b\r
+ * @throws IOException\r
+ * @see java.io.FileOutputStream#write(byte[])\r
+ */\r
+ public void write(byte[] b) throws IOException {\r
+ if (!closed)\r
+ super.write(b);\r
+ else\r
+ throw new IOException("write on Closed FileOutputStream");\r
+ }\r
+\r
+ /**\r
+ * @param b\r
+ * @throws IOException\r
+ * @see java.io.FileOutputStream#write(int)\r
+ */\r
+ public void write(int b) throws IOException {\r
+ if (!closed)\r
+ super.write(b);\r
+ else\r
+ throw new IOException("write on Closed FileOutputStream");\r
}\r
\r
}\r
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
+import java.nio.channels.ReadableByteChannel;
+/**
+ * @author JimP
+ *
+ */
public class NativeLock extends Lock {
protected FileLock lock = null;
/**
* @param lockfile
+ * @param block true means thread will block until a lock is obtained.
*/
- public NativeLock(File lockfile) {
+ public NativeLock(File lockfile, boolean block) {
super(lockfile);
// try and get a lock.
lock = null;
return;
}
- lock = (rafile=new RandomAccessFile(lockfile,"rw")).getChannel().tryLock();
+ rafile=new RandomAccessFile(lockfile,"rw");
+ if (block)
+ lock = rafile.getChannel().lock();
+ else
+ lock = rafile.getChannel().tryLock();
if (lock==null || !lock.isValid()) {
// failed to get lock. Close the file channel
log.debug("failed to get lock for "+lockfile);
public FileOutputStream getFileOutputStream(boolean clear) throws IOException {
if (!isLocked())
return null;
- if (clear)
+ if (clear) {
+ rafile.seek(0);
rafile.setLength(0);
- rafile.seek(rafile.length());
+ } else
+ rafile.seek(rafile.length());
return new LockedFileOutputStream(rafile.getFD());
}
* @return
*/
public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException {
- FileOutputStream fos = getFileOutputStream(clear);
+ OutputStream fos = getFileOutputStream(clear);
if (fos!=null)
return new BufferedOutputStream(fos);
return null;
super.finalize();
}
+ /* (non-Javadoc)
+ * @see org.vamsas.client.simpleclient.Lock#getLength()
+ */
+ public long length() {
+ if (isLocked()){
+ try {
+ return rafile.length();
+ } catch (Exception e) {
+ log.debug("getLength exception:",e);
+ }
+ }
+ return -1;
+ }
+
+ public RandomAccessFile getRaFile() throws IOException {
+ if (isLocked())
+ return rafile;
+ else
+ log.debug("Failed to getRaFile on "+target);
+ return null;
+ }
+
+ public FileChannel getRaChannel() throws IOException {
+ if (isLocked())
+ return rafile.getChannel();
+ else
+ log.debug("Failed to getRaChannel on "+target);
+ return null;
+ }
+
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.ReadableByteChannel;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
fileLock.release();// tidy up invalid lock
fileLock=null;
}
- if (extantlock!=null)
+ if (extantlock!=null && extantlock.isLocked())
fileLock=extantlock; // THIS IS BROKEN - lockFile then nulls the lock.
return lockFile();
}
-
- /**
- * Get a lock for the SessionFile
- *
- * @return true if lock was made
- */
- protected boolean lockFile() {
- if (fileLock != null)
- if (fileLock.isLocked())
- return true;
- else
- // lock failed for some reason.
- fileLock.release();
+ private boolean ensureSessionFile() {
if (sessionFile != null) {
if (!sessionFile.exists()) {
// create new file
return false;
}
}
- // TODO: see if we need to loop-wait for locks or they just block until
- // lock is made...
- long tries=500;
- do {
- tries--;
- if (fileLock!=null && !fileLock.isLocked()) {
- fileLock.release();
- try { Thread.sleep(5); } catch (Exception e) {};
- }
- fileLock = LockFactory.getLock(sessionFile); // TODO: wait around if we can't get the lock.
- } while (tries>0 && !fileLock.isLocked());
- if (!fileLock.isLocked())
- log.error("Failed to get lock for "+sessionFile);
- // fileLock = new Lock(sessionFile);
- return fileLock.isLocked();
- } else
- log.error("lockFile called for non-initialised SessionFile!");
-
- // no lock possible
+ return true;
+ }
+ log.error("ensureSessionFile called for non-initialised SessionFile!");
return false;
}
+ /**
+ * Get a lock for the SessionFile
+ *
+ * @return true if lock was made
+ */
+ protected boolean lockFile() {
+ if (fileLock != null) {
+ if (fileLock.isLocked()) {
+ if (!ensureSessionFile())
+ return false;
+ return true;
+ } else {
+ // lock failed for some reason.
+ fileLock.release();
+ log.info("Unexpected session file lock failure. Trying to get it again.");
+ fileLock=null;
+ }
+ }
+ if (!ensureSessionFile())
+ return false;
+ // TODO: see if we need to loop-wait for locks or they just block until
+ // lock is made...
+ long tries=5000;
+ do {
+ tries--;
+ if (fileLock==null || !fileLock.isLocked()) {
+ //try { Thread.sleep(1); } catch (Exception e) {};
+ fileLock = LockFactory.getLock(sessionFile,true); // TODO: wait around if we can't get the lock.
+ }
+ } while (tries>0 && !fileLock.isLocked());
+ if (!fileLock.isLocked())
+ log.error("Failed to get lock for "+sessionFile);
+ // fileLock = new Lock(sessionFile);
+ return fileLock.isLocked();
+ }
/**
* Explicitly release the SessionFile's lock.
if (lockFile(extantLock)) {
try {
tempfile = File.createTempFile(backupPrefix, backupSuffix, backupDir);
- FileOutputStream tos = new FileOutputStream(tempfile);
- tos.getChannel().transferFrom(fileLock.rafile.getChannel(), 0,
- fileLock.rafile.length());
- tos.close();
+ if (fileLock.length()>0) {
+ FileOutputStream tos = new FileOutputStream(tempfile);
+ ReadableByteChannel channel;
+ tos.getChannel().transferFrom(channel=fileLock.getRaChannel(), 0,
+ fileLock.length());
+ tos.close();
+ if (!channel.isOpen())
+ throw new Error(tos.getChannel().getClass()+".transferFrom closes source channel!");
+ if (!lockFile(extantLock))
+ throw new Error("Lost lock for "+sessionFile.getName()+" after backup.");
+
+ }
} catch (FileNotFoundException e1) {
log.warn("Can't create temp file for "+sessionFile.getName(),e1);
tempfile=null;
throw new IOException("Null SessionFile in newData.");
if (!lockFile(extantLock))
- log.error("Failed to get write lock for "+sessionFile);
+ throw new IOException("Failed to get write lock for "+sessionFile);
if (!newData.lockFile())
- log.warn("Failed to get lock for updateFrom "+newData.sessionFile);
- fileLock.rafile.getChannel().transferFrom(newData.fileLock.rafile.getChannel(), 0,
- newData.fileLock.rafile.length());
+ throw new IOException("Failed to get lock for updateFrom "+newData.sessionFile);
+ RandomAccessFile nrafile = newData.fileLock.getRaFile();
+ nrafile.seek(0);
+ RandomAccessFile trafile = fileLock.getRaFile();
+ /*long tries=5000;
+ while (trafile==null && --tries>0) {
+ log.debug("Lost lock on "+sessionFile+"! Re-trying for a transfer.");
+ lockFile();
+ trafile = fileLock.getRaFile();
+ }*/
+ trafile.seek(0);
+ trafile.getChannel().transferFrom(nrafile.getChannel(), 0,
+ nrafile.length());
}
/**
* remove all trace of the sessionFile file
log.debug("Successfully made temp appData file for "+apdname);
} else {
// truncate to remove existing data.
- apdfile.fileLock.rafile.setLength(0);
+ apdfile.fileLock.getRaFile().setLength(0);
log.debug("Successfully truncated existing temp appData for "+apdname);
}
} catch (Exception e) {
*/
File originalBackup = null;
- boolean donotdeletebackup=false;
+ boolean donotdeletebackup=true;
private final int _TRANSFER_BUFFER=4096*4;
protected SimpleDocument vorba = null;
/**
*/
public VamsasArchive(File archive, boolean overwrite, boolean vamsasdocument, SessionFile extantLock) throws IOException {
super();
- if (archive==null || (archive!=null && !(archive.getParentFile().canWrite() && (!archive.exists() || archive.canWrite())))) {
+ if (archive==null || (archive!=null && !(archive.getAbsoluteFile().getParentFile().canWrite() && (!archive.exists() || archive.canWrite())))) {
log.fatal("Expect Badness! -- Invalid parameters for VamsasArchive constructor:"+((archive!=null)
? "File cannot be overwritten." : "Null Object not valid constructor parameter"));
return;
else
rchive = new SessionFile(archive);
rchive.lockFile();
- if (rchive.fileLock==null || rchive.fileLock.rafile==null || !rchive.fileLock.isLocked())
+ if (rchive.fileLock==null || !rchive.fileLock.isLocked())
throw new IOException("Lock failed for new archive"+archive);
- rchive.fileLock.rafile.setLength(0); // empty the archive.
+ rchive.fileLock.getRaFile().setLength(0); // empty the archive.
virginArchive = true;
}
this.openArchive(); // open archive
newarchive.closeEntry();
if (!isDocumentWritten())
log.warn("Premature closure of archive '"+archive.getAbsolutePath()+"': No document has been written.");
- newarchive.close(); // use newarchive.finish(); for a stream IO
+ newarchive.finish();// close(); // use newarchive.finish(); for a stream IO
+ newarchive.flush();
+ //
updateOriginal();
closeAndReset();
} else {
if (!rchive.lockFile())
throw new IOException("Failed to get lock on file "+archive);
// LATER: locked IO stream based access.
- //Manifest newmanifest = new Manifest();
- //newarchive = new JarOutputStream(rchive.fileLock.getBufferedOutputStream(true), newmanifest);
- newarchive = new JarOutputStream(new BufferedOutputStream(new java.io.FileOutputStream(archive)));
+ Manifest newmanifest = new Manifest();
+ newarchive = new JarOutputStream(rchive.fileLock.getBufferedOutputStream(true), newmanifest);
+ //newarchive = new JarOutputStream(new BufferedOutputStream(new java.io.FileOutputStream(archive)));
entries = new Hashtable();
}
public void putVamsasDocument(VamsasDocument doc) throws IOException,
odoclock.updateFrom(null, rchive);
}
catch (IOException e) {
- // LATER: decide if leaving nastily named backup files around is necessary.
- log.error("Problem updating archive from temporary file! - backup left in '"
+ // LATER: decide if leaving nastily named backup files around is necessary.
+ File backupFile=backupFile();
+ if (backupFile!=null)
+ log.error("Problem updating archive from temporary file! - backup left in '"
+backupFile().getAbsolutePath()+"'",e);
+ else
+ log.error("Problems updating, and failed to even make a backup file. Ooops!", e);
}
// Tidy up if necessary.
removeBackup();
} else {
+
}
}
}
ZipInputStream jstream=null;
Hashtable strmentries = null;
private void streamInit() {
- throw new Error("VamsasArchiveReader(Stream) Not implemented!");
- /* if (!stream) {
+ //throw new Error("VamsasArchiveReader(Stream) Not implemented!");
+ if (!stream) {
log.debug("Skipping init for Jar Stream input.");
return;
}
catch (Exception e) {
log.warn("Exceptions during init!",e);
jstream=null;
- }*/
+ }
}
public VamsasArchiveReader(File vamsasfile) {
*/
public VamsasArchiveReader(Lock vamsaslock) {
// LATER: implement or remove
- throw new Error("VamsasArchiveReading from locked IO stream not yet implemented.");
- //rfile = vamsaslock.rafile;
- //stream = true;
- //streamInit();
- //if (jstream==null)
- // throw new Error("Failed to open archive from Locked random access stream.");
+ if (vamsaslock==null || !vamsaslock.isLocked())
+ throw new Error("IMPLEMENTATION ERROR: Cannot create a VamsasArchiveReader without a valid lock.");
+ // throw new Error("VamsasArchiveReading from locked IO stream not yet implemented.");
+ try {
+ rfile = vamsaslock.getRaFile();
+ } catch (Exception e) {
+ log.warn("Unexpected IO Exception when accessing locked vamsas archive stream "+vamsaslock.target,e);
+ }
+ stream = true;
+ streamInit();
+ if (jstream==null)
+ throw new Error("Failed to open archive from Locked random access stream.");
}
/**
long epos = entrypos.longValue();
do {
entry = jstream.getNextEntry();
- } while (entry!=null && epos-->0);
+ } while (entry!=null && --epos>=0);
// rfile.seek(entrypos.longValue());
// make a Jar entry from a zip entry.
return new JarEntry(entry);
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
+import java.io.RandomAccessFile;
import java.io.Writer;
import org.apache.commons.logging.Log;
SessionFile sfw = new SessionFile(new File(sessionDir, CLOSEANDSAVE_FILE));
while (!sfw.lockFile())
log.debug("Trying to get lock for "+CLOSEANDSAVE_FILE);
- sfw.fileLock.rafile.setLength(0); // wipe out any old info.
+ RandomAccessFile sfwfile=sfw.fileLock.getRaFile();
+ sfwfile.setLength(0); // wipe out any old info.
// TODO: rationalise what gets written to this file (ie do we want other clients to read the id of the requestor?)
- sfw.fileLock.rafile.writeUTF(client.getClientUrn()+":"+user.getFullName()+"@"+user.getOrganization());
+ sfwfile.writeUTF(client.getClientUrn()+":"+user.getFullName()+"@"+user.getOrganization());
sfw.unlockFile();
if (store_doc_file!=null)
store_doc_file.setState();
if (vsess==null)
throw new Error("ArchiveClient instance is invalid!.");
}
-
+ public static int WATCH_SLEEP=300;
/**
* watch the document file for updates.
* @param time - length of time to watch for.
*/
public ClientDoc watch(long time) {
valid();
+ vsess.unLock(); // doh.
FileWatcher watcher = new FileWatcher(vsess.getVamsasFile());
long endtime=System.currentTimeMillis()+time;
try {
org.vamsas.client.simpleclient.Lock doclock;
- watcher.setState();
+ //watcher.setState();
do {
- Thread.sleep(50); // tuning.
doclock=watcher.getChangedState();
- } while (doclock==null && (time==0 || endtime>System.currentTimeMillis()));
+ if (doclock==null)
+ Thread.sleep(WATCH_SLEEP);
+ } while (doclock==null && (time==0 || endtime>System.currentTimeMillis())); // tuning.
if (doclock==null)
return null;
else {
public ClientDoc getUpdateable() {
valid();
try {
- vsess.getLock();
+ // patiently wait for a lock on the document.
+ long tries=5000;
+ org.vamsas.client.simpleclient.Lock lock;
+ while (((lock=vsess.getLock())==null || !lock.isLocked()) && --tries>0) {
+// Thread.sleep(1);
+ log.debug("Trying to get a document lock for the "+tries+"'th time.");
+ }
VamsasArchive varc = new VamsasArchive(vsess, true, false); // read archive, write as vamsasDocument, don't erase original contents.
varc.setVorba(this);
VamsasDocument d = varc.getVamsasDocument(getProvenanceUser(), "Created new document.", VersionEntries.latestVersion()); // VAMSAS: provenance user and client combined
// do any appDatas first.
if (cdoc.iohandler.transferRemainingAppDatas())
log.debug("Remaining appdatas were transfered.");
+ cdoc.updateDocumentRoots();
cdoc.iohandler.putVamsasDocument(cdoc.doc);
cdoc.iohandler.closeArchive();
cdoc.iohandler=null;
cdoc.addVamsasRoot(Core.getDemoVamsas());
System.out.println("Doing update.");
client.doUpdate(cdoc);
+ cdoc.closeDoc();
cdoc = null;
int u=5;
while (--u>0) {
System.out.println("Watch for more... ("+u+" left)");
- cdoc = client.watch(0);
- if (cdoc!=null) {
+ ClientDoc ucdoc = client.watch(50000);
+ if (ucdoc!=null) {
System.out.println("****\nUpdate detected at "+new Date());
- ArchiveReports.reportDocument(cdoc.doc, cdoc.getReader(), true, System.out);
+ ArchiveReports.reportDocument(ucdoc.doc, ucdoc.getReader(), true, System.out);
+ ucdoc.closeDoc();
+ ucdoc=null;
} else {
System.out.println("!!!! Null document update detected at "+new Date());
}
public VamsasArchiveReader getReader() {
return reader;
}
+ private void _finalize() {
+ log.debug("finalizing clientDoc");
+ if (doc!=null) {
+ doc = null;
+ }
+ if (_VamsasRoots!=null) {
+ for (int i=0; i<_VamsasRoots.length; i++)
+ _VamsasRoots[i]=null;
+ _VamsasRoots=null;
+
+ }
+
+ if (reader!=null) {
+ log.debug("Closing and removing reader reference");
+ reader.close();
+ reader=null;
+ }
+ if (iohandler!=null) {
+ log.debug("Removing ioHandler reference.");
+ iohandler.cancelArchive();
+ iohandler=null;
+ }
+ }
protected void finalize() throws Throwable {
+ _finalize();
super.finalize();
- //if (reader!=null)
- // reader.close();
- //reader=null;
-// if (iohandler!=null) {
-// iohandler.cancelArchive(); // otherwise the original may be overwritten.
-// }
}
private java.util.Hashtable objrefs=null;
log.debug("Returning null Vobject reference for id "+ids[i].getId());
return vo;
}
+ protected void updateDocumentRoots() {
+ if (doc==null) {
+ log.error("updateDocumentRoots called on null document. Probably an implementation error.");
+ return;
+ }
+ if (isModified) {
+ if (_VamsasRoots!=null) {
+ doc.setVAMSAS(_VamsasRoots);
+ _VamsasRoots=null;
+ }
+ }
+ }
+ /**
+ * tell vamsas client to close the document and reset the object. Once closed, nothing can be done with the object.
+ *
+ */
+ public void closeDoc() {
+ if (doc!=null) {
+ log.debug("Closing open document.");
+ _finalize();
+ } else {
+ log.warn("Ignoring closeDoc on invalid document.");
+ }
+ }
}
\ No newline at end of file
break;
case 3:
// clear
- cfhand = null;
- cf.delete();
+ //cfhand.get = null;
+ //cf.delete();
try {
- cf.createNewFile();
- cfhand = new ClientsFile(cf);
+
+ cfhand.clearList();
+
} catch (Exception e) {
System.err.println("Failed on new empty clientfile creation!");
e.printStackTrace(System.err);
}
while (newf.exists());
} */
+ if (newf.exists()) {
+ log.info("Removing existing "+newf);
+ newf.delete();
+ }
+
log.info("Now writing new Archive into "+newf.getAbsolutePath());
org.vamsas.client.simpleclient.VamsasArchive va=null;
{ // hold lock over deletion and write of new archive.
//Lock wlock = sfile.getLock();
//newf.delete(); // clear out old file.
- va = new org.vamsas.client.simpleclient.VamsasArchive(newf, true, true); // , sfile);
+ sfile.getLock();
+ va = new org.vamsas.client.simpleclient.VamsasArchive(newf, true, true, sfile);
// open another and...
ApplicationData appdata = makeDemoAppdata(va,
"org.vamsas.test.simpleclient.VamsasArchive", "arnold Bugger esq", "disOrganised");
{
Lock lock=sfile.getLock();
if (lock==null)
- while ((lock=sfile.getLock())==null)
+ while ((lock=sfile.getLock())==null) {
log.info("Waiting for lock.");
- VamsasArchiveReader vreader = new VamsasArchiveReader(newf);
+ Thread.sleep(100);
+ }
+ VamsasArchiveReader vreader = new VamsasArchiveReader(sfile.getVamsasFile());// lock); // cannot do new JarFile on a locked file. // newf);
SimpleDocument sdoc = new SimpleDocument("testing new vamsas write");
ArchiveReports.reportDocument(sdoc.getVamsasDocument(vreader), vreader, true, System.out);
sfile.unLock();