1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
##*****************************************************************************
## 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

  ## 1.84-3 typo
  try( if( !exists( as.character( substitute( fun ) ), inherits=TRUE ) ||
          !is.function( fun ) ||
          is.null( get( as.character( substitute( fun ) ), inherits=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 {
    ## 1.84-4
    ## Problem: it is required to write to global env!
    ## Comment censored :)
#    assign( name, value, envir = globalenv() )
    assign( name, value, pos=sys.nframe() )

    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 )
}