Inceptum/launcher-gtk/src/main/kotlin/io/gitlab/jfronny/inceptum/gtk/util/Memory.kt

94 lines
3.4 KiB
Kotlin

package io.gitlab.jfronny.inceptum.gtk.util
import io.gitlab.jfronny.commons.OSUtils
import io.gitlab.jfronny.inceptum.common.Utils
import java.io.IOException
import java.nio.file.Files
import java.nio.file.Path
import java.util.regex.Pattern
object Memory {
const val KB: Long = 1024
const val MB = KB * 1024
const val GB = MB * 1024
private val impl = when (OSUtils.TYPE) {
OSUtils.Type.LINUX -> LinuxMI
OSUtils.Type.WINDOWS -> WindowsMI
OSUtils.Type.MAC_OS -> MacOsMI
}
private val totalMemory by lazy { impl.getTotalMemory() }
val maxMBForInstance: Long get() = (totalMemory / MB - 1024).coerceAtLeast(1024)
private interface MI {
fun getTotalMemory(): Long
}
private object LinuxMI : MI {
override fun getTotalMemory(): Long {
try {
Files.lines(Path.of("/proc/meminfo")).use { stream ->
val memTotal = stream
.filter { s: String -> s.startsWith("MemTotal:") }
.map { s: String -> s.substring("MemTotal:".length) }
.map { obj: String -> obj.trim { it <= ' ' } }
.findFirst()
return if (memTotal.isPresent()) {
parseDecimalMemorySizeToBinary(memTotal.get())
} else {
Utils.LOGGER.error("Could not find total memory")
32 * GB
}
}
} catch (e: IOException) {
Utils.LOGGER.error("Could not get total memory", e)
return 32 * GB
}
}
// Taken from oshi
private val BYTES_PATTERN = Pattern.compile("(\\d+) ?([kKMGT]?B?).*")
private val WHITESPACES = Pattern.compile("\\s+")
private fun parseDecimalMemorySizeToBinary(size: String): Long {
var mem = WHITESPACES.split(size)
if (mem.size < 2) {
// If no spaces, use regexp
val matcher = BYTES_PATTERN.matcher(size.trim { it <= ' ' })
if (matcher.find() && matcher.groupCount() == 2) {
mem = arrayOfNulls(2)
mem[0] = matcher.group(1)
mem[1] = matcher.group(2)
}
}
var capacity = parseLongOrDefault(mem[0], 0L)
if (mem.size == 2 && mem[1]!!.length > 1) {
when (mem[1]!![0]) {
'T' -> capacity = capacity shl 40
'G' -> capacity = capacity shl 30
'M' -> capacity = capacity shl 20
'K', 'k' -> capacity = capacity shl 10
else -> {}
}
}
return capacity
}
private fun parseLongOrDefault(s: String, defaultLong: Long): Long = try {
s.toLong()
} catch (e: NumberFormatException) {
defaultLong
}
}
private object WindowsMI : MI {
override fun getTotalMemory(): Long {
return 32 * GB // This is currently unsupported, but any implementations by Windows user using panama are welcome
}
}
private object MacOsMI : MI {
override fun getTotalMemory(): Long {
return 32 * GB // This is currently unsupported, but any implementations by MacOS user using panama are welcome
}
}
}