some changes that may help to prevent deadlocks that cause an OutOfMemoryError

as described in
http://www.yacy-forum.de/viewtopic.php?p=24359

git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@2353 6c8d7289-2bf4-0310-a012-ef5d649a1542
pull/1/head
orbiter 19 years ago
parent 988341cf81
commit d468d665c9

@ -3,7 +3,7 @@ javacSource=1.4
javacTarget=1.4 javacTarget=1.4
# Release Configuration # Release Configuration
releaseVersion=0.457 releaseVersion=0.458
releaseFile=yacy_dev_v${releaseVersion}_${DSTAMP}_${releaseNr}.tar.gz releaseFile=yacy_dev_v${releaseVersion}_${DSTAMP}_${releaseNr}.tar.gz
#releaseFile=yacy_v${releaseVersion}_${DSTAMP}_${releaseNr}.tar.gz #releaseFile=yacy_v${releaseVersion}_${DSTAMP}_${releaseNr}.tar.gz
releaseDir=yacy_dev_v${releaseVersion}_${DSTAMP}_${releaseNr} releaseDir=yacy_dev_v${releaseVersion}_${DSTAMP}_${releaseNr}

@ -118,6 +118,8 @@ import de.anomic.ymage.ymagePainter;
public final class httpdFileHandler extends httpdAbstractHandler implements httpdHandler { public final class httpdFileHandler extends httpdAbstractHandler implements httpdHandler {
private static final boolean safeServletsMode = false; // if true then all servlets are called synchronized
// class variables // class variables
private static final Properties mimeTable = new Properties(); private static final Properties mimeTable = new Properties();
private static final serverClassLoader provider; private static final serverClassLoader provider;
@ -476,7 +478,7 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http
requestHeader.put("CLIENTIP", conProp.getProperty("CLIENTIP")); requestHeader.put("CLIENTIP", conProp.getProperty("CLIENTIP"));
requestHeader.put("PATH", path); requestHeader.put("PATH", path);
// in case that there are no args given, args = null or empty hashmap // in case that there are no args given, args = null or empty hashmap
img = rewriteMethod(targetClass).invoke(null, new Object[] {requestHeader, args, switchboard}); img = invokeServlet(targetClass, requestHeader, args);
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
this.theLogger.logSevere("INTERNAL ERROR: " + e.toString() + ":" + this.theLogger.logSevere("INTERNAL ERROR: " + e.toString() + ":" +
e.getMessage() + e.getMessage() +
@ -560,8 +562,7 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http
httpd.sendRespondHeader(this.connectionProperties, out, httpVersion, 200, null); httpd.sendRespondHeader(this.connectionProperties, out, httpVersion, 200, null);
// in case that there are no args given, args = null or empty hashmap // in case that there are no args given, args = null or empty hashmap
/* serverObjects tp = (serverObjects) */ rewriteMethod(targetClass).invoke(null, new Object[] {requestHeader, args, switchboard}); /* serverObjects tp = (serverObjects) */ invokeServlet(targetClass, requestHeader, args);
this.forceConnectionClose(); this.forceConnectionClose();
return; return;
} else if ((targetFile.exists()) && (targetFile.canRead())) { } else if ((targetFile.exists()) && (targetFile.canRead())) {
@ -597,7 +598,7 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http
requestHeader.put("CLIENTIP", conProp.getProperty("CLIENTIP")); requestHeader.put("CLIENTIP", conProp.getProperty("CLIENTIP"));
requestHeader.put("PATH", path); requestHeader.put("PATH", path);
// in case that there are no args given, args = null or empty hashmap // in case that there are no args given, args = null or empty hashmap
tp = (serverObjects) rewriteMethod(targetClass).invoke(null, new Object[] {requestHeader, args, switchboard}); tp = (serverObjects) invokeServlet(targetClass, requestHeader, args);
// if no args given , then tp will be an empty Hashtable object (not null) // if no args given , then tp will be an empty Hashtable object (not null)
if (tp == null) tp = new serverObjects(); if (tp == null) tp = new serverObjects();
// check if the servlets requests authentification // check if the servlets requests authentification
@ -708,8 +709,8 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http
//warning: o,tp and fis are reused //warning: o,tp and fis are reused
httpTemplate.writeTemplate(fis, o, tp, "-UNRESOLVED_PATTERN-".getBytes()); httpTemplate.writeTemplate(fis, o, tp, "-UNRESOLVED_PATTERN-".getBytes());
if(pageClass != null && pageClass.exists()) if (pageClass != null && pageClass.exists())
tp = (serverObjects) rewriteMethod(pageClass).invoke(null, new Object[] {requestHeader, args, switchboard}); tp = (serverObjects) invokeServlet(pageClass, requestHeader, args);
else else
tp = new serverObjects(); tp = new serverObjects();
tp.put("page", o.toString()); tp.put("page", o.toString());
@ -994,6 +995,16 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http
return m; return m;
} }
private Object invokeServlet(File targetClass, httpHeader request, serverObjects args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
Object result;
if (safeServletsMode) synchronized (switchboard) {
result = rewriteMethod(targetClass).invoke(null, new Object[] {request, args, switchboard});
} else {
result = rewriteMethod(targetClass).invoke(null, new Object[] {request, args, switchboard});
}
return result;
}
public void doConnect(Properties conProp, httpHeader requestHeader, InputStream clientIn, OutputStream clientOut) { public void doConnect(Properties conProp, httpHeader requestHeader, InputStream clientIn, OutputStream clientOut) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

@ -90,7 +90,7 @@ public class indexURLEntry implements Cloneable, indexEntry {
) { ) {
// more needed attributes: // more needed attributes:
// - boolean: appearance attributes: title, appears in header, anchor-descr, image-tag etc // - boolean: appearance attributes: title, appears in header, anchor-descr, image-tag, hervorhebungen, meta-tags, word in link etc
// - boolean: URL attributes // - boolean: URL attributes
if ((language == null) || (language.length() != indexURL.urlLanguageLength)) language = "uk"; if ((language == null) || (language.length() != indexURL.urlLanguageLength)) language = "uk";

@ -69,8 +69,9 @@ public abstract class kelondroAbstractIOChunks {
if (len < 0) throw new IndexOutOfBoundsException("length is negative:" + len); if (len < 0) throw new IndexOutOfBoundsException("length is negative:" + len);
if (b.length < off + len) throw new IndexOutOfBoundsException("bounds do not fit: b.length=" + b.length + ", off=" + off + ", len=" + len); if (b.length < off + len) throw new IndexOutOfBoundsException("bounds do not fit: b.length=" + b.length + ", off=" + off + ", len=" + len);
while (len > 0) { while (len > 0) {
int r = read(pos, b, off, len); int r = read(pos, b, off, len); // blocks until at least one byte is available
if (r < 0) throw new IOException("EOF"); // read exceeded EOF if (r < 0) throw new IOException("EOF"); // read exceeded EOF
if (r == 0) throw new IOException("readFully cannot read remaining " + len + " bytes"); // security exception to prevent endless loops
pos += r; pos += r;
off += r; off += r;
len -= r; len -= r;

@ -64,6 +64,8 @@ abstract class kelondroAbstractRA implements kelondroRA {
} }
// pseudo-native methods: // pseudo-native methods:
abstract public long available() throws IOException;
abstract public int read() throws IOException; abstract public int read() throws IOException;
abstract public void write(int b) throws IOException; abstract public void write(int b) throws IOException;

@ -45,6 +45,8 @@ import java.io.IOException;
public class kelondroBufferedRA extends kelondroAbstractRA implements kelondroRA { public class kelondroBufferedRA extends kelondroAbstractRA implements kelondroRA {
// FIXME: a lot of synchronization of ra is needed here
protected kelondroRA ra; protected kelondroRA ra;
protected byte[] buffer; protected byte[] buffer;
protected int bufferPage; protected int bufferPage;
@ -75,6 +77,13 @@ public class kelondroBufferedRA extends kelondroAbstractRA implements kelondroRA
this.bufferWritten = true; this.bufferWritten = true;
} }
public long available() throws IOException {
synchronized (ra) {
ra.seek(seekpos);
return ra.available();
}
}
private void readBuffer(int newPageNr) throws IOException { private void readBuffer(int newPageNr) throws IOException {
if (newPageNr == bufferPage) return; if (newPageNr == bufferPage) return;
bufferPage = newPageNr; bufferPage = newPageNr;

@ -65,6 +65,13 @@ public class kelondroCachedRA extends kelondroAbstractRA implements kelondroRA {
this.seekpos = 0; this.seekpos = 0;
} }
public long available() throws IOException {
synchronized (ra) {
ra.seek(seekpos);
return ra.available();
}
}
private int cacheElementNumber(long address) { private int cacheElementNumber(long address) {
return (int) address / cacheElementSize; return (int) address / cacheElementSize;
} }

@ -334,6 +334,10 @@ public class kelondroDyn extends kelondroTree {
this.filekey = filekey; this.filekey = filekey;
} }
public long available() throws IOException {
return Long.MAX_VALUE;
}
public int read() throws IOException { public int read() throws IOException {
return getDyn(filekey, seekpos++); return getDyn(filekey, seekpos++);
} }

@ -60,6 +60,10 @@ public final class kelondroFileRA extends kelondroAbstractRA implements kelondro
RAFile = new RandomAccessFile(file, "rw"); RAFile = new RandomAccessFile(file, "rw");
} }
public long available() throws IOException {
return RAFile.length() - RAFile.getFilePointer();
}
// pseudo-native method read // pseudo-native method read
public int read() throws IOException { public int read() throws IOException {
return RAFile.read(); return RAFile.read();

@ -113,6 +113,10 @@ public class kelondroNIOFileRA extends kelondroAbstractRA implements kelondroRA
return true; return true;
} }
public long available() throws IOException {
return RAFile.length() - RAFile.getFilePointer();
}
// pseudo-native method read // pseudo-native method read
public int read() throws IOException { public int read() throws IOException {
int r; int r;

@ -59,6 +59,8 @@ public interface kelondroRA {
public String name(); public String name();
// pseudo-native methods: // pseudo-native methods:
public long available() throws IOException;
public int read() throws IOException; public int read() throws IOException;
public void write(int b) throws IOException; public void write(int b) throws IOException;

@ -53,9 +53,17 @@ public final class kelondroRAIOChunks extends kelondroAbstractIOChunks implement
} }
public int read(long pos, byte[] b, int off, int len) throws IOException { public int read(long pos, byte[] b, int off, int len) throws IOException {
if (len == 0) return 0;
synchronized (this.ra) { synchronized (this.ra) {
this.ra.seek(pos); this.ra.seek(pos);
return ra.read(b, off, len); long available = ra.available();
if (available >= len) {
return ra.read(b, off, len);
} else if (available == 0) {
return -1;
} else {
return ra.read(b, off, (int) available);
}
} }
} }

@ -153,12 +153,14 @@ public abstract class serverAbstractSwitch implements serverSwitch {
public void setConfig(String key, String value) { public void setConfig(String key, String value) {
// perform action before setting new value // perform action before setting new value
Iterator bevore = switchActions.entrySet().iterator();
Iterator after = switchActions.entrySet().iterator();
synchronized (configProps) { synchronized (configProps) {
Map.Entry entry; Map.Entry entry;
serverSwitchAction action; serverSwitchAction action;
Iterator i = switchActions.entrySet().iterator();
while (i.hasNext()) { while (bevore.hasNext()) {
entry = (Map.Entry) i.next(); entry = (Map.Entry) bevore.next();
action = (serverSwitchAction) entry.getValue(); action = (serverSwitchAction) entry.getValue();
try { try {
action.doBevoreSetConfig(key, value); action.doBevoreSetConfig(key, value);
@ -172,9 +174,8 @@ public abstract class serverAbstractSwitch implements serverSwitch {
saveConfig(); saveConfig();
// perform actions afterwards // perform actions afterwards
i = switchActions.entrySet().iterator(); while (after.hasNext()) {
while (i.hasNext()) { entry = (Map.Entry) after.next();
entry = (Map.Entry) i.next();
action = (serverSwitchAction) entry.getValue(); action = (serverSwitchAction) entry.getValue();
try { try {
action.doAfterSetConfig(key, value, (oldValue == null) ? null : (String) oldValue); action.doAfterSetConfig(key, value, (oldValue == null) ? null : (String) oldValue);
@ -186,6 +187,7 @@ public abstract class serverAbstractSwitch implements serverSwitch {
} }
public String getConfig(String key, String dflt) { public String getConfig(String key, String dflt) {
Iterator i = switchActions.entrySet().iterator();
synchronized (configProps) { synchronized (configProps) {
// get the value // get the value
Object s = configProps.get(key); Object s = configProps.get(key);
@ -193,7 +195,6 @@ public abstract class serverAbstractSwitch implements serverSwitch {
// do action // do action
Map.Entry entry; Map.Entry entry;
serverSwitchAction action; serverSwitchAction action;
Iterator i = switchActions.entrySet().iterator();
while (i.hasNext()) { while (i.hasNext()) {
entry = (Map.Entry) i.next(); entry = (Map.Entry) i.next();
action = (serverSwitchAction) entry.getValue(); action = (serverSwitchAction) entry.getValue();

Loading…
Cancel
Save