| # File src/library/base/makebasedb.R | |
| # Part of the R package, https://www.R-project.org | |
| # | |
| # Copyright (C) 1995-2012 The R Core Team | |
| # | |
| # This program is free software; you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation; either version 2 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # This program is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| # GNU General Public License for more details. | |
| # | |
| # A copy of the GNU General Public License is available at | |
| # https://www.R-project.org/Licenses/ | |
| local({ | |
| makeLazyLoadDB <- function(from, filebase, compress = TRUE, ascii = FALSE, | |
| variables) { | |
| envlist <- function(e) | |
| .Internal(getVarsFromFrame(ls(e, all = TRUE), e, FALSE)) | |
| envtable <- function() { | |
| idx <- 0 | |
| envs <- NULL | |
| enames <- character(0) | |
| find <- function(v, keys, vals) { | |
| for (i in seq_along(keys)) | |
| if (identical(v, keys[[i]])) | |
| return(vals[i]) | |
| NULL | |
| } | |
| getname <- function(e) find(e, envs, enames) | |
| getenv <- function(n) find(n, enames, envs) | |
| insert <- function(e) { | |
| idx <<- idx + 1 | |
| name <- paste("env", idx, sep="::") | |
| envs <<- c(e, envs) | |
| enames <<- c(name, enames) | |
| name | |
| } | |
| list(insert = insert, getenv = getenv, getname = getname) | |
| } | |
| lazyLoadDBinsertValue <- function(value, file, ascii, compress, hook) | |
| .Internal(lazyLoadDBinsertValue(value, file, ascii, compress, hook)) | |
| lazyLoadDBinsertListElement <- function(x, i, file, ascii, compress, hook) | |
| .Internal(lazyLoadDBinsertValue(x[[i]], file, ascii, compress, hook)) | |
| lazyLoadDBinsertVariable <- function(n, e, file, ascii, compress, hook) { | |
| x <- .Internal(getVarsFromFrame(n, e, FALSE)) | |
| .Internal(lazyLoadDBinsertValue(x[[1L]], file, ascii, compress, hook)) | |
| } | |
| mapfile <- paste(filebase, "rdx", sep = ".") | |
| datafile <- paste(filebase, "rdb", sep = ".") | |
| close(file(datafile, "w")) # truncate to zero | |
| table <- envtable() | |
| varenv <- new.env(hash = TRUE) | |
| envenv <- new.env(hash = TRUE) | |
| envhook <- function(e) { | |
| if (is.environment(e)) { | |
| name <- table$getname(e) | |
| if (is.null(name)) { | |
| name <- table$insert(e) | |
| data <- list(bindings = envlist(e), | |
| enclos = parent.env(e)) | |
| key <- lazyLoadDBinsertValue(data, datafile, ascii, | |
| compress, envhook) | |
| assign(name, key, envir = envenv) | |
| } | |
| name | |
| } | |
| } | |
| if (is.environment(from)) { | |
| if (! missing(variables)) | |
| vars <- variables | |
| else vars <- ls(from, all = TRUE) | |
| } | |
| else if (is.list(from)) { | |
| vars <- names(from) | |
| if (length(vars) != length(from) || any(nchar(vars) == 0)) | |
| stop("source list must have names for all elements") | |
| } | |
| else stop("source must be an environment or a list"); | |
| for (i in seq_along(vars)) { | |
| if (is.environment(from)) | |
| key <- lazyLoadDBinsertVariable(vars[i], from, datafile, | |
| ascii, compress, envhook) | |
| else key <- lazyLoadDBinsertListElement(from, i, datafile, ascii, | |
| compress, envhook) | |
| assign(vars[i], key, envir = varenv) | |
| } | |
| vals <- lapply(vars, get, envir = varenv, inherits = FALSE) | |
| names(vals) <- vars | |
| rvars <- ls(envenv, all = TRUE) | |
| rvals <- lapply(rvars, get, envir = envenv, inherits = FALSE) | |
| names(rvals) <- rvars | |
| val <- list(variables = vals, references = rvals, | |
| compressed = compress) | |
| saveRDS(val, mapfile) | |
| } | |
| omit <- c(".Last.value", ".AutoloadEnv", ".BaseNamespaceEnv", | |
| ".Device", ".Devices", ".Machine", ".Options", ".Platform") | |
| if (length(search()[search()!="Autoloads"]) != 2) | |
| stop("start R with NO packages loaded to create the data base") | |
| baseFileBase <- file.path(.Library,"base","R","base") | |
| if (file.info(baseFileBase)["size"] < 20000) # crude heuristic | |
| stop("may already be using lazy loading on base"); | |
| basevars <- ls(baseenv(), all.names=TRUE) | |
| prims <- basevars[sapply(basevars, function(n) is.primitive(get(n, baseenv())))] | |
| basevars <- basevars[! basevars %in% c(omit, prims)] | |
| makeLazyLoadDB(baseenv(), baseFileBase, variables = basevars) | |
| }) |