/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2004
* Copyright by ESO (in the framework of the ALMA collaboration),
* All rights reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package alma.acs.logging;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.LogRecord;
import org.omg.CORBA.Any;
import org.omg.CORBA.ORB;
import org.omg.CORBA.UserException;
import org.omg.DsLogAdmin.Log;
import org.omg.DsLogAdmin.LogOperations;
import alma.Logging.AcsLogServiceOperations;
import alma.Logging.XmlLogRecord;
import alma.acs.logging.formatters.AcsLogFormatter;
import alma.acs.logging.formatters.AcsXMLLogFormatter;
/**
* Sends log records to the remote CORBA log service.
* No caching or threading is done, so this class should be used at the delivering end of a smarter queue.
*
* @author hsommer
* created Apr 19, 2005 4:15:19 PM
*/
class RemoteLogDispatcher {
/**
* Name of the property which will enable using the ACS extensions to the
* telecom logging service ("Log"), mainly to avoid wrapping all log records with a Corba Any.
*/
public static final String USE_ACS_LOGSERVICE_EXTENSIONS_PROPERTYNAME = "alma.acs.logging.useAcsLogServiceExtensions";
public final boolean useAcsLogServiceExtensions = Boolean.getBoolean(USE_ACS_LOGSERVICE_EXTENSIONS_PROPERTYNAME);
/**
* Maximum number of CORBA Anys (with 1 log record each) sent to remote log service at a time.
* This buffer is is configured in the CDB through the attribute dispatchPacketSize
.
*/
private int bufferSize = 30;
private final ORB orb;
private final AcsLogServiceOperations logService;
private final AcsLogFormatter logFormatter;
private LogRecordComparator timestampLogRecordComparator;
private final boolean DEBUG = Boolean.getBoolean("alma.acs.logging.verbose");
/**
*
* @param orb used for creation of Anys
* @param logService remote log service to which logs are sent.
* Since the reference is persistent across failures and restarts,
* we can keep working with this object the whole time.
* May be null
for unit tests, in which case {@link #sendLogRecords(LogRecord[])}
* will fail and return the all log records inside the FailedLogRecords
structure.
* With ACS 7.0.1 we allow the super type {@link LogOperations} instead of the usually
* expected {@link Log}, to allow unit tests with a mock Log service.
* @param logFormatter used to format LogRecords to Any representation.
* No direct assumption on XML is made, so technically any valid Any returned by the formatter will do
* (as far as this class is concerned).
*/
RemoteLogDispatcher(ORB orb, AcsLogServiceOperations logService, AcsLogFormatter logFormatter) {
this.orb = orb;
this.logService = logService;
this.logFormatter = logFormatter;
timestampLogRecordComparator = new LogRecordComparator(true);
if (useAcsLogServiceExtensions && !(logFormatter instanceof AcsXMLLogFormatter)) {
throw new RuntimeException("Only XML-based remote logging is supported with the " + USE_ACS_LOGSERVICE_EXTENSIONS_PROPERTYNAME + " option.");
}
}
public int getBufferSize() {
return bufferSize;
}
/**
* Sets the size of the log record buffer, which determines the maximum number of log records
* that can be sent to the remote log service in one call.
*
* Corresponds to dispatchPacketSize
in the CDB.
*
* @param newBuffSize value >=1, otherwise ignored
*/
public void setBufferSize(int newBuffSize) {
if (newBuffSize >= 1) {
bufferSize = newBuffSize;
}
else {
System.out.println("RemoteLogDispatcher#setBufferSize: ignoring illegal value " + newBuffSize);
}
}
/**
* Attempts to send logRecords
over to the remote logging service.
* To not lose any log records in case of failure, they can be obtained from the returned
* FailedLogRecords
object, and should be fed back to the log record queue in order to try again later.
*
* Should not be called concurrently (which can't happen since we use a single threaded executor
* in DispatchingLogQueue
).
*
* Sorts all log records by timestamp before converting them for remote transmission.
*
* @param logRecords
* @return those LogRecords that failed to be sent, either because they could not be converted to Any,
* or because the remote logger failed.
*/
FailedLogRecords sendLogRecords(LogRecord[] logRecords) {
// sort this set of records by timestamp (queue delivers them by level/timestamp)
Arrays.sort(logRecords, timestampLogRecordComparator);
FailedLogRecords failures = new FailedLogRecords();
// used for feeding back these LogRecords if the sending fails
List