{Filename?} Memory Leak?

From: Justin Deutsch (justin.deutsc..elevance.com.au)
Date: Wed Oct 27 2004 - 22:47:37 EDT

  • Next message: Kevin J. Menard, Jr.: "Re: DB Creation Ant Task?"

    Warning: This message has had one or more attachments removed
    Warning: (Logs.map.xml).
    Warning: Please read the "VirusWarning.txt" attachment(s) for more information.

    Hi All,

    I must say I've been very happy with Cayenne so far. I've been using it
    for a month or sow now on an log reporting tool. This tool takes log
    files and puts them into a database and from there will provide a series
    of reports.

    At the moment I seem to have run into a problem where I run out of
    memory when I'm trying to insert the log files into the database (the
    files total over 300MB of data). The database, currently has three tables:

       Message - the log message.
       Log_Level - the level of the message, e.g. warn, info.
       Host - The host the message was logged on.

    At the moment I seem to be able to insert about 44000 entries before I
    run out of memory (Heap size: 64MB). Now I believe that I'm getting rid
      of all of the instances of Message, LogLevel and Host (the java
    objects) that I am creating, but I'm not sure, and I was hoping someone
    could help me out.

    The following code are the two classes that sit above the Cayenne
    classes. The only modifications I have made to the Cayenne classes is
    to over ride the toString methods.

    Code over view:

    TestDB finds the log files and then iterates over it and adds them to
    the DBLog. DBLog will cache N (100 in this case) entries before
    flushing them to the database (context.commitChanges()). I also call
    flush between files to ensure that all of the entries have been saved to
    the DB.

    Any help would be greatly appreciated.

    == TestDB.java ==
    <imports removed>

    public class TestDB {

         public static void main(String[] argv){
             config = Configuration.getSharedConfiguration();
             domain = config.getDomain();
             context = DataContext.createDataContext();

             String files[] = {
                 "e:/tmp/NTGTest_Logs/log/skip.log.old-20041009-080513",
                 "e:/tmp/NTGTest_Logs/log/skip.log.old-20041011-025444",
                 "e:/tmp/NTGTest_Logs/log/skip.log.old-20041011-025444"
             };

             for(int i = 0; i < files.length; i++){

                 insertIntoLog(files[i]);
             }
         }

         private static void insertIntoLog(String file){
             //Log outputLog = new DBLog(context, 10000);
             Log outputLog = new DBLog(context, 100);
             System.out.println("Processing " + file);
             Log inputLog = new SpiderLog(file, inputTimeZone);

             Entry entry;

             Map params;
             List messages;
             SelectQuery sq;

             try{
                 while(inputLog.hasNext()){
                     params = new HashMap();
                     entry =(Entry)inputLog.next() ;
                     entry.setHost("search.nt.gov.au");
                     entry.setProcessID(-1);

                     outputLog.add(entry);

                     /*
                     params.put("date", entry.getDate());
                     params.put("message", entry.getMessage());
                     sq = checkQuery.queryWithParameters(params);

                     messages = context.performQuery(sq);

                     if(messages.size() == 0){
                         outputLog.add(entry);
                         System.out.print(".");
                     } else {
                         System.out.println ("Diplicate '" + entry.getDate()
                                 + ": " + entry.getMessage()
                                 + "' - skipping");
                     }
                      */
                 }
                 outputLog.flush();
             } catch(LogUncheckedException f){
                 System.err.println("Unchecked: " + f.getMessage());
             } catch(LogCheckedException f){
                 System.err.println("Checked: " + f.getMessage());

             }
         }

         private static Configuration config =
             Configuration.getSharedConfiguration();
         private static DataDomain domain = config.getDomain();
         private static DataContext context =
             DataContext.createDataContext();
         private static TimeZone inputTimeZone =TimeZone.getTimeZone(
             "Australia/Darwin");

         private static final Expression checkTemplate =
             Expression.fromString(
                 "loggedDate = $date and message = $message");
         private static final SelectQuery checkQuery = new SelectQuery(
             Message.class);

         static {
             checkQuery.setQualifier(checkTemplate);
         }
    }
    == End TestDB.java ==
    == DBLog.java ==
    package au.com.relevance.log.db;
    <imports removed>
    /**
      * DBLog implements the Log interface for databases
      * conforming to the Relevance Logging Database. This interface uses
      * the Cayenne ORM to achieve this goal.<p>
      *
      * The DBLog automatically flushes the log entries based on the cache
      * size. The default cache size is 1.
      *
      * <strong>NB: Currently does not support reading from the data
      * store </strong>
      *
      *..ee Log
      */
    public class DBLog extends AbstractLog {

    < removed un-used constructors >
         /**
          *
          *..aram context the Cayenne context for the database.
          *..aram cacheSize the number of entries to store before flushing
          * the buffer automatically.
          */
         public DBLog(DataContext context, int cacheSize) {
             this.ctxt = context;
             this.cacheSize = cacheSize;

             createQueue();
         }

         /**
          * ..nheritDoc}
          */
         public void add(Entry entry) throws LogAttributeException,
         LogCheckedException, LogHostException {
             entryQueue.add(entry);

             if(entryQueue.isFull()){
                 flush();
             } else {
                 emptyEntry = false;
             }
         }

         /**
          * ..nheritDoc}
          */
         public void flush() throws LogAttributeException,
          LogCheckedException,
          LogHostException, LogLogLevelException {
             Message m;
             Entry e;
             Iterator i = entryQueue.iterator();

             while(i.hasNext()){

                 e = (Entry) i.next();
                 checkAttributes(e);

                 m = (Message)
                      ctxt.createAndRegisterNewObject(Message.class);
                 m.setHost(host);
                 m.setLogLevel(level);
                 m.setMessage(e.getMessage());
                 m.setProcessID(e.getProcessID());
                 m.setLoggedDate(e.getDate());
                 m.setApplication(e.getApplication());
                 m.setEnteredDate(Calendar.getInstance().getTime());

             }
             i = null;
             ctxt.commitChanges();

             createQueue();
             emptyEntry = true;
         }

         /**
          * Ensure that the required attributes are set for the
          * entry.
          *
          *..aram entry the entry to check.
          *
          *..eturn true if the attributes are set appropriately, false
          * otherwise.
          */
         private boolean checkAttributes(Entry entry)
             throws LogAttributeException,
                    LogHostException, LogLogLevelException {
             boolean passed = true;
             boolean firstAttribute = true;

             StringBuffer attributeExceptionMsg = new StringBuffer(
             "The follwoing attribute(s) were not set: ");
                     /*
                      * Verify all of the attributes
                      */
             if(entry.getHost() == null){
                 firstAttribute = false;
                 attributeExceptionMsg.append("Host name");
             }
             if(entry.getDate() == null){
                 firstAttribute = false;
                 if(!firstAttribute){
                     attributeExceptionMsg.append(", ");
                 }
                 attributeExceptionMsg.append("Date");
             }
             < other attribute test removed for brefity >

             if(!firstAttribute){
                 throw new
                     LogAttributeException(attributeExceptionMsg.toString());
             }

                     /*
                      * Verify the host name and log level
                      */
             host = getHostObject(entry.getHost());
             level = getLogLevelObject(entry.getLogLevel());

             return passed;
         }

         /**
          * Retrieve the host object from the database.
          *
          *..aram host the name of the host.
          *
          *..eturn the host object.
          */
         private Host getHostObject(String host) throws LogHostException {
            Map params = new HashMap();
             List hosts;

             params.put("name", host);

             hosts = ctxt.performQuery("HostQuery", params, false);

             if(hosts.size() == 0){
                 throw new LogHostException(
                     "The host for the entry wasn't found in the database");
             }
             return (Host) hosts.get(0);
         }

         /**
          * ..nheritDoc}
          */
         public void snapShot(){
             snapShot = true;
         }

         /**
          * ..nheritDoc}
          */
         public void keepUpToDate(){
             snapShot = false;
         }

         /**
          * ..nheritDoc}
          * <strong> Not Currently Supported </strong>
          */
         public Object next() {
             throw new LogUncheckedException(
                 "This part of the interface is not currently supported");
         }

         /**
          * ..nheritDoc}
          * <strong> Not Currently Supported </strong>
          */
         public boolean hasNext() {
             throw new LogUncheckedException(
                 "This part of the interface is not currently supported");
         }

         /**
          * Retrieve the log level object from the database.
          *
          *..aram level the log level to retrieve.
          *
          *..eturn the log level object representing the <code>level</code>
          */
         private LogLevel getLogLevelObject(String level) throws
    LogLogLevelException {
             Map params = new HashMap();
             //SelectQuery sq;
             List logLevels;

             params.put("name", level);
             //sq = logLevelQuery.queryWithParameters(params);

             //logLevels = ctxt.performQuery(sq);
             logLevels = ctxt.performQuery("LogLevelQuery", params, false);

             if(logLevels.size() == 0){
                 throw new LogLogLevelException(
                     "The log level for the entry wasn't found in the
    database");
             }

             return (LogLevel) logLevels.get(0);
         }

         /**
          * Create a new queue.
          */
         private void createQueue(){
             entryQueue = new BoundedFifoBuffer(cacheSize);
         }

         /*
          * Database details
          */
         private DataContext ctxt;

         /*
          * The entry details
          */
         private Entry entry = null;

         private Host host = null;
         private LogLevel level = null;

         /*
          * Internal State
          */
         private boolean emptyEntry = true;
         private boolean snapShot = true;
         private BoundedFifoBuffer entryQueue;

         /*
          * Default Cache Size
          */
         private int cacheSize = 1;

         /*
          * Queries to find things.
          */

         private static final SelectQuery hostQuery =
             new SelectQuery(Host.class);
         private static final SelectQuery logLevelQuery =
             new SelectQuery(LogLevel.class);

         /*
          * Message strings
          */
         private static final String startAttributeMessage =
             "The attribute(s) ";
         private static final String endAttributeMessage = ", were not set.";

    }
    == End DBLog.java ==

    -- 
    Justin Deutsch
    

    Relevance... because results count

    Relevance Phone: +61 (0)2 6241 6400 A.B.N. 86 063 403 690 Fax: +61 (0)2 6241 6422 Unit 11, Mobile: +61 (0)40 246 55 88 Cnr Brookes & Heffernan Sts, E-mail: Justin.Deutsc..elevance.com.au Mitchell ACT 2911 Web: http://www.relevance.com.au







    This archive was generated by hypermail 2.0.0 : Wed Oct 27 2004 - 23:01:13 EDT