Skip to content
This repository was archived by the owner on Aug 5, 2024. It is now read-only.

Commit 91b8ba1

Browse files
committed
simplify native tor ready detection
1 parent 7e180ee commit 91b8ba1

1 file changed

Lines changed: 14 additions & 81 deletions

File tree

tor.native/src/main/kotlin/org/berndpruenster/netlayer/tor/NativeWatchObserver.kt

Lines changed: 14 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -35,103 +35,36 @@ various open source licenses (www.opensource.org).
3535
package org.berndpruenster.netlayer.tor
3636

3737
import java.io.File
38-
import java.nio.file.*
38+
import java.security.MessageDigest
3939
import java.util.concurrent.TimeUnit
4040

4141
/**
4242
* Watches to see if a particular file is changed
4343
*/
4444
class NativeWatchObserver(private val fileToWatch: File) : WriteObserver {
45-
private val watchService: WatchService
46-
private val key: WatchKey
47-
private val lastModified: Long
48-
private val length: Long
45+
private var lastDigest: ByteArray
46+
47+
private var messageDigestCreator: MessageDigest
4948

5049
init {
5150
if (!fileToWatch.exists()) {
5251
throw RuntimeException("$fileToWatch does not exist")
5352
}
5453

55-
lastModified = fileToWatch.lastModified()
56-
length = fileToWatch.length()
57-
58-
watchService = FileSystems.getDefault().newWatchService()
59-
// Note that poll depends on us only registering events that are of current
60-
// path
61-
if (OsType.current != OsType.MACOS) {
62-
key = fileToWatch.parentFile.toPath().register(watchService,
63-
StandardWatchEventKinds.ENTRY_CREATE,
64-
StandardWatchEventKinds.ENTRY_DELETE,
65-
StandardWatchEventKinds.ENTRY_MODIFY)
66-
} else {
67-
// Unfortunately the default watch service on MACOS is broken, it uses a
68-
// separate thread and really slow polling to detect file changes
69-
// rather than integrating with the OS. There is a hack to make it poll
70-
// faster which we can use for now. See
71-
// http://stackoverflow.com/questions/9588737/is-java-7-watchservice-slow-for-anyone-else
72-
key = fileToWatch.parentFile.toPath().register(watchService,
73-
arrayOf(StandardWatchEventKinds.ENTRY_CREATE,
74-
StandardWatchEventKinds.ENTRY_DELETE,
75-
StandardWatchEventKinds.ENTRY_MODIFY))
76-
}
54+
messageDigestCreator = MessageDigest.getInstance("SHA-256")
55+
lastDigest = messageDigestCreator.digest(fileToWatch.readBytes())
7756
}
7857

7958
override fun poll(timeout: Long, unit: TimeUnit): Boolean {
8059
var result = false
81-
try {
82-
var remainingTimeoutInNanos = unit.toNanos(timeout)
83-
while (remainingTimeoutInNanos > 0) {
84-
val startTimeInNanos = System.nanoTime()
85-
val receivedKey = watchService.poll(remainingTimeoutInNanos, TimeUnit.NANOSECONDS)
86-
val timeWaitedInNanos = System.nanoTime() - startTimeInNanos
87-
88-
if (receivedKey != null) {
89-
if (receivedKey != key) {
90-
throw RuntimeException("This really shouldn't have happened. EEK!" + receivedKey.toString())
91-
}
92-
93-
for (event in receivedKey.pollEvents()) {
94-
val kind = event.kind()
95-
96-
if (kind == StandardWatchEventKinds.OVERFLOW) {
97-
logger?.error("We got an overflow, there shouldn't have been enough activity to make that happen.")
98-
}
99-
100-
val changedEntry = event.context() as Path
101-
if (fileToWatch.toPath().endsWith(changedEntry)) {
102-
result = true
103-
return result
104-
}
105-
}
106-
107-
// In case we haven't yet gotten the event we are looking for we have
108-
// to reset in order to
109-
// receive any further notifications.
110-
if (!key.reset()) {
111-
logger?.error("The key became invalid which should not have happened.")
112-
}
113-
}
114-
115-
if (timeWaitedInNanos >= remainingTimeoutInNanos) {
116-
break
117-
}
118-
119-
remainingTimeoutInNanos -= timeWaitedInNanos
120-
}
121-
122-
// Even with the high sensitivity setting above for the MACOS the polling
123-
// still misses changes so I've added
124-
// a last modified check as a backup. Except I personally witnessed last
125-
// modified not returning a new value
126-
// value even when I saw the file change!!!! So I'm also adding in a
127-
// length check. Java really seems to
128-
// have an issue with the OS/X file system.
129-
result = (fileToWatch.lastModified() != lastModified) || (fileToWatch.length() != length)
130-
return result
131-
} finally {
132-
if (result) {
133-
watchService.close()
134-
}
60+
var remaining = unit.toMillis(timeout)
61+
while (remaining > 0 && !result) {
62+
Thread.sleep(250)
63+
result = !lastDigest.contentEquals(messageDigestCreator.digest(fileToWatch.readBytes()))
64+
65+
remaining -= 250
13566
}
67+
68+
return result
13669
}
13770
}

0 commit comments

Comments
 (0)