简短版

我将如何阻止对文件的访问,直到涉及该文件的读写过程的特定函数返回?


用例

我经常想要创建某种中央注册表,并且可能有多个R进程参与读取和写入该注册表(以“穷人的并行化”设置为例,其中不同的进程彼此独立地运行,除非尊重到注册表访问) .

我希望在开发过程的早期依赖于任何DBMS,例如SQLitePostgreSQLMongoDB等 . 即使我后来可能使用DBMS,基于文件系统的解决方案仍可能是一个方便的后备选项 . 因此,我很好奇我如何通过基本R功能实现它(充其量) .

I'm aware that having a lot of reads and writes to the file system in a parallel setting is not very efficient compared to DBMS solutions.

我在MS Windows 8.1(64位)上运行

我希望对此有更深入的了解

当两个或多个R进程同时尝试写入或读取文件时,究竟发生了什么?操作系统是否自动找出“访问顺序”并执行“排在第二”的进程等待或是否会触发错误,因为第一个进程可能会阻止文件访问?我怎么能阻止第二个进程返回错误,而是“等待”直到轮到他?

进程的共享工作空间

除了rredis包:在MS Windows上还有其他共享内存选项吗?

插图

注册表文件的路径:

path_registry <- file.path(tempdir(), "registry.rdata")

注册事件的示例函数:

registerEvent <- function(
    id=gsub("-| |:", "", Sys.time()), 
    values, 
    path_registry
) {
    if (!file.exists(path_registry)) {
        registry <- new.env()
        save(registry, file=path_registry)
    } else {
        load(path_registry)
    }

    message("Simulated additional runtime between reading and writing (5 seconds)")
    Sys.sleep(5)

    if (!exists(id, envir=registry, inherits=FALSE)) {
        assign(id, values, registry)
        save(registry, file=path_registry)
        message(sprintf("Registering with ID %s", id))
        out <- TRUE
    } else {
        message(sprintf("ID %s already registered", id))
        out <- FALSE
    }
    out
}

已注册的示例内容:

x <- new.env()
x$a <- TRUE
x$b <- letters[1:5]

请注意,内容通常是"nested",即无论如何RDBMS都不是真正的"useful",或者至少在写入数据库之前会涉及一些规范化步骤 . 这就是为什么我更喜欢 environment (唯一的变量ID和传递引用是可能的)而不是 list ,如果确实使用真正的DBMS,我宁愿转向NoSQL方法,例如MongoDB .

注册周期:

The actual calls might be spread over different processes, so there is a possibility of concurrent access atempts.

我希望有其他进程/调用"wait",直到__完成读写周期(没有触发错误)_1166833_读写周期 .

registerEvent(values=list(x_1=x, x_2=x), path_registry=path_registry)
registerEvent(values=list(x_1=x, x_2=x), path_registry=path_registry)
registerEvent(id="abcd", values=list(x_1=x, x_2=x), 
    path_registry=path_registry)
registerEvent(id="abcd", values=list(x_1=x, x_2=x), 
    path_registry=path_registry)

检查注册表内容:

load(path_registry)
ls(registry)