Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve and fix locking #3

Merged
merged 1 commit into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ plugins {


group = "com.wsl.symlinks"
version = "2024.1.0"
version = "2024.1.1"

// Configure project's dependencies
repositories {
Expand Down
68 changes: 46 additions & 22 deletions src/main/kotlin/com/wsl/symlinks/vfs/WslVirtualFileSystem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import com.intellij.openapi.vfs.impl.VirtualFileManagerImpl
import com.intellij.openapi.vfs.impl.local.LocalFileSystemImpl
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
import com.intellij.util.io.URLUtil
import com.jetbrains.rd.util.collections.SynchronizedMap
import java.io.*
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantLock
Expand Down Expand Up @@ -57,9 +59,16 @@ class MyLogger(category: String): DefaultLogger(category) {
val myResourceLock = ReentrantLock()

class WslSymlinksProvider(distro: String) {
val LOGGER = Logger.getInstance(WslSymlinksProvider::class.java)

private var process: Process
private var processReader: BufferedReader
private var processWriter: BufferedWriter
private val queue: LinkedBlockingQueue<AsyncValue> = LinkedBlockingQueue()
private val mapped: SynchronizedMap<String, AsyncValue> = SynchronizedMap()

class AsyncValue {
public val id = this.hashCode().toString()
public var request: String? = null
internal var value: String? = null
internal val condition = myResourceLock.newCondition()
Expand All @@ -72,24 +81,18 @@ class WslSymlinksProvider(distro: String) {
}
elapsed += 10
}
if (this.value == null) {
throw Error("failed to obtain file info for $request")
}
// if (this.value == null) {
// throw Error("failed to obtain file info for $request")
// }
return this.value
}
}

private var process: Process
private var processReader: BufferedReader
private var processWriter: BufferedWriter
private val queue: LinkedBlockingQueue<AsyncValue> = LinkedBlockingQueue()

init {
val bash = {}.javaClass.getResource("/files.sh")?.readText()!!
val location = "\\\\wsl.localhost\\$distro\\var\\tmp\\intellij-idea-wsl-symlinks.sh"
File(location).writeText(bash)
val builder = ProcessBuilder("wsl.exe", "-d", distro, "-e", "bash", "//var/tmp/intellij-idea-wsl-symlinks.sh")
val outQueue: LinkedBlockingQueue<AsyncValue> = LinkedBlockingQueue()
val process = builder.start()
this.process = process

Expand All @@ -102,28 +105,39 @@ class WslSymlinksProvider(distro: String) {
this.processWriter = writer;

process.onExit().whenComplete { t, u ->
LOGGER.error("process did exit", u)
this.process = builder.start()
this.processReader = BufferedReader(InputStreamReader(process.inputStream))
this.processWriter = BufferedWriter(OutputStreamWriter(process.outputStream));
}

thread {
while (true) {
val a = outQueue.take()
val line = this.processReader.readLine()
a.value = line
myResourceLock.withLock {
a.condition.signalAll()
try {
val line = this.processReader.readLine()
val (id, answer) = line.split(";")
val a = mapped[id]!!
a.value = answer
myResourceLock.withLock {
a.condition.signalAll()
}
mapped.remove(id)
} catch (e: Exception) {
LOGGER.error("failed to write", e)
}
}
}

thread {
while (true) {
val a = this.queue.take()
outQueue.add(a)
this.processWriter.write(a.request!!)
this.processWriter.flush()
try {
val a = this.queue.take()
mapped[a.id] = a
this.processWriter.write(a.request!!)
this.processWriter.flush()
} catch (e: Exception) {
LOGGER.error("failed to write", e)
}
}
}
}
Expand All @@ -137,12 +151,17 @@ class WslSymlinksProvider(distro: String) {
try {
val wslPath = file.getWSLPath()
val a = AsyncValue()
a.request = "read-symlink;${wslPath}\n"
a.request = "${a.id};read-symlink;${wslPath}\n"
this.queue.add(a)
while (a.getValue() == null) {
if (!queue.contains(a)) {
this.queue.add(a)
}
}
val link = a.getValue()
file.cachedWSLCanonicalPath = file.path.split("/").subList(0, 4).joinToString("/") + link
} catch (e: IOException) {
//
LOGGER.error("failed to getWSLCanonicalPath", e)
}
}

Expand All @@ -157,12 +176,17 @@ class WslSymlinksProvider(distro: String) {
try {
val path: String = file.path.replace("^//wsl\\$/[^/]+".toRegex(), "").replace("""^//wsl.localhost/[^/]+""".toRegex(), "")
val a = AsyncValue()
a.request = "is-symlink;${path}\n"
this.queue.add(a)
a.request = "${a.id};is-symlink;${path}\n"
while (a.getValue() == null) {
if (!queue.contains(a)) {
this.queue.add(a)
}
}
val isSymLink = a.getValue()
file.isSymlink = isSymLink.equals("true")
return isSymLink.equals("true")
} catch (e: Exception) {
LOGGER.error("failed isWslSymlink", e)
return false
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
]]></description>

<change-notes><![CDATA[

see <a href="https://github.com/patricklx/intellij-wsl-symlinks/blob/main/CHANGELOG.md">https://github.com/patricklx/intellij-wsl-symlinks/</a> for more
CHANGELOG_PLACEHOLDER
]]>
</change-notes>

Expand Down
10 changes: 6 additions & 4 deletions src/main/resources/files.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ while IFS='$\n' read line
do
IFS=';'
read -ra command <<< "$line"
type=${command[0]}
value=${command[1]}
id=${command[0]}
type=${command[1]}
value=${command[2]}
if [ "$type" == "is-symlink" ]; then
(test -L "$value") && echo "true" || echo "false"
(test -L "$value") && echo "$id;true" || echo "$id;false"
fi
if [ "$type" == "read-symlink" ]; then
readlink -f "$value"
link=$(readlink -f "$value")
echo "$id;$link"
fi
done
Loading