From: zapata Date: Sun, 30 Oct 2005 00:46:57 +0000 (+0000) Subject: serious memory leak in the producer subsystem fixed X-Git-Tag: LATEST_MERGED_1_1~90 X-Git-Url: http://erislabs.net/gitweb/?p=mir.git;a=commitdiff_plain;h=b7ea95152eaddbf069564a5f2f117774165d36e6 serious memory leak in the producer subsystem fixed --- diff --git a/source/mir/entity/AbstractEntity.java b/source/mir/entity/AbstractEntity.java index a56572ed..108f4247 100755 --- a/source/mir/entity/AbstractEntity.java +++ b/source/mir/entity/AbstractEntity.java @@ -44,7 +44,7 @@ import mir.storage.Database; * Base class the entities are derived from. Provides base functionality of * an entity. * - * @version $Id: AbstractEntity.java,v 1.8.2.7 2005/03/26 11:26:23 zapata Exp $ + * @version $Id: AbstractEntity.java,v 1.8.2.8 2005/10/30 00:46:57 zapata Exp $ */ public class AbstractEntity implements Entity { @@ -52,11 +52,8 @@ public class AbstractEntity implements Entity { protected Map values; protected Database database; - protected LoggerWrapper logger; public AbstractEntity() { - logger = new LoggerWrapper("Entity"); - values = new HashMap(); } @@ -90,7 +87,7 @@ public class AbstractEntity implements Entity { /** {@inheritDoc} */ public String insert() throws DatabaseExc { - logger.debug("Entity: trying to insert ..."); + getLogger().debug("Entity: trying to insert ..."); if (database != null) { return database.insert(this); @@ -130,7 +127,7 @@ public class AbstractEntity implements Entity { if (hasField(theProp)) values.put(theProp, theValue); else { - logger.warn("Entity.setFieldValue: Property not found: " + theProp + " (" + theValue + ")"); + getLogger().warn("Entity.setFieldValue: Property not found: " + theProp + " (" + theValue + ")"); } } @@ -149,5 +146,9 @@ public class AbstractEntity implements Entity { public boolean hasField(String fieldName) throws DatabaseFailure { return getFieldNames().contains(fieldName); } + + protected LoggerWrapper getLogger() { + return new LoggerWrapper("Entity"); + } } diff --git a/source/mir/storage/store/StoreIdentifier.java b/source/mir/storage/store/StoreIdentifier.java index de65c7ac..bb986985 100755 --- a/source/mir/storage/store/StoreIdentifier.java +++ b/source/mir/storage/store/StoreIdentifier.java @@ -58,7 +58,7 @@ public class StoreIdentifier { private long timesUsed; private boolean invalidating = false; - protected LoggerWrapper logger = new LoggerWrapper("Database.ObjectStore"); + protected static LoggerWrapper logger = new LoggerWrapper("Database.ObjectStore"); public StoreIdentifier(StorableObject reference, int storeType, String uniqueIdentifier) { diff --git a/source/mir/util/HTMLRoutines.java b/source/mir/util/HTMLRoutines.java index c4a2e84a..dd4882fb 100755 --- a/source/mir/util/HTMLRoutines.java +++ b/source/mir/util/HTMLRoutines.java @@ -30,6 +30,8 @@ package mir.util; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; @@ -37,17 +39,35 @@ import java.util.Map; public class HTMLRoutines { private HTMLRoutines() { } - + + private static Method encodeURLMethod; + static { + try { + encodeURLMethod = URLEncoder.class.getMethod("encode", new Class[] {String.class}); + } + catch (NoSuchMethodException e) { + throw new RuntimeException(e.getMessage()); + } + } + /** * Encodes a URL: escapes reserved URL characters like &, = into % escape * constructions. */ public static String encodeURL(String aString) { - return URLEncoder.encode(aString); + try { + return (String) encodeURLMethod.invoke(URLEncoder.class, new Object[] {aString}); + } + catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + catch (InvocationTargetException e) { + throw new RuntimeException(e.getMessage()); + } } public static String encodeURL(String aString, String anEncoding) { - return URLEncoder.encode(aString); + return encodeURL(aString); } private static final char[] CHARACTERS_TO_ESCAPE = { '&', '<', '>', '"' }; diff --git a/source/mircoders/entity/EntityComment.java b/source/mircoders/entity/EntityComment.java index 022ccfe4..2e9e8db9 100755 --- a/source/mircoders/entity/EntityComment.java +++ b/source/mircoders/entity/EntityComment.java @@ -41,7 +41,7 @@ import mircoders.storage.DatabaseContent; * This class maps one line of the comment-table to a java-object. * * @author $Author: zapata $ - * @version $Revision: 1.16.2.6 $ $Date: 2005/03/26 11:26:26 $ + * @version $Revision: 1.16.2.7 $ $Date: 2005/10/30 00:46:58 $ */ @@ -75,8 +75,7 @@ public class EntityComment extends AbstractEntity { /** * Deattaches media from a comment */ - public void dettach(String aCommentId,String aMediaId) throws DatabaseFailure - { + public void dettach(String aCommentId,String aMediaId) throws DatabaseFailure { if (aMediaId!=null){ DatabaseCommentToMedia.getInstance().delete(aCommentId, aMediaId); DatabaseContent.getInstance().setUnproduced("id="+getFieldValue("to_media")); @@ -94,7 +93,7 @@ public class EntityComment extends AbstractEntity { DatabaseContent.getInstance().setUnproduced("id="+getFieldValue("to_media")); } else { - logger.error("EntityContent: attach without mid"); + getLogger().error("EntityContent: attach without mid"); } } } diff --git a/source/mircoders/entity/EntityContent.java b/source/mircoders/entity/EntityContent.java index d35ad7c7..96ab2dc9 100755 --- a/source/mircoders/entity/EntityContent.java +++ b/source/mircoders/entity/EntityContent.java @@ -44,22 +44,13 @@ import mircoders.storage.DatabaseContentToMedia; * this class implements mapping of one line of the database table content * to a java object * - * @version $Id: EntityContent.java,v 1.19.2.11 2005/03/26 11:26:26 zapata Exp $ + * @version $Id: EntityContent.java,v 1.19.2.12 2005/10/30 00:46:58 zapata Exp $ * @author mir-coders group * */ public class EntityContent extends AbstractEntity { - // constructors - - public EntityContent() - { - super(); - - logger = new LoggerWrapper("Entity.Content"); - } - /** * set is_produced flag for the article */ @@ -114,7 +105,7 @@ public class EntityContent extends AbstractEntity { setProduced(false); } else { - logger.error("EntityContent: attach without mid"); + getLogger().error("EntityContent: attach without mid"); } } diff --git a/source/mircoders/entity/EntityImages.java b/source/mircoders/entity/EntityImages.java index 21404d68..019ee22c 100755 --- a/source/mircoders/entity/EntityImages.java +++ b/source/mircoders/entity/EntityImages.java @@ -50,8 +50,6 @@ public class EntityImages extends EntityUploadedMedia public EntityImages() { super(); - - logger = new LoggerWrapper("Entity.UploadedMedia.Images"); } /** diff --git a/source/mircoders/entity/EntityUploadedMedia.java b/source/mircoders/entity/EntityUploadedMedia.java index 74cb05ce..578ad4b6 100755 --- a/source/mircoders/entity/EntityUploadedMedia.java +++ b/source/mircoders/entity/EntityUploadedMedia.java @@ -41,16 +41,10 @@ import mircoders.storage.DatabaseUploadedMedia; /** * * @author mh, mir-coders group - * @version $Id: EntityUploadedMedia.java,v 1.26.2.12 2005/03/26 11:26:26 zapata Exp $ + * @version $Id: EntityUploadedMedia.java,v 1.26.2.13 2005/10/30 00:46:58 zapata Exp $ */ public class EntityUploadedMedia extends AbstractEntity { - public EntityUploadedMedia() { - super(); - - logger = new LoggerWrapper("Entity.UploadedMedia"); - } - public void update() throws DatabaseFailure { super.update(); diff --git a/source/mircoders/entity/EntityVideo.java b/source/mircoders/entity/EntityVideo.java index 00e3639d..ed5b918c 100755 --- a/source/mircoders/entity/EntityVideo.java +++ b/source/mircoders/entity/EntityVideo.java @@ -31,21 +31,14 @@ package mircoders.entity; import java.util.Map; -import mir.log.LoggerWrapper; - public class EntityVideo extends EntityUploadedMedia { - public EntityVideo() { - super(); - - logger = new LoggerWrapper("Entity.UploadedMedia.Video"); - } - - public void setFieldValues(Map theStringValues) { - if (theStringValues != null) { - if (!theStringValues.containsKey("is_published")) - theStringValues.put("is_published", "0"); + public void setFieldValues(Map someFieldValues) { + if (someFieldValues != null) { + if (!someFieldValues.containsKey("is_published")) { + someFieldValues.put("is_published", "0"); + } } - super.setFieldValues(theStringValues); + super.setFieldValues(someFieldValues); } } \ No newline at end of file diff --git a/source/mircoders/global/JobQueue.java b/source/mircoders/global/JobQueue.java index 5cc3a922..99ffed77 100755 --- a/source/mircoders/global/JobQueue.java +++ b/source/mircoders/global/JobQueue.java @@ -82,8 +82,9 @@ public class JobQueue { public String appendJob(Job aJob, String aDescription) { try { - if (System.currentTimeMillis() - lastCleanup > 60000) + if (System.currentTimeMillis() - lastCleanup > 60000) { cleanupJobList(); + } } catch (Throwable t) { logger.error("error while cleaning up joblist: " + t.toString()); @@ -92,8 +93,10 @@ public class JobQueue { synchronized (jobHandlers) { JobHandler jobHandler = new JobHandler(aJob, Integer.toString(nrJobs), aDescription); nrJobs++; + jobHandlers.add(jobHandler); identifierToJobHandler.put(jobHandler.getIdentifier(), jobHandler); + jobHandler.setPending(); jobHandlers.notify(); @@ -103,6 +106,10 @@ public class JobQueue { } public List getJobsInfo() { + if (System.currentTimeMillis() - lastCleanup > 60000) { + cleanupJobList(); + } + List result = new ArrayList(); synchronized (jobHandlers) { @@ -132,6 +139,7 @@ public class JobQueue { synchronized (jobHandler) { if (jobHandler.isFinished() && jobHandler.getLastChange().before(treshold)) { toRemove.add(jobHandler); + identifierToJobHandler.remove(jobHandler.getIdentifier()); } } } diff --git a/source/mircoders/global/ProducerEngine.java b/source/mircoders/global/ProducerEngine.java index d60345bd..de40217c 100755 --- a/source/mircoders/global/ProducerEngine.java +++ b/source/mircoders/global/ProducerEngine.java @@ -29,15 +29,7 @@ */ package mircoders.global; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - import mir.config.MirPropertiesConfiguration; -import mir.log.LoggerToWriterAdapter; import mir.log.LoggerWrapper; import mir.producer.Producer; import mir.producer.ProducerFactory; @@ -45,32 +37,30 @@ import mir.producer.ProductionContext; import mir.util.GeneratorFormatAdapters; import mir.util.StringRoutines; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Collections; + public class ProducerEngine { - private JobQueue producerJobQueue; - private LoggerWrapper logger; - private Map nameToFactory; - private List factories; + private final JobQueue producerJobQueue; + private final LoggerWrapper logger = new LoggerWrapper("Producer"); + private final Map nameToFactory = new HashMap();; + private List factories = new ArrayList(); protected ProducerEngine() { - logger = new LoggerWrapper("Producer"); producerJobQueue = new JobQueue(new LoggerWrapper("Producer.Queue")); - - factories = new ArrayList(); - nameToFactory = new HashMap(); - - try { - reloadConfiguration(); - } - catch (Throwable t) { - } + reloadConfiguration(); } /** * Reloads the producer configuration */ - public void reloadConfiguration() throws MirGlobalExc, MirGlobalFailure { + public void reloadConfiguration() { try { - factories = MirGlobal.localizer().producers().loadFactories(); + factories = new ArrayList(MirGlobal.localizer().producers().loadFactories()); synchronized (nameToFactory) { nameToFactory.clear(); @@ -100,21 +90,21 @@ public class ProducerEngine { * Returns all factories */ public List getFactories() { - return factories; + return Collections.unmodifiableList(factories); } /** * Adds a producer job to the queue */ public void addJob(String aProducerFactory, String aVerb) throws MirGlobalExc, MirGlobalFailure { - ProducerFactory factory; + ProducerFactory factory = getFactoryForName( aProducerFactory ); - factory = getFactoryForName( aProducerFactory ); - - if (factory==null) + if (factory==null) { throw new MirGlobalExc("Unknown producer: " + aProducerFactory); + } - if (!factory.allowVerb(aVerb)) + if (!factory.allowVerb(aVerb)) { throw new MirGlobalExc("illegal producer/verb combination: " + aProducerFactory+"::"+aVerb); + } producerJobQueue.appendJob( new ProducerJob(aProducerFactory, aVerb), aProducerFactory+"."+aVerb); @@ -139,26 +129,34 @@ public class ProducerEngine { } private String convertStatus(JobQueue.JobInfo aJob) { + switch (aJob.getStatus()) { case JobQueue.STATUS_ABORTED: return "aborted"; + case JobQueue.STATUS_CANCELLED: return "cancelled"; + case JobQueue.STATUS_CREATED: return "created"; + case JobQueue.STATUS_PENDING: return "pending"; + case JobQueue.STATUS_PROCESSED: return "processed"; + case JobQueue.STATUS_PROCESSING: return "processing"; } + return "unknown"; } private Map convertJob(JobQueue.JobInfo aJob) { try { Map result = new HashMap(); + result.put("identifier", aJob.getIdentifier()); result.put("description", aJob.getDescription()); result.put("priority", new Integer(aJob.getPriority())); @@ -198,7 +196,7 @@ public class ProducerEngine { private Producer producer; private ProductionContext productionContext; - public ProducerJob(String aFactory, String aVerb) { + ProducerJob(String aFactory, String aVerb) { factoryName = aFactory; verb = aVerb; producer=null; @@ -219,22 +217,14 @@ public class ProducerEngine { } public boolean run() { - final ProducerFactory factory; - long startTime; - long endTime; - boolean result = false; final Map startingMap = new HashMap(); - Map mirMap = new HashMap(); - mirMap.put("producer", factoryName); - mirMap.put("verb", verb); - startingMap.put("Mir", mirMap); - - startTime = System.currentTimeMillis(); + long startTime = System.currentTimeMillis(); logger.info("Producing job: "+factoryName+"."+verb); + boolean result = false; try { - factory = getFactoryForName(factoryName); + final ProducerFactory factory = getFactoryForName(factoryName); if (factory!=null) { MirGlobal.localizer().producerAssistant().initializeGenerationValueSet(startingMap); @@ -272,9 +262,11 @@ public class ProducerEngine { return startingMap; } }; + result = producer.execute(productionContext); productionContext = null; producer = null; + try { MirGlobal.localizer().producers().afterProducerTask(factoryName, verb); } @@ -285,10 +277,10 @@ public class ProducerEngine { } } catch (Throwable t) { - logger.error("Exception occurred while producing " + factoryName + "." + verb + t.getMessage()); - t.printStackTrace(new PrintWriter(new LoggerToWriterAdapter(logger, LoggerWrapper.ERROR_MESSAGE))); + logger.error("Exception occurred while producing " + factoryName + "." + verb, t); } - endTime = System.currentTimeMillis(); + long endTime = System.currentTimeMillis(); + logger.info("Done producing job: " + factoryName + "." + verb + ", time elapsed:" + (endTime-startTime) + " ms"); return result; @@ -317,18 +309,18 @@ public class ProducerEngine { } public static List parseProducerTaskList(String aList) throws MirGlobalExc { - Iterator i; List result = new ArrayList(); - i = StringRoutines.splitString(aList, ";").iterator(); + Iterator i = StringRoutines.splitString(aList, ";").iterator(); while (i.hasNext()) { String taskExpression = ((String) i.next()).trim(); if (taskExpression.length()>0) { List parts = StringRoutines.splitString(taskExpression, "."); - if (parts.size() != 2) + if (parts.size() != 2) { throw new MirGlobalExc("Invalid producer expression: '" + taskExpression + "'"); + } result.add(new ProducerEngine.ProducerTask( (String) parts.get(0), (String) parts.get(1))); } } diff --git a/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java b/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java index b6833ed9..01333162 100755 --- a/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java @@ -35,6 +35,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.Collections; import mir.config.MirPropertiesConfiguration; import mir.log.LoggerWrapper; @@ -171,8 +172,9 @@ public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer { long l = System.currentTimeMillis(); l = (l*l*l*l)/random; - if (l<0) + if (l<0) { l = l * -1; + } String returnString = ""+l; @@ -180,11 +182,11 @@ public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer { } public List getAntiAbuseFilterTypes() { - return filterTypes; + return Collections.unmodifiableList(filterTypes); } public boolean allowArticlePublication(EntityContent anArticle){ - return (anArticle!=null) && "t".equals(anArticle.getFieldValue("is_published")); + return anArticle != null && "1".equals(anArticle.getFieldValue("is_published")); } public void removeSimpleAntiAbuseFilterType(String aName) { diff --git a/source/mircoders/servlet/ServletModuleComment.java b/source/mircoders/servlet/ServletModuleComment.java index 8f6bbebb..b7123148 100755 --- a/source/mircoders/servlet/ServletModuleComment.java +++ b/source/mircoders/servlet/ServletModuleComment.java @@ -124,8 +124,7 @@ public class ServletModuleComment extends AdminServletModule { } } - public void attach(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc - { + public void attach(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { String mediaIdParam = aRequest.getParameter("mid"); String commentId = aRequest.getParameter("commentid"); @@ -146,8 +145,7 @@ public class ServletModuleComment extends AdminServletModule { editObject(aRequest, aResponse, commentId); } - public void dettach(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc - { + public void dettach(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { String commentId = aRequest.getParameter("commentid"); String midParam = aRequest.getParameter("mid"); if (commentId == null) {