Skip to content

Commit 8b44087

Browse files
author
Rob Austin
committed
cleanup tests and added LockCheck and test cases
1 parent e2a420b commit 8b44087

3 files changed

Lines changed: 168 additions & 5 deletions

File tree

affinity/src/main/java/net/openhft/affinity/Affinity.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@
2121
import org.slf4j.Logger;
2222
import org.slf4j.LoggerFactory;
2323

24+
import java.io.IOException;
2425
import java.io.PrintWriter;
2526
import java.io.StringWriter;
2627
import java.lang.reflect.Field;
2728
import java.util.BitSet;
2829

2930
/**
30-
* Library to wrap low level JNI or JNA calls. Can be called without needing to know the actual implementation used.
31+
* Library to wrap low level JNI or JNA calls. Can be called without needing to know the actual
32+
* implementation used.
3133
*
3234
* @author peter.lawrey
3335
*/
@@ -37,6 +39,7 @@ public enum Affinity {
3739
@NotNull
3840
private static final IAffinity AFFINITY_IMPL;
3941
private static Boolean JNAAvailable;
42+
private static LockCheck LOCK_CHECK = new LockCheck();
4043

4144
static {
4245
String osName = System.getProperty("os.name");
@@ -153,16 +156,16 @@ public static BitSet getAffinity() {
153156
return AFFINITY_IMPL.getAffinity();
154157
}
155158

159+
public static void setAffinity(final BitSet affinity) {
160+
AFFINITY_IMPL.setAffinity(affinity);
161+
}
162+
156163
public static void setAffinity(int cpu) {
157164
BitSet affinity = new BitSet(Runtime.getRuntime().availableProcessors());
158165
affinity.set(cpu);
159166
setAffinity(affinity);
160167
}
161168

162-
public static void setAffinity(final BitSet affinity) {
163-
AFFINITY_IMPL.setAffinity(affinity);
164-
}
165-
166169
public static int getCpu() {
167170
return AFFINITY_IMPL.getCpu();
168171
}
@@ -195,7 +198,20 @@ public static boolean isJNAAvailable() {
195198
return JNAAvailable;
196199
}
197200

201+
public static long getPID() {
202+
String processName =
203+
java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
204+
return Long.parseLong(processName.split("@")[0]);
205+
}
206+
198207
public static AffinityLock acquireLock() {
208+
if (LockCheck.IS_LINUX)
209+
210+
try {
211+
LOCK_CHECK.isCoreAlreadyAssigned(getCpu(), getPID());
212+
} catch (IOException e) {
213+
// unknown state
214+
}
199215
return isNonForkingAffinityAvailable() ? NonForkingAffinityLock.acquireLock() : AffinityLock.acquireLock();
200216
}
201217

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package net.openhft.affinity;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
5+
import java.io.*;
6+
import java.text.SimpleDateFormat;
7+
import java.util.Date;
8+
import java.util.function.Supplier;
9+
10+
11+
/**
12+
* @author Rob Austin.
13+
*/
14+
public class LockCheck {
15+
16+
static final String TMP = System.getProperty("java.io.tmpdir");
17+
public static final String TARGET = System.getProperty("project.build.directory", findTarget());
18+
private static final String OS = System.getProperty("os.name").toLowerCase();
19+
static final boolean IS_LINUX = OS.startsWith("linux");
20+
private ThreadLocal<SimpleDateFormat> df = ThreadLocal.withInitial(new Supplier() {
21+
@Override
22+
public Object get() {
23+
return new SimpleDateFormat("yyyy.MM" + ".dd 'at' HH:mm:ss z");
24+
}
25+
});
26+
27+
private static String findTarget() {
28+
for (File dir = new File(System.getProperty("user.dir")); dir != null; dir = dir.getParentFile()) {
29+
File target = new File(dir, "target");
30+
if (target.exists())
31+
return target.getAbsolutePath();
32+
}
33+
return TMP + "/target";
34+
}
35+
36+
/**
37+
* stores the process id for a give pid
38+
*
39+
* @param core
40+
* @param processID
41+
* @return
42+
* @throws IOException
43+
*/
44+
public boolean isCoreAlreadyAssigned(int core, long processID) throws IOException {
45+
46+
File file = new File(tmpDir(), "core-" + core);
47+
boolean exists = file.exists();
48+
49+
if (!exists) {
50+
// create a lock file
51+
storePid(processID, file);
52+
return true;
53+
} else {
54+
int currentProcess = getPid(file);
55+
if (!isProcessRunning(currentProcess)) {
56+
replacePid(processID, file);
57+
return true;
58+
}
59+
return false;
60+
}
61+
62+
}
63+
64+
private void replacePid(long processID, File file) throws IOException {
65+
file.delete();
66+
storePid(processID, file);
67+
}
68+
69+
boolean isProcessRunning(long pid) {
70+
if (IS_LINUX)
71+
return new File("/proc/" + pid).exists();
72+
else
73+
throw new UnsupportedOperationException("this is only supported on LINUX");
74+
}
75+
76+
/**
77+
* stores the pid in a file, named by the core, the pid is written to the file with the date
78+
* below
79+
*
80+
* @param processID
81+
* @param coreFile
82+
* @throws IOException
83+
*/
84+
private void storePid(long processID, File coreFile) throws IOException {
85+
try (Writer writer = new BufferedWriter(new OutputStreamWriter(
86+
new FileOutputStream(coreFile), "utf-8"))) {
87+
String processIDStr = Long.toString(processID);
88+
writer.write(processIDStr + "\n" + df.get().format(new Date()));
89+
}
90+
}
91+
92+
int getPid(int core) throws IOException {
93+
return getPid(new File(tmpDir(), "core-" + core));
94+
}
95+
96+
private int getPid(@NotNull File coreFile) throws IOException {
97+
98+
try (LineNumberReader reader = new LineNumberReader(
99+
new BufferedReader(new InputStreamReader(new FileInputStream(coreFile), "utf-8")))) {
100+
String s = reader.readLine().trim();
101+
System.out.println("" + s);
102+
return Integer.parseInt(s);
103+
}
104+
}
105+
106+
private File tmpDir() {
107+
final File tempDir = new File(System.getProperty("java.io.tmpdir"));
108+
109+
if (!tempDir.exists())
110+
tempDir.mkdirs();
111+
112+
return tempDir;
113+
}
114+
115+
116+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package net.openhft.affinity;
2+
3+
import org.junit.Assert;
4+
import org.junit.Test;
5+
6+
import java.io.IOException;
7+
8+
/**
9+
* @author Rob Austin.
10+
*/
11+
public class LockCheckTest {
12+
13+
private static final int CORE = 1111;
14+
private static final int PROCESS_ID = 2222;
15+
16+
@Test
17+
public void test() throws IOException {
18+
LockCheck lockCheck = new LockCheck();
19+
lockCheck.isCoreAlreadyAssigned(CORE, PROCESS_ID);
20+
Assert.assertEquals(PROCESS_ID, lockCheck.getPid(CORE));
21+
}
22+
23+
@Test
24+
public void testPidOnLinux() {
25+
final LockCheck lockCheck = new LockCheck();
26+
27+
if (LockCheck.IS_LINUX)
28+
Assert.assertTrue(lockCheck.isProcessRunning(Affinity.getPID()));
29+
30+
}
31+
}

0 commit comments

Comments
 (0)