snowfall-internal.R
##*****************************************************************************
## Unordered internal helper functions.
##*****************************************************************************
##*****************************************************************************
## Helpers for managing the internal variables in the package namespace without
## awake the R CMD check for later R versions (which basically blaims many
## global assignings).
##
## The given solution has an advantage: only writing is affected. Reading of the
## objects can remain the same (thanks to Uwe Ligges for the tipp):
## reading: .sfOption$parallel
## writing: setOption("parallel", TRUE)
##*****************************************************************************
##*****************************************************************************
## Set an option in the snowfall option list.
## (Basically this is the setting of a list entry).
## key - character: object name
## val - object (everything is allowed, even NULL)
##*****************************************************************************
setOption <- function( key=NULL, val=NULL ) {
if( !is.null(key) && is.character( key ) ) {
option <- getVar( ".sfOption" ) ## Get from NS
option[[key]] <- val
setVar( ".sfOption", option ) ## Write to NS
return( invisible( TRUE ) )
}
stop( "key or val is NULL or key no string." )
}
##*****************************************************************************
## Get a specific variable from the snowfall namespace.
## var - character: object name
##*****************************************************************************
getVar <- function( var=NULL ) {
if( !is.null( var ) && is.character( var ) ) {
tmp <- try( getFromNamespace( var, "snowfall" ) )
if( inherits( tmp, "try-error" ) )
stop( paste( "Object", var, "not found in package" ) )
return( tmp )
}
stop( "var is NULL or not a string." )
}
##*****************************************************************************
## Write a specific variable to the snowfall namespace.
## var - character: object name
## arg - object (NULL allowed)
##*****************************************************************************
setVar <- function( var=NULL, arg=NULL ) {
if( !is.null( var ) && is.character( var ) ) {
assignInNamespace( var, arg, "snowfall" )
return( invisible( TRUE ) )
}
stop( "var is NULL or no character" );
}
##*****************************************************************************
## Replaces the tilde operator in file/directory names with the system
## depending counterpart.
## Used for configuration files mainly.
##
## PARAMETER: String directory
## RETURN: String directory replaced
##*****************************************************************************
fetchDirName <- function( dir ) {
return( gsub( "~", Sys.getenv( "HOME" ), dir ) )
}
##*****************************************************************************
## Is this snowfall session started through sfCluster?
## As a backward compatible solution there is only the LOCKFILE option open
## (as there is no default for it and setable through commandline).
##
## PARAMETER: -
## RETURN: Boolean True (running with sfCluster), False
##*****************************************************************************
startedWithSfCluster <- function() {
if( !exists( ".sfOption" ) )
return( FALSE )
else
return( !is.null( .sfOption$LOCKFILE ) && ( .sfOption$LOCKFILE != '' ) )
}
##*****************************************************************************
## Creates a directory (recursive) if needed and stops on failure.
##
## PARAMETER: String directory
## RETURN: Boolean success (true, on fail, execution stops)
##*****************************************************************************
dirCreateStop <- function( dir=NULL ) {
if( !is.null( dir ) && !file.exists( dir ) ) {
if( dir.create( dir, recursive=TRUE ) ) {
message( "Created directory: ", dir )
return( invisible( TRUE ) );
}
else
stop( "UNABLE to create directory: ", dir )
}
## Never reached.
return( invisible( FALSE ) );
}
##***************************************************************************
## Add a file (with absolute path) to remove list after sfStop().
## Used for save/restore-files.
##
## PARAMETER: file String abs. filepath
##***************************************************************************
addRestoreFile <- function( file=NULL ) {
if( !is.null( file ) )
if( is.vector( .sfOption$RESTOREFILES ) )
## Check if file is already in the list. If yes: no add.
if( length( grep( file, .sfOption$RESTOREFILES ) ) == 0 )
setOption( "RESTOREFILES", c( .sfOption$RESTOREFILES, file ) )
else
setOption( "RESTOREFILES", c( file ) )
debug( paste( "Added file for delete: ", file, "\n" ) )
return( invisible( length( .sfOption$RESTOREFILES ) ) )
}
##***************************************************************************
## Clean up save/restore files after successfull cluster shutdown.
##***************************************************************************
deleteRestoreFiles <- function() {
if( !is.null( .sfOption$RESTOREFILES ) ) {
## File names are absolute: just unlink all.
## lapply( .sfOption$RESTOREFILES, unlink )
for( file in .sfOption$RESTOREFILES ) {
## Does file exist?
if( file.exists( file ) ) {
if( unlink( file ) != 0 )
cat( "Unable to delete save/restore file:", file, "\n" )
else
cat( "Deleted save/restore file:", file, "\n" )
}
}
setOption( "RESTOREFILES", NULL )
}
}
##***************************************************************************
## Check if any element of a given list produced a stop or try-error.
## RETURN: Vector of logicals (true: ok, false: try error caught).
##***************************************************************************
checkTryErrorAny <- function( res ) {
return( sapply( res,
function( x ) {
if( inherits( x, "try-error" ) )
return( FALSE )
else
return( TRUE )
}
) )
}
##***************************************************************************
## Check if given argument is a function.
##***************************************************************************
checkFunction <- function( fun, stopOnError=TRUE ) {
return( TRUE )
state <- FALSE
try( if( !exists( as.character( substitute( fun ) ), inherit=TRUE ) ||
!is.function( fun ) ||
is.null( get( as.character( substitute( fun ) ), inherit=TRUE ) ) ||
!is.function( fun ) ) state <- TRUE )
if( !state ) {
## if( !is.function( fun ) ) cat( "FAIL SYMBOL\n" )
## if( !exists( as.character( substitute( fun ) ), inherit=TRUE ) ) cat( "FAIL EXIST\n" )
## if( is.null( get( as.character( substitute( fun ) ), inherit=TRUE ) ) ) cat( "FAIL GET\n" )
## if( !is.function( fun ) ) cat( "FAIL FUNCTION\n" )
if( stopOnError )
stop( paste( "Not a function in sfCluster function call: '", fun, "'" ) )
}
return( state )
}
errHandler <- function( ... ) {
print( "ERROR IN HANDLING STUFF!\n" )
}
##***************************************************************************
## Treat given three dot arguments as strings (for names listings
## like in sfExport).
## Ripped from buildin R function rm (by XXX).
## Returns list with names, stops on errors.
##***************************************************************************
fetchNames <- function( ... ) {
## Dot argument to list of characters: ripped from rm()...
dots <- match.call(expand.dots = FALSE)$...
if( length(dots) &&
!all( sapply( dots, function(x) is.symbol(x) || is.character(x) ) ) )
stop( "... must contain names or character strings in function ",
as.character( sys.call( -1 ) ) )
## end ripp.
return( sapply(dots, as.character) )
}
##***************************************************************************
## Create named list with all parameters from an function call.
## Idea somewhere from R-help (not tracked).
## This does not work if above env is not global env!
##***************************************************************************
getNamedArguments <- function( ... ) {
pars <- as.list( substitute( {...} )[-1] )
## pars <- as.list( substitute( {...} )[-1] )
## pars <- lapply( pars, function( x ) {
## if( is.atomic( x ) )
## return( x )
## else
## return( deparse( x ) )
## } )
return( pars )
}
##***************************************************************************
## Ensure a given filename contains an absolute path.
## Kind of silly and lame. But works in most cases.
##***************************************************************************
absFilePath <- function( file ) {
## If not starting with separator, path is most likely relative.
## Make it absolute then.
## On Windows absolute path can contain drive chars.
if( .Platform$OS.type == "windows" ) {
if( ( substr( file, 1, 1 ) != .Platform$file.sep ) &&
( substr( file, 2, 2 ) != ":" ) )
file <- file.path( getwd(), file )
}
else
if( substr( file, 1, 1 ) != .Platform$file.sep )
file <- file.path( getwd(), file )
return( file )
}
simpleAssign <- function( name=NULL, value ) {
message( paste( "simpleAssign called: ", name, "VAL:", value ) )
if( is.null( name ) || !is.character( name ) || ( nchar( name ) == 0 ) ) {
warning( "NULL assign on simpleAssign()" )
return( NULL )
}
else {
assign( name, value, env = globalenv() )
return( NULL )
}
}
##***************************************************************************
## Internal debug printer (globally disable using package variable DEBUG).
##***************************************************************************
debug <- function( txt='' ) {
if( DEBUG )
message( txt )
}
.onLoad <- function( lib, pkg ) {
## options( "error"=errHandler )
}