001 package railo.commons.io.res.util; 002 003 import java.util.HashMap; 004 import java.util.Map; 005 006 import railo.commons.io.res.Resource; 007 import railo.commons.io.res.ResourceLock; 008 import railo.commons.lang.SerializableObject; 009 import railo.commons.lang.SystemOut; 010 import railo.runtime.config.Config; 011 import railo.runtime.engine.ThreadLocalPageContext; 012 013 public final class ResourceLockImpl implements ResourceLock { 014 015 private static final long serialVersionUID = 6888529579290798651L; 016 017 private long lockTimeout; 018 private boolean caseSensitive; 019 020 public ResourceLockImpl(long timeout,boolean caseSensitive) { 021 this.lockTimeout=timeout; 022 this.caseSensitive=caseSensitive; 023 } 024 025 private Object token=new SerializableObject(); 026 private Map<String,Thread> resources=new HashMap<String,Thread>(); 027 028 @Override 029 public void lock(Resource res) { 030 String path=getPath(res); 031 032 synchronized(token) { 033 _read(path); 034 resources.put(path,Thread.currentThread()); 035 } 036 } 037 038 private String getPath(Resource res) { 039 return caseSensitive?res.getPath():res.getPath().toLowerCase(); 040 } 041 042 @Override 043 public void unlock(Resource res) { 044 String path=getPath(res); 045 //if(path.endsWith(".dmg"))print.err("unlock:"+path); 046 synchronized(token) { 047 resources.remove(path); 048 token.notifyAll(); 049 } 050 } 051 052 @Override 053 public void read(Resource res) { 054 String path=getPath(res); 055 synchronized(token) { 056 //print.ln("......."); 057 _read(path); 058 } 059 } 060 061 private void _read(String path) { 062 long start=-1,now; 063 Thread t; 064 do { 065 if((t=resources.get(path))==null) { 066 //print.ln("read ok"); 067 return; 068 } 069 if(t==Thread.currentThread()) { 070 //aprint.err(path); 071 Config config = ThreadLocalPageContext.getConfig(); 072 if(config!=null) 073 SystemOut.printDate(config.getErrWriter(),"conflict in same thread: on "+path); 074 //throw new RuntimeException("conflict in same thread: on "+res); 075 return; 076 } 077 // bugfix when lock von totem thread, wird es ignoriert 078 if(!t.isAlive()) { 079 resources.remove(path); 080 return; 081 } 082 if(start==-1)start=System.currentTimeMillis(); 083 try { 084 token.wait(lockTimeout); 085 now=System.currentTimeMillis(); 086 if((start+lockTimeout)<=now) { 087 Config config = ThreadLocalPageContext.getConfig(); 088 if(config!=null) 089 SystemOut.printDate(config.getErrWriter(),"timeout after "+(now-start)+" ms ("+(lockTimeout)+" ms) occured while accessing file ["+path+"]"); 090 else 091 SystemOut.printDate("timeout ("+(lockTimeout)+" ms) occured while accessing file ["+path+"]"); 092 return; 093 } 094 } 095 catch (InterruptedException e) { 096 } 097 } 098 while(true); 099 } 100 101 @Override 102 public long getLockTimeout() { 103 return lockTimeout; 104 } 105 106 /** 107 * @param lockTimeout the lockTimeout to set 108 */ 109 public void setLockTimeout(long lockTimeout) { 110 this.lockTimeout = lockTimeout; 111 } 112 113 /** 114 * @param caseSensitive the caseSensitive to set 115 */ 116 public void setCaseSensitive(boolean caseSensitive) { 117 this.caseSensitive = caseSensitive; 118 } 119 }