summaryrefslogtreecommitdiff
path: root/csharp/src/Ice/LoggerAdminI.cs
diff options
context:
space:
mode:
authorMatthew Newhook <matthew@zeroc.com>2015-03-21 15:35:40 -0230
committerMatthew Newhook <matthew@zeroc.com>2015-03-21 15:35:40 -0230
commit630a37d2fe66f24518299e705f958b571803c522 (patch)
tree969723791bdc4d73bb099c19d45554d0ca241ad9 /csharp/src/Ice/LoggerAdminI.cs
parentFix some README.md markdown formatting (diff)
downloadice-630a37d2fe66f24518299e705f958b571803c522.tar.bz2
ice-630a37d2fe66f24518299e705f958b571803c522.tar.xz
ice-630a37d2fe66f24518299e705f958b571803c522.zip
py -> python
rb -> ruby objc -> objective-c cs -> csharp
Diffstat (limited to 'csharp/src/Ice/LoggerAdminI.cs')
-rw-r--r--csharp/src/Ice/LoggerAdminI.cs483
1 files changed, 483 insertions, 0 deletions
diff --git a/csharp/src/Ice/LoggerAdminI.cs b/csharp/src/Ice/LoggerAdminI.cs
new file mode 100644
index 00000000000..e32b098c634
--- /dev/null
+++ b/csharp/src/Ice/LoggerAdminI.cs
@@ -0,0 +1,483 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+
+namespace IceInternal
+{
+sealed class LoggerAdminI : Ice.LoggerAdminDisp_
+{
+ public override void
+ attachRemoteLogger(Ice.RemoteLoggerPrx prx, Ice.LogMessageType[] messageTypes, string[] categories,
+ int messageMax, Ice.Current current)
+ {
+ if(prx == null)
+ {
+ return; // can't send this null RemoteLogger anything!
+ }
+
+ Ice.RemoteLoggerPrx remoteLogger = Ice.RemoteLoggerPrxHelper.uncheckedCast(prx.ice_twoway());
+
+ Filters filters = new Filters(messageTypes, categories);
+ LinkedList<Ice.LogMessage> initLogMessages = null;
+
+ lock(this)
+ {
+ if(_sendLogCommunicator == null)
+ {
+ if(_destroyed)
+ {
+ throw new Ice.ObjectNotExistException();
+ }
+
+ _sendLogCommunicator =
+ createSendLogCommunicator(current.adapter.getCommunicator(), _logger.getLocalLogger());
+ }
+
+ Ice.Identity remoteLoggerId = remoteLogger.ice_getIdentity();
+
+ if(_remoteLoggerMap.ContainsKey(remoteLoggerId))
+ {
+ if(_traceLevel > 0)
+ {
+ _logger.trace(_traceCategory, "rejecting `" + remoteLogger.ToString() +
+ "' with RemoteLoggerAlreadyAttachedException");
+ }
+
+ throw new Ice.RemoteLoggerAlreadyAttachedException();
+ }
+
+ _remoteLoggerMap.Add(remoteLoggerId,
+ new RemoteLoggerData(changeCommunicator(remoteLogger, _sendLogCommunicator), filters));
+
+ if(messageMax != 0)
+ {
+ initLogMessages = new LinkedList<Ice.LogMessage>(_queue); // copy
+ }
+ else
+ {
+ initLogMessages = new LinkedList<Ice.LogMessage>();
+ }
+ }
+
+ if(_traceLevel > 0)
+ {
+ _logger.trace(_traceCategory, "attached `" + remoteLogger.ToString() + "'");
+ }
+
+ if(initLogMessages.Count > 0)
+ {
+ filterLogMessages(initLogMessages, filters.messageTypes, filters.traceCategories, messageMax);
+ }
+
+ try
+ {
+ remoteLogger.begin_init(_logger.getPrefix(), initLogMessages.ToArray(), initCompleted, null);
+ }
+ catch(Ice.LocalException ex)
+ {
+ deadRemoteLogger(remoteLogger, _logger, ex, "init");
+ throw ex;
+ }
+ }
+
+ public override bool
+ detachRemoteLogger(Ice.RemoteLoggerPrx remoteLogger, Ice.Current current)
+ {
+ if(remoteLogger == null)
+ {
+ return false;
+ }
+
+ //
+ // No need to convert the proxy as we only use its identity
+ //
+ bool found = removeRemoteLogger(remoteLogger);
+
+ if(_traceLevel > 0)
+ {
+ if(found)
+ {
+ _logger.trace(_traceCategory, "detached `" + remoteLogger.ToString() + "'");
+ }
+ else
+ {
+ _logger.trace(_traceCategory, "cannot detach `" + remoteLogger.ToString() + "': not found");
+ }
+ }
+
+ return found;
+ }
+
+ public override Ice.LogMessage[]
+ getLog(Ice.LogMessageType[] messageTypes, string[] categories, int messageMax, out string prefix,
+ Ice.Current current)
+ {
+ LinkedList<Ice.LogMessage> logMessages = null;
+ lock(this)
+ {
+ if(messageMax != 0)
+ {
+ logMessages = new LinkedList<Ice.LogMessage>(_queue);
+ }
+ else
+ {
+ logMessages = new LinkedList<Ice.LogMessage>();
+ }
+ }
+
+ prefix = _logger.getPrefix();
+
+ if(logMessages.Count > 0)
+ {
+ Filters filters = new Filters(messageTypes, categories);
+ filterLogMessages(logMessages, filters.messageTypes, filters.traceCategories, messageMax);
+ }
+ return logMessages.ToArray();
+ }
+
+
+ internal LoggerAdminI(Ice.Properties props, LoggerAdminLoggerI logger)
+ {
+ _maxLogCount = props.getPropertyAsIntWithDefault("Ice.Admin.Logger.KeepLogs", 100);
+ _maxTraceCount = props.getPropertyAsIntWithDefault("Ice.Admin.Logger.KeepTraces", 100);
+ _traceLevel = props.getPropertyAsInt("Ice.Trace.Admin.Logger");
+ _logger = logger;
+ }
+
+ internal void destroy()
+ {
+ Ice.Communicator sendLogCommunicator = null;
+
+ lock(this)
+ {
+ if(!_destroyed)
+ {
+ _destroyed = true;
+ sendLogCommunicator = _sendLogCommunicator;
+ _sendLogCommunicator = null;
+ }
+ }
+
+ //
+ // Destroy outside lock to avoid deadlock when there are outstanding two-way log calls sent to
+ // remote logggers
+ //
+ if(sendLogCommunicator != null)
+ {
+ sendLogCommunicator.destroy();
+ }
+ }
+
+ internal List<Ice.RemoteLoggerPrx> log(Ice.LogMessage logMessage)
+ {
+ lock(this)
+ {
+ List<Ice.RemoteLoggerPrx> remoteLoggers = null;
+
+ //
+ // Put message in _queue
+ //
+ if((logMessage.type != Ice.LogMessageType.TraceMessage && _maxLogCount > 0) ||
+ (logMessage.type == Ice.LogMessageType.TraceMessage && _maxTraceCount > 0))
+ {
+ _queue.AddLast(logMessage);
+
+ if(logMessage.type != Ice.LogMessageType.TraceMessage)
+ {
+ Debug.Assert(_maxLogCount > 0);
+ if(_logCount == _maxLogCount)
+ {
+ //
+ // Need to remove the oldest log from the queue
+ //
+ Debug.Assert(_oldestLog != null);
+ var next = _oldestLog.Next;
+ _queue.Remove(_oldestLog);
+ _oldestLog = next;
+
+ while(_oldestLog != null && _oldestLog.Value.type == Ice.LogMessageType.TraceMessage)
+ {
+ _oldestLog = _oldestLog.Next;
+ }
+ Debug.Assert(_oldestLog != null); // remember: we just added a Log at the end
+ }
+ else
+ {
+ Debug.Assert(_logCount < _maxLogCount);
+ _logCount++;
+ if(_oldestLog == null)
+ {
+ _oldestLog = _queue.Last;
+ }
+ }
+ }
+ else
+ {
+ Debug.Assert(_maxTraceCount > 0);
+ if(_traceCount == _maxTraceCount)
+ {
+ //
+ // Need to remove the oldest trace from the queue
+ //
+ Debug.Assert(_oldestTrace != null);
+ var next = _oldestTrace.Next;
+ _queue.Remove(_oldestTrace);
+ _oldestTrace = next;
+
+ while(_oldestTrace != null && _oldestTrace.Value.type != Ice.LogMessageType.TraceMessage)
+ {
+ _oldestTrace = _oldestTrace.Next;
+ }
+ Debug.Assert(_oldestTrace != null); // remember: we just added a Log at the end
+ }
+ else
+ {
+ Debug.Assert(_traceCount < _maxTraceCount);
+ _traceCount++;
+ if(_oldestTrace == null)
+ {
+ _oldestTrace = _queue.Last;
+ }
+ }
+ }
+ }
+
+ //
+ // Queue updated, now find which remote loggers want this message
+ //
+ foreach(RemoteLoggerData p in _remoteLoggerMap.Values)
+ {
+ Filters filters = p.filters;
+
+ if(filters.messageTypes.Count == 0 || filters.messageTypes.Contains(logMessage.type))
+ {
+ if(logMessage.type != Ice.LogMessageType.TraceMessage || filters.traceCategories.Count == 0 ||
+ filters.traceCategories.Contains(logMessage.traceCategory))
+ {
+ if(remoteLoggers == null)
+ {
+ remoteLoggers = new List<Ice.RemoteLoggerPrx>();
+ }
+ remoteLoggers.Add(p.remoteLogger);
+ }
+ }
+ }
+
+ return remoteLoggers;
+ }
+ }
+
+ internal void deadRemoteLogger(Ice.RemoteLoggerPrx remoteLogger, Ice.Logger logger, Ice.LocalException ex,
+ string operation)
+ {
+ //
+ // No need to convert remoteLogger as we only use its identity
+ //
+ if(removeRemoteLogger(remoteLogger))
+ {
+ if(_traceLevel > 0)
+ {
+ logger.trace(_traceCategory, "detached `" + remoteLogger.ToString() + "' because "
+ + operation + " raised:\n" + ex.ToString());
+ }
+ }
+ }
+
+ internal int getTraceLevel()
+ {
+ return _traceLevel;
+ }
+
+ private bool removeRemoteLogger(Ice.RemoteLoggerPrx remoteLogger)
+ {
+ lock(this)
+ {
+ return _remoteLoggerMap.Remove(remoteLogger.ice_getIdentity());
+ }
+ }
+
+ private void initCompleted(Ice.AsyncResult r)
+ {
+ Ice.RemoteLoggerPrx remoteLogger = Ice.RemoteLoggerPrxHelper.uncheckedCast(r.getProxy());
+
+ try
+ {
+ remoteLogger.end_init(r);
+
+ if(_traceLevel > 1)
+ {
+ _logger.trace(_traceCategory, r.getOperation() + " on `" + remoteLogger.ToString()
+ + "' completed successfully");
+ }
+ }
+ catch(Ice.LocalException ex)
+ {
+ deadRemoteLogger(remoteLogger, _logger, ex, r.getOperation());
+ }
+ }
+
+ private static void filterLogMessages(LinkedList<Ice.LogMessage> logMessages,
+ HashSet<Ice.LogMessageType> messageTypes,
+ HashSet<string> traceCategories, int messageMax)
+ {
+ Debug.Assert(logMessages.Count > 0 && messageMax != 0);
+
+ //
+ // Filter only if one of the 3 filters is set; messageMax < 0 means "give me all"
+ // that match the other filters, if any.
+ //
+ if(messageTypes.Count > 0 || traceCategories.Count > 0 || messageMax > 0)
+ {
+ int count = 0;
+ var p = logMessages.Last;
+ while(p != null)
+ {
+ bool keepIt = false;
+ Ice.LogMessage msg = p.Value;
+ if(messageTypes.Count == 0 || messageTypes.Contains(msg.type))
+ {
+ if(msg.type != Ice.LogMessageType.TraceMessage || traceCategories.Count == 0 ||
+ traceCategories.Contains(msg.traceCategory))
+ {
+ keepIt = true;
+ }
+ }
+
+ if(keepIt)
+ {
+ ++count;
+ if(messageMax > 0 && count >= messageMax)
+ {
+ // Remove all older messages
+ p = p.Previous;
+ while(p != null)
+ {
+ var previous = p.Previous;
+ logMessages.Remove(p);
+ p = previous;
+ }
+ break; // while
+ }
+ else
+ {
+ p = p.Previous;
+ }
+ }
+ else
+ {
+ var previous = p.Previous;
+ logMessages.Remove(p);
+ p = previous;
+ }
+ }
+ }
+ // else, don't need any filtering
+ }
+
+ //
+ // Change this proxy's communicator, while keeping its invocation timeout
+ //
+ private static Ice.RemoteLoggerPrx changeCommunicator(Ice.RemoteLoggerPrx prx, Ice.Communicator communicator)
+ {
+ if(prx == null)
+ {
+ return null;
+ }
+
+ Ice.ObjectPrx result = communicator.stringToProxy(prx.ToString());
+ return Ice.RemoteLoggerPrxHelper.uncheckedCast(result.ice_invocationTimeout(prx.ice_getInvocationTimeout()));
+ }
+
+ private static void copyProperties(string prefix, Ice.Properties from, Ice.Properties to)
+ {
+ foreach(var p in from.getPropertiesForPrefix(prefix))
+ {
+ to.setProperty(p.Key, p.Value);
+ }
+ }
+
+ private static Ice.Communicator createSendLogCommunicator(Ice.Communicator communicator, Ice.Logger logger)
+ {
+ Ice.InitializationData initData = new Ice.InitializationData();
+ initData.logger = logger;
+ initData.properties = Ice.Util.createProperties();
+
+ Ice.Properties mainProps = communicator.getProperties();
+
+ copyProperties("Ice.Default.Locator", mainProps, initData.properties);
+ copyProperties("Ice.Plugin.IceSSL", mainProps, initData.properties);
+ copyProperties("IceSSL.", mainProps, initData.properties);
+
+ string[] extraProps = mainProps.getPropertyAsList("Ice.Admin.Logger.Properties");
+
+ if(extraProps.Length > 0)
+ {
+ for(int i = 0; i < extraProps.Length; ++i)
+ {
+ string p = extraProps[i];
+ if(!p.StartsWith("--"))
+ {
+ extraProps[i] = "--" + p;
+ }
+ }
+ initData.properties.parseCommandLineOptions("", extraProps);
+ }
+ return Ice.Util.initialize(initData);
+ }
+
+
+ private readonly LinkedList<Ice.LogMessage> _queue = new LinkedList<Ice.LogMessage>();
+ private int _logCount = 0; // non-trace messages
+ private readonly int _maxLogCount;
+ private int _traceCount = 0;
+ private readonly int _maxTraceCount;
+ private readonly int _traceLevel;
+
+ private LinkedListNode<Ice.LogMessage> _oldestTrace = null;
+ private LinkedListNode<Ice.LogMessage> _oldestLog = null;
+
+ private class Filters
+ {
+ internal Filters(Ice.LogMessageType[] m, string[] c)
+ {
+ messageTypes = new HashSet<Ice.LogMessageType>(m);
+ traceCategories = new HashSet<string>(c);
+ }
+
+ internal readonly HashSet<Ice.LogMessageType> messageTypes;
+ internal readonly HashSet<string> traceCategories;
+ }
+
+ private class RemoteLoggerData
+ {
+ internal RemoteLoggerData(Ice.RemoteLoggerPrx prx, Filters f)
+ {
+ remoteLogger = prx;
+ filters = f;
+ }
+
+ internal readonly Ice.RemoteLoggerPrx remoteLogger;
+ internal readonly Filters filters;
+ }
+
+ private readonly Dictionary<Ice.Identity, RemoteLoggerData> _remoteLoggerMap
+ = new Dictionary<Ice.Identity, RemoteLoggerData>();
+
+ private readonly LoggerAdminLoggerI _logger;
+
+ private Ice.Communicator _sendLogCommunicator = null;
+ private bool _destroyed = false;
+ static private readonly string _traceCategory = "Admin.Logger";
+}
+
+}