blob: 893397c9b28cf73adb76f1799b46d78314f009a7 [file] [log] [blame]
# 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)
})