diff options
Diffstat (limited to 'kamon-system/src/main/scala/kamon/system/native/SigarLoader.scala')
-rw-r--r-- | kamon-system/src/main/scala/kamon/system/native/SigarLoader.scala | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/kamon-system/src/main/scala/kamon/system/native/SigarLoader.scala b/kamon-system/src/main/scala/kamon/system/native/SigarLoader.scala new file mode 100644 index 00000000..511a8ffc --- /dev/null +++ b/kamon-system/src/main/scala/kamon/system/native/SigarLoader.scala @@ -0,0 +1,82 @@ +package kamon.system.native + +import org.hyperic.sigar.Sigar +import org.hyperic.sigar.SigarProxy +import java.io._ +import scalax.io.JavaConverters._ +import scalax.io._ + +import Resource._ + +import scalax.file.Path +import java.util +import scala.collection.JavaConversions._ + +object SigarLoader { + val Version = "1.6.4" + val JavaLibraryPath = "java.library.path" + val TmpDir = "java.io.tmpdir" + val IndexFile = "/kamon/system/native/index" + val UsrPathField = "usr_paths" + + def init: SigarProxy = init(new File(System.getProperty(TmpDir))) + + private def init(baseTmp: File): SigarProxy = { + val tmpDir = createTmpDir(baseTmp) + for (lib ← loadIndex) copy(lib, tmpDir) + + attachToLibraryPath(tmpDir) + + try { + val sigar = new Sigar + sigar.getPid + sigar + } catch { + case t: Throwable ⇒ + throw new RuntimeException("Failed to load sigar", t) + } + } + + private val usrPathField = { + val usrPathField = classOf[ClassLoader].getDeclaredField(UsrPathField) + usrPathField.setAccessible(true) + usrPathField + } + + private def attachToLibraryPath(dir: File): Unit = { + val dirAbsolute = dir.getAbsolutePath + System.setProperty(JavaLibraryPath, newLibraryPath(dirAbsolute)) + var paths = usrPathField.get(null).asInstanceOf[Array[String]] + if (paths == null) paths = new Array[String](0) + for (path ← paths) if (path == dirAbsolute) return + val newPaths = util.Arrays.copyOf(paths, paths.length + 1) + newPaths(newPaths.length - 1) = dirAbsolute + usrPathField.set(null, newPaths) + } + + private def newLibraryPath(dirAbsolutePath: String): String = { + Option(System.getProperty(JavaLibraryPath)).fold(dirAbsolutePath)(oldValue ⇒ s"$dirAbsolutePath${File.pathSeparator}$oldValue") + } + + private def copy(lib: String, tmpDir: File) { + val dest: Path = Path(new File(tmpDir, lib)) + if (dest.exists) return + val currentFile = Resource.fromInputStream(classOf[Loader].getResourceAsStream("" + lib)) + currentFile.acquireFor(current ⇒ dest.doCopyFrom(current.asInput)) + } + + private def createTmpDir(baseTmp: File): File = { + val path = Path(new File(baseTmp, s"sigar-$Version")) + path.createDirectory(failIfExists = false) + path.jfile + } + + private def loadIndex: util.List[String] = { + val libs = new util.ArrayList[String] + val input = fromInputStream(classOf[Loader].getResourceAsStream(IndexFile)) + input.lines().foreach(libs.add) + libs + } +} + +class Loader
\ No newline at end of file |