001/* 002 * Copyright (c) 2004-2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: welker $' 006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 007 * '$Revision: 24234 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.actor; 031 032import java.io.File; 033import java.io.IOException; 034 035import org.apache.commons.logging.Log; 036import org.apache.commons.logging.LogFactory; 037import org.kepler.io.MappedLog; 038 039import ptolemy.actor.TypedAtomicActor; 040import ptolemy.actor.TypedIOPort; 041import ptolemy.data.BooleanToken; 042import ptolemy.data.StringToken; 043import ptolemy.data.expr.FileParameter; 044import ptolemy.data.expr.Parameter; 045import ptolemy.data.type.BaseType; 046import ptolemy.kernel.CompositeEntity; 047import ptolemy.kernel.util.IllegalActionException; 048import ptolemy.kernel.util.NameDuplicationException; 049 050////////////////////////////////////////////////////////////////////////// 051//// MappedLogger 052 053/** 054 * Log a string (single-line) into a file but also keep all text in a HashSet so 055 * that the strings can quickly looked up. This actor is useful to create simple 056 * checkpoint mechanism. 057 * 058 * At first call, MappedLogger looks for the specified file and reads it into 059 * memory if exists. 060 * 061 * At each call, the MappedLogger checks if a the input line already is in the 062 * set. If not, it writes the line into the set and the file. It returns the 063 * boolean flag indicating whether the line was already found (true) or not 064 * (false). The check and write is an atomic operation, so two actors cannot mix 065 * up this behaviour. 066 * 067 * All MappedLogger actors can write into the same file, if their parameter 068 * points to the same file. This allows checking if others already did (and 069 * logged) something. 070 * 071 * Query only (not writing out a line, but only checking its existence) can be 072 * achieved by setting the boolean flag 'checkOnly'. 073 * 074 * If the line is empty (or only white spaces), nothing will be written and 075 * false will be returned. 076 * 077 * @author Norbert Podhorszki 078 * @version $Id: MappedLogger.java 24234 2010-05-06 05:21:26Z welker $ 079 * @since Ptolemy II 5.0.1 080 */ 081public class MappedLogger extends TypedAtomicActor { 082 /** 083 * Construct an actor with the given container and name. 084 * 085 * @param container 086 * The container. 087 * @param name 088 * The name of this actor. 089 * @exception IllegalActionException 090 * If the actor cannot be contained by the proposed 091 * container. 092 * @exception NameDuplicationException 093 * If the container already has an actor with this name. 094 */ 095 public MappedLogger(CompositeEntity container, String name) 096 throws NameDuplicationException, IllegalActionException { 097 super(container, name); 098 099 // Logger file parameter 100 logfile = new FileParameter(this, "logfile"); 101 logfile.setExpression("$CWD" + File.separator + "kepler.ckpt"); 102 103 // line 104 line = new TypedIOPort(this, "line", true, false); 105 line.setTypeEquals(BaseType.STRING); 106 new Parameter(line, "_showName", BooleanToken.FALSE); 107 108 // flag: check only the line in already existing text 109 checkOnly = new Parameter(this, "checkOnly", new BooleanToken(false)); 110 checkOnly.setTypeEquals(BaseType.BOOLEAN); 111 112 // return value: true if the text is found in the map 113 found = new TypedIOPort(this, "found", false, true); 114 found.setTypeEquals(BaseType.BOOLEAN); 115 new Parameter(found, "_showName", BooleanToken.FALSE); 116 117 } 118 119 /*********************************************************** 120 * ports and parameters 121 */ 122 123 /** 124 * The log file. It can be changed between firings. The file will be created 125 * if does not exists. If exists its content will be read before the first 126 * execution. 127 */ 128 public FileParameter logfile; 129 130 /** 131 * The text to be printed into the log. It must be single-line (no newline) 132 * This port expects strings. 133 */ 134 public TypedIOPort line; 135 136 /** 137 * Boolean flag. If true, input will only be checked against already 138 * existing texts but will not be printed out. 139 */ 140 public Parameter checkOnly; 141 142 /** 143 * The boolean return value. True if the line is found in the already 144 * existing text. 145 */ 146 public TypedIOPort found; 147 148 /*********************************************************** 149 * public methods 150 */ 151 152 /** 153 * Nothing to do currently. 154 */ 155 public void initialize() throws IllegalActionException { 156 super.initialize(); 157 _mappedLog = new MappedLog(); 158 } 159 160 /** 161 * fire 162 * 163 * @exception IllegalActionException 164 * Not thrown. 165 */ 166 public void fire() throws IllegalActionException { 167 super.fire(); 168 169 String logText = ((StringToken) line.get(0)).stringValue(); 170 boolean bCheckOnly = ((BooleanToken) checkOnly.getToken()) 171 .booleanValue(); 172 173 // do the work 174 boolean bFound; 175 if (bCheckOnly) { 176 bFound = _mappedLog.check(logfile.asFile(), logText); 177 } else { 178 bFound = _mappedLog.add(logfile.asFile(), logText); 179 } 180 181 if (isDebugging) 182 log.debug("Return " + bFound); 183 found.send(0, new BooleanToken(bFound)); 184 } 185 186 /** 187 * Close all opened log files. This method is invoked exactly once per 188 * execution of an application. None of the other action methods should be 189 * be invoked after it. 190 * 191 * @exception IllegalActionException 192 * Not thrown in this base class. 193 */ 194 public void wrapup() throws IllegalActionException { 195 super.wrapup(); 196 if (isDebugging) 197 log.debug("wrapup begin"); 198 try { 199 _mappedLog.closeAll(); 200 } catch (IOException ex) { 201 log.error("Error at wrapup: " + ex); 202 } 203 if (isDebugging) 204 log.debug("wrapup end"); 205 } 206 207 /** 208 * Close all opened log files. This method is invoked exactly once per 209 * execution of an application. None of the other action methods should be 210 * be invoked after it. 211 * 212 * @exception IllegalActionException 213 * Not thrown in this base class. 214 */ 215 public void stop() { 216 if (isDebugging) 217 log.debug("stop begin"); 218 super.stop(); 219 try { 220 _mappedLog.closeAll(); 221 } catch (IOException ex) { 222 log.error("Error at stop: " + ex); 223 } 224 if (isDebugging) 225 log.debug("stop end"); 226 } 227 228 private MappedLog _mappedLog; 229 230 // apache commons log for the source code logging. 231 private static final Log log = LogFactory.getLog(MappedLogger.class 232 .getName()); 233 private static final boolean isDebugging = log.isDebugEnabled(); 234 235}