Author: thebeing
Date: Wed Jul 15 10:41:14 2015
New Revision: 38798

URL: http://svn.gna.org/viewcvs/gnustep?rev=38798&view=rev
Log:
Implement an interface to export memory usage statistics by loading
a bundle. Controlled using the `MemoryLoggerBundle' defaults key.

Added:
    libs/ec/trunk/EcMemoryLogger.h
Modified:
    libs/ec/trunk/ChangeLog
    libs/ec/trunk/EcProcess.m
    libs/ec/trunk/GNUmakefile

Modified: libs/ec/trunk/ChangeLog
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/ChangeLog?rev=38798&r1=38797&r2=38798&view=diff
==============================================================================
--- libs/ec/trunk/ChangeLog     (original)
+++ libs/ec/trunk/ChangeLog     Wed Jul 15 10:41:14 2015
@@ -1,3 +1,9 @@
+2015-07-15  Niels Grewe <[email protected]>
+       * EcMemoryLogger.h
+       * EcProcess.m:
+       Add the ability to load a bundle to export memory logs to. Configured
+       using the 'MemoryLoggerBundle' default key.
+
 2015-07-13  Richard Frith-Macdonald <[email protected]>
 
        * EcProcess.h:

Added: libs/ec/trunk/EcMemoryLogger.h
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/EcMemoryLogger.h?rev=38798&view=auto
==============================================================================
--- libs/ec/trunk/EcMemoryLogger.h      (added)
+++ libs/ec/trunk/EcMemoryLogger.h      Wed Jul 15 10:41:14 2015
@@ -0,0 +1,48 @@
+
+/** Enterprise Control Configuration and Logging 
+    -- memory logger protocol
+
+   Copyright (C) 2015 Free Software Foundation, Inc.
+
+   Written by: Niels Grewe <[email protected]>
+   Date: July 2015
+
+   This file is part of the GNUstep project.
+
+   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 3 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
+   Library 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., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02111 USA.
+
+   */
+
+#import <Foundation/NSObject.h>
+
+@class EcProcess;
+
+/**
+ * This protocol should be implemented by classes that want to receive
+ * callbacks about memory usage in the process. This feature is enabled
+ * by setting the MemoryLoggerBundle user default to a bundle whose 
+ * principal class implements this protocol.
+ */
+@protocol EcMemoryLogger <NSObject>
+/**
+ * This callback is issued once per minute, with totalUsage representing
+ * the memory usage of the process and notLeaked the amount of memory 
+ * accounted for as active by -ecNotLeaked. All values are in bytes.
+ */
+- (void)process: (EcProcess*)process
+   didUseMemory: (uint64_t)totalUsage
+      notLeaked: (uint64_t)notLeaked;
+@end

Modified: libs/ec/trunk/EcProcess.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/EcProcess.m?rev=38798&r1=38797&r2=38798&view=diff
==============================================================================
--- libs/ec/trunk/EcProcess.m   (original)
+++ libs/ec/trunk/EcProcess.m   Wed Jul 15 10:41:14 2015
@@ -59,6 +59,7 @@
 #import "EcHost.h"
 #import "EcUserDefaults.h"
 #import "EcBroadcastProxy.h"
+#import "EcMemoryLogger.h"
 
 #include "config.h"
 
@@ -130,6 +131,7 @@
 static NSUserDefaults  *cmdDefs = nil;
 static NSString                *cmdDebugName = nil;
 static NSMutableDictionary     *cmdLogMap = nil;
+static id<EcMemoryLogger>       cmdMemoryLogger = nil;
 
 static NSDate  *started = nil;         /* Time object was created. */
 static NSDate  *memStats = nil;        /* Time stats were started. */
@@ -1055,8 +1057,51 @@
       DESTROY(started);
       DESTROY(userDir);
       DESTROY(warningLogger);
-    }
-}
+      DESTROY(cmdMemoryLogger);
+    }
+}
+
+
+- (Class)_memoryLoggerClassFromBundle: (NSString*)bundleName
+{
+  NSString *path = nil;
+  Class c = Nil;
+  NSBundle *bundle = nil;
+  NSArray *paths =
+   NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
+                                       NSAllDomainsMask,
+                                       YES);
+  NSEnumerator *e = [paths objectEnumerator];
+  while (nil != (path = [e nextObject]))
+    {
+      path = [path stringByAppendingPathComponent: @"Bundles"];
+      path = [path stringByAppendingPathComponent: bundleName];
+      path = [path stringByAppendingPathExtension: @"bundle"];
+      bundle = [NSBundle bundleWithPath: path];
+      if (bundle != nil)
+        {
+          break;
+        }
+    }
+  if (nil == bundle)
+    {
+      [self cmdWarn: @"Could not load bundle '%@'", bundleName];
+    }
+  else if (Nil == (c = [bundle principalClass]))
+    {
+      [self cmdWarn: @"Could not load principal class from %@ at %@.",
+        bundleName, path];
+    }
+  else if (NO == [c conformsToProtocol: @protocol(EcMemoryLogger)])
+    {
+      [self cmdWarn:
+       @"%@ does not implement the EcMemoryLogger protocol", 
+        NSStringFromClass(c)];
+      c = Nil;
+    }
+  return c;
+}
+
 
 + (NSMutableDictionary*) ecInitialDefaults
 {
@@ -4294,6 +4339,48 @@
     }
 }
 
+- (void)_ensureMemLogger
+{
+  NSString *bundle = [cmdDefs stringForKey: @"MemoryLoggerBundle"];
+  Class cls = Nil;
+  if (nil == bundle)
+    {
+      DESTROY(cmdMemoryLogger);
+      return;
+    }
+  // This is a reasonable fast path if we have already loaded the bundle
+  cls = NSClassFromString(bundle);
+  if ((Nil == cls)
+      || (NO == [cls conformsToProtocol: @protocol(EcMemoryLogger)]))
+    {
+      cls = [self _memoryLoggerClassFromBundle: bundle];
+    }
+  if (Nil == cls)
+    {
+      // No usable logger class, destroy any we might have
+      DESTROY(cmdMemoryLogger);
+      return;
+    }
+  if (NO == [cmdMemoryLogger isKindOfClass: cls])
+    {
+      // If it's no longer the right class, destroy it
+      DESTROY(cmdMemoryLogger);
+    }
+  if (nil == cmdMemoryLogger)
+    {
+      NS_DURING
+        {
+          cmdMemoryLogger = [cls new];
+        }
+      NS_HANDLER
+        {
+          [self cmdWarn: @"Exception creating memory logger: %@",
+             localException];
+        }
+      NS_ENDHANDLER
+    }
+}
+
 - (void) _memCheck
 {
   BOOL          memDebug = [cmdDefs boolForKey: @"Memory"];
@@ -4319,6 +4406,24 @@
       fclose(fptr);
     }
   excLast = (uint64_t)[self ecNotLeaked];
+
+  [self _ensureMemLogger];
+  if (nil != cmdMemoryLogger)
+    {
+      NS_DURING
+        {
+          [cmdMemoryLogger process: self
+                      didUseMemory: memLast
+                         notLeaked: excLast];
+        }
+      NS_HANDLER
+        {
+          [self cmdWarn:
+            @"Exception logging memory usage to bundle: %@",
+           localException];
+        }
+      NS_ENDHANDLER
+    }
 
   /* Do initial population so we can work immediately.
    */

Modified: libs/ec/trunk/GNUmakefile
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/GNUmakefile?rev=38798&r1=38797&r2=38798&view=diff
==============================================================================
--- libs/ec/trunk/GNUmakefile   (original)
+++ libs/ec/trunk/GNUmakefile   Wed Jul 15 10:41:14 2015
@@ -60,7 +60,7 @@
        EcProcess.h \
        EcTest.h \
        EcUserDefaults.h \
-
+       EcMemoryLogger.h
 
 TOOL_NAME = \
        Command \


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to