mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-19 04:06:43 -04:00
synchronizing filesystem component and making open/read/seek/close limited direct calls, reduced default max read buffer in turn. this should give better performance when reading many small files; made fs.close direct without limit to get rid of the ugly file handle gc workaround involving a timer
This commit is contained in:
parent
02827f69b7
commit
83860523a7
@ -20,13 +20,15 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
@Callback(direct = true)
|
||||
def getLabel(context: Context, args: Arguments): Array[AnyRef] = label match {
|
||||
case value: Label => result(label.getLabel)
|
||||
case _ => null
|
||||
def getLabel(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
label match {
|
||||
case value: Label => result(label.getLabel)
|
||||
case _ => null
|
||||
}
|
||||
}
|
||||
|
||||
@Callback
|
||||
def setLabel(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def setLabel(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
if (label == null) throw new Exception("filesystem does not support labeling")
|
||||
if (args.checkAny(0) == null) label.setLabel(null)
|
||||
else label.setLabel(args.checkString(0))
|
||||
@ -34,12 +36,12 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def isReadOnly(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def isReadOnly(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.isReadOnly)
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def spaceTotal(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def spaceTotal(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
val space = fileSystem.spaceTotal
|
||||
if (space < 0)
|
||||
Array("unlimited")
|
||||
@ -48,32 +50,32 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def spaceUsed(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def spaceUsed(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.spaceUsed)
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def exists(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def exists(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.exists(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def size(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def size(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.size(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def isDirectory(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def isDirectory(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.isDirectory(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback(direct = true)
|
||||
def lastModified(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def lastModified(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.lastModified(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback
|
||||
def list(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def list(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
Option(fileSystem.list(clean(args.checkString(0)))) match {
|
||||
case Some(list) => Array(list)
|
||||
case _ => null
|
||||
@ -81,26 +83,26 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
|
||||
@Callback
|
||||
def makeDirectory(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def makeDirectory(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
def recurse(path: String): Boolean = !fileSystem.exists(path) && (fileSystem.makeDirectory(path) ||
|
||||
(recurse(path.split("/").dropRight(1).mkString("/")) && fileSystem.makeDirectory(path)))
|
||||
result(recurse(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback
|
||||
def remove(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def remove(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
def recurse(parent: String): Boolean = (!fileSystem.isDirectory(parent) ||
|
||||
fileSystem.list(parent).forall(child => recurse(parent + "/" + child))) && fileSystem.delete(parent)
|
||||
result(recurse(clean(args.checkString(0))))
|
||||
}
|
||||
|
||||
@Callback
|
||||
def rename(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def rename(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
result(fileSystem.rename(clean(args.checkString(0)), clean(args.checkString(1))))
|
||||
}
|
||||
|
||||
@Callback
|
||||
def close(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
@Callback(direct = true)
|
||||
def close(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
val handle = args.checkInteger(0)
|
||||
Option(fileSystem.getHandle(handle)) match {
|
||||
case Some(file) =>
|
||||
@ -113,8 +115,8 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
null
|
||||
}
|
||||
|
||||
@Callback
|
||||
def open(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
@Callback(direct = true, limit = 4)
|
||||
def open(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
if (owners.get(context.node.address).fold(false)(_.size >= Settings.get.maxHandles)) {
|
||||
throw new IOException("too many open handles")
|
||||
}
|
||||
@ -127,8 +129,8 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
result(handle)
|
||||
}
|
||||
|
||||
@Callback
|
||||
def read(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
@Callback(direct = true, limit = 4)
|
||||
def read(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
val handle = args.checkInteger(0)
|
||||
val n = math.min(Settings.get.maxReadBuffer, math.max(0, args.checkInteger(1)))
|
||||
checkOwner(context.node.address, handle)
|
||||
@ -158,8 +160,8 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
}
|
||||
|
||||
@Callback
|
||||
def seek(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
@Callback(direct = true, limit = 4)
|
||||
def seek(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
val handle = args.checkInteger(0)
|
||||
val whence = args.checkString(1)
|
||||
val offset = args.checkInteger(2)
|
||||
@ -178,7 +180,7 @@ class FileSystem(val fileSystem: IFileSystem, var label: Label) extends ManagedC
|
||||
}
|
||||
|
||||
@Callback
|
||||
def write(context: Context, args: Arguments): Array[AnyRef] = {
|
||||
def write(context: Context, args: Arguments): Array[AnyRef] = fileSystem.synchronized {
|
||||
val handle = args.checkInteger(0)
|
||||
val value = args.checkByteArray(1)
|
||||
if (!node.tryChangeBuffer(-Settings.get.hddWriteCost * value.length)) {
|
||||
|
@ -3,7 +3,7 @@ local unicode = require("unicode")
|
||||
|
||||
local filesystem, fileStream = {}, {}
|
||||
local isAutorunEnabled = true
|
||||
local mtab = {children={}, links={}}
|
||||
local mtab = {name="", children={}, links={}}
|
||||
|
||||
local function segments(path)
|
||||
path = path:gsub("\\", "/")
|
||||
@ -472,18 +472,9 @@ function filesystem.open(path, mode)
|
||||
|
||||
local stream = {fs = node.fs, handle = handle}
|
||||
|
||||
-- stream:close does a syscall, which yields, and that's not possible in
|
||||
-- the __gc metamethod. So we start a timer to do the yield/cleanup.
|
||||
local function cleanup(self)
|
||||
if not self.handle then return end
|
||||
-- save non-gc'ed values as upvalues
|
||||
local fs = self.fs
|
||||
local handle = self.handle
|
||||
local function close()
|
||||
fs.close(handle)
|
||||
end
|
||||
-- Required locally because this is a bootstrapped file.
|
||||
require("event").timer(0, close)
|
||||
self.fs.close(self.handle)
|
||||
end
|
||||
local metatable = {__index = fileStream,
|
||||
__gc = cleanup,
|
||||
|
@ -8,7 +8,6 @@ local loaded = {
|
||||
["_G"] = _G,
|
||||
["bit32"] = bit32,
|
||||
["coroutine"] = coroutine,
|
||||
["io"] = io,
|
||||
["math"] = math,
|
||||
["os"] = os,
|
||||
["package"] = package,
|
||||
|
@ -588,7 +588,7 @@ opencomputers {
|
||||
# allocations regardless of the amount of RAM installed in the computer it
|
||||
# runs on. As a side effect this pretty much determines the read
|
||||
# performance of file systems.
|
||||
maxReadBuffer: 8192
|
||||
maxReadBuffer: 2048
|
||||
}
|
||||
|
||||
# Internet settings, security related.
|
||||
|
Loading…
x
Reference in New Issue
Block a user