]> 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 cfccc215447af083bbf6e5d032464309185400da..bf761380312de52f69e32e574a3dc4dc16ab9482 100644 (file)
-package org.simantics.nativemem;\r
-\r
-import org.simantics.nativemem.internal.Arch;\r
-import org.simantics.nativemem.internal.OS;\r
-import org.simantics.nativemem.internal.Psapi32;\r
-import org.simantics.nativemem.internal.Psapi64;\r
-\r
-import com.sun.jna.platform.win32.Kernel32;\r
-import com.sun.jna.platform.win32.WinNT.HANDLE;\r
-\r
-\r
-public class NativeMem {\r
-\r
-    /**\r
-     * @param out\r
-     *            the structure to write the result into or <code>null</code> to\r
-     *            create a new structure\r
-     * @return the result structure\r
-     */\r
-    public static ProcessMemoryCounters getMemoryCounters(ProcessMemoryCounters out) {\r
-        if (out == null)\r
-            out = new ProcessMemoryCounters();\r
-\r
-        OS os = OS.calculate();\r
-        Arch arch = Arch.calculate();\r
-        switch (os) {\r
-        case WINDOWS: {\r
-            HANDLE proc = Kernel32.INSTANCE.GetCurrentProcess();\r
-            switch (arch) {\r
-            case X86: {\r
-                Psapi32.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi32.PROCESS_MEMORY_COUNTERS_EX();\r
-                boolean ok = Psapi32.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());\r
-                if (ok)\r
-                    pmem.writeTo(out);\r
-                return out;\r
-            }\r
-\r
-            case X86_64: {\r
-                Psapi64.PROCESS_MEMORY_COUNTERS_EX pmem = new Psapi64.PROCESS_MEMORY_COUNTERS_EX();\r
-                boolean ok = Psapi64.INSTANCE.GetProcessMemoryInfo(proc, pmem, pmem.size());\r
-                if (ok)\r
-                    pmem.writeTo(out);\r
-                return out;\r
-            }\r
-\r
-            default:\r
-                throw new UnsupportedOperationException("Architecture " + arch + " not supported on operating system " + os);\r
-            }\r
-        }\r
-\r
-        default:\r
-            throw new UnsupportedOperationException("Operating system " + os + " not supported");\r
-        }\r
-    }\r
-\r
+/*******************************************************************************
+ * 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.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;
+
+
+public class NativeMem {
+
+    /**
+     * @param out
+     *            the structure to write the result into or <code>null</code> to
+     *            create a new structure
+     * @return the result structure
+     */
+    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:
+            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);
+        }
+    }
+
 }
\ No newline at end of file