package railo.commons.io.res.util;
import java.util.HashMap;
import java.util.Map;
import railo.commons.io.res.Resource;
import railo.commons.io.res.ResourceLock;
import railo.commons.lang.SerializableObject;
import railo.commons.lang.SystemOut;
import railo.runtime.config.Config;
import railo.runtime.engine.ThreadLocalPageContext;
public final class ResourceLockImpl implements ResourceLock {
private static final long serialVersionUID = 6888529579290798651L;
private long lockTimeout;
private boolean caseSensitive;
public ResourceLockImpl(long timeout,boolean caseSensitive) {
this.lockTimeout=timeout;
this.caseSensitive=caseSensitive;
}
private Object token=new SerializableObject();
private Map<String,Thread> resources=new HashMap<String,Thread>();
@Override
public void lock(Resource res) {
String path=getPath(res);
synchronized(token) {
_read(path);
resources.put(path,Thread.currentThread());
}
}
private String getPath(Resource res) {
return caseSensitive?res.getPath():res.getPath().toLowerCase();
}
@Override
public void unlock(Resource res) {
String path=getPath(res);
//if(path.endsWith(".dmg"))print.err("unlock:"+path);
synchronized(token) {
resources.remove(path);
token.notifyAll();
}
}
@Override
public void read(Resource res) {
String path=getPath(res);
synchronized(token) {
//print.ln(".......");
_read(path);
}
}
private void _read(String path) {
long start=-1,now;
Thread t;
do {
if((t=resources.get(path))==null) {
//print.ln("read ok");
return;
}
if(t==Thread.currentThread()) {
//aprint.err(path);
Config config = ThreadLocalPageContext.getConfig();
if(config!=null)
SystemOut.printDate(config.getErrWriter(),"conflict in same thread: on "+path);
//throw new RuntimeException("conflict in same thread: on "+res);
return;
}
// bugfix when lock von totem thread, wird es ignoriert
if(!t.isAlive()) {
resources.remove(path);
return;
}
if(start==-1)start=System.currentTimeMillis();
try {
token.wait(lockTimeout);
now=System.currentTimeMillis();
if((start+lockTimeout)<=now) {
Config config = ThreadLocalPageContext.getConfig();
if(config!=null)
SystemOut.printDate(config.getErrWriter(),"timeout after "+(now-start)+" ms ("+(lockTimeout)+" ms) occured while accessing file ["+path+"]");
else
SystemOut.printDate("timeout ("+(lockTimeout)+" ms) occured while accessing file ["+path+"]");
return;
}
}
catch (InterruptedException e) {
}
}
while(true);
}
@Override
public long getLockTimeout() {
return lockTimeout;
}
/**
* @param lockTimeout the lockTimeout to set
*/
public void setLockTimeout(long lockTimeout) {
this.lockTimeout = lockTimeout;
}
/**
* @param caseSensitive the caseSensitive to set
*/
public void setCaseSensitive(boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}
}