]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.nativemem/src/org/simantics/nativemem/NativeMem.java
Rudimentary Linux and MacOSX support for org.simantics.nativemem
[simantics/platform.git] / bundles / org.simantics.nativemem / src / org / simantics / nativemem / NativeMem.java
index c902214ac9bcee3711f747bbb31451100719a2f8..bf761380312de52f69e32e574a3dc4dc16ab9482 100644 (file)
@@ -1,9 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
 package org.simantics.nativemem;
 
+import java.lang.reflect.InvocationTargetException;
+
 import org.simantics.nativemem.internal.Arch;
+import org.simantics.nativemem.internal.DummyProcessMemoryInfo;
+import org.simantics.nativemem.internal.CMemoryInfo;
 import org.simantics.nativemem.internal.OS;
-import org.simantics.nativemem.internal.Psapi32;
-import org.simantics.nativemem.internal.Psapi64;
+import org.simantics.nativemem.internal.Resource;
+import org.simantics.nativemem.internal.Resource32;
+import org.simantics.nativemem.internal.Resource64;
+import org.simantics.nativemem.internal.linux.Stat;
+import org.simantics.nativemem.internal.win.ProcessMemoryCounters;
+import org.simantics.nativemem.internal.win.Psapi32;
+import org.simantics.nativemem.internal.win.Psapi64;
 
 import com.sun.jna.platform.win32.Kernel32;
 import com.sun.jna.platform.win32.WinNT.HANDLE;
@@ -17,39 +37,107 @@ public class NativeMem {
      *            create a new structure
      * @return the result structure
      */
-    public static ProcessMemoryCounters getMemoryCounters(ProcessMemoryCounters out) {
-        if (out == null)
-            out = new ProcessMemoryCounters();
-
-        OS os = OS.calculate();
-        Arch arch = Arch.calculate();
-        switch (os) {
-        case WINDOWS: {
-            HANDLE proc = Kernel32.INSTANCE.GetCurrentProcess();
-            switch (arch) {
-            case X86: {
-                Psapi32.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi32.PROCESS_MEMORY_COUNTERS_EX();
-                boolean ok = Psapi32.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());
-                if (ok)
-                    pmem.writeTo(out);
-                return out;
-            }
-
-            case X86_64: {
-                Psapi64.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi64.PROCESS_MEMORY_COUNTERS_EX();
-                boolean ok = Psapi64.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());
-                if (ok)
-                    pmem.writeTo(out);
-                return out;
-            }
-
-            default:
-                throw new UnsupportedOperationException("Architecture " + arch + " not supported on operating system " + os);
-            }
+    public static ProcessMemoryInfo getMemoryInfo(ProcessMemoryInfo out) {
+        switch (OS.calculate()) {
+        case WINDOWS:
+            return getProcessMemoryCounters(out);
+
+        case APPLE:
+            return getCMemoryInfo(out);
+
+        case LINUX: {
+            CMemoryInfo info = getCMemoryInfo(out);
+            info.peakRSS *= 1024L;
+            getCurrentRSS(info);
+            return info;
+        }
+
+        default:
+            return DummyProcessMemoryInfo.INSTANCE;
+        }
+    }
+
+    private static ProcessMemoryCounters getProcessMemoryCounters(ProcessMemoryInfo out) {
+        ProcessMemoryCounters counters = castOrCreate(out, ProcessMemoryCounters.class);
+        HANDLE proc = Kernel32.INSTANCE.GetCurrentProcess();
+        switch (Arch.calculate()) {
+        case X86: {
+            Psapi32.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi32.PROCESS_MEMORY_COUNTERS_EX();
+            boolean ok = Psapi32.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());
+            if (ok)
+                pmem.writeTo(counters);
+            return counters;
+        }
+
+        case X86_64: {
+            Psapi64.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi64.PROCESS_MEMORY_COUNTERS_EX();
+            boolean ok = Psapi64.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());
+            if (ok)
+                pmem.writeTo(counters);
+            return counters;
+        }
+
+        default:
+            return counters;
+        }
+    }
+
+    private static CMemoryInfo getCMemoryInfo(ProcessMemoryInfo out) {
+        CMemoryInfo info = castOrCreate(out, CMemoryInfo.class);
+
+        switch (Arch.calculate()) {
+        case X86: {
+            Resource32.Rusage rusage = new Resource32.Rusage();
+            int ok = Resource32.INSTANCE.getrusage(Resource.RUSAGE_SELF, rusage);
+            if (ok == 0)
+                rusage.writeTo(info);
+            return info;
+        }
+
+        case X86_64: {
+            Resource64.Rusage rusage = new Resource64.Rusage();
+            int ok = Resource64.INSTANCE.getrusage(Resource.RUSAGE_SELF, rusage);
+            if (ok == 0)
+                rusage.writeTo(info);
+            return info;
+        }
+
+        default:
+            return info;
+        }
+    }
+
+    private static CMemoryInfo getCurrentRSS(ProcessMemoryInfo out) {
+        CMemoryInfo info = castOrCreate(out, CMemoryInfo.class);
+
+        switch (Arch.calculate()) {
+        case X86: {
+            long rss = Stat.getCurrentRSS(Resource32.INSTANCE);
+            if (rss >= 0)
+                info.currentRSS = rss;
+            return info;
+        }
+
+        case X86_64: {
+            long rss = Stat.getCurrentRSS(Resource64.INSTANCE);
+            if (rss >= 0)
+                info.currentRSS = rss;
+            return info;
         }
 
         default:
-            throw new UnsupportedOperationException("Operating system " + os + " not supported");
+            return info;
+        }
+    }
+
+    private static <T> T castOrCreate(Object o, Class<T> clazz) {
+        if (clazz.isInstance(o))
+            return clazz.cast(o);
+        try {
+            return clazz.getConstructor().newInstance();
+        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
+                | NoSuchMethodException | SecurityException e) {
+            throw new Error("Class " + clazz + " does not have a public parameterless constructor", e);
         }
     }