Version of 1997/05/20
One of the chores of migrating from one platform to another is that S objects need to be migrated too. We provide two functions Dump.All and Undump.All to aid in this process. These functions are meant to be used as follows.
Suppose user Joe (userid joe) wishes to move objects from platform A to platform B. As a first step, Joe transfers all his files from A to B using some program like tar, preserving his directory structure. On platform A Joe invokes S from his home directory and executes the command
> Dump.All("/var/tmp")
The argument to the function is a directory which is assumed to have
enough space to hold all the dumped files. If everything goes
well, Joe will have a gzip'ed tar ball called joe.tar.gz in
the directory /var/tmp. Joe can now ftp the file
over to platform B in binary mode, say, to a directory
/tmp, invoke S from his home directory there and
type
> Undump.All("/tmp")
to restore all his objects.
Some assumptions.
We begin with our usual copyright.
<Copyright>= (U->) # # $Revision: 1.1 $ # # Copyright (C) 1996, B. Narasimhan (naras@stat.stanford.edu) # # 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. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
The two functions are, of course, Dump.All and UnDump.All.
<*>= <Copyright> <Dump.All function> <Undump.All function>
The function is quite easy to describe.
<Dump.All function>= (<-U)
Dump.All <- function(dest.dir="~", find.cmd="find")
{
<Set up dump names and map name>
data.dirs <- <List all data directories>
for (i in seq(along = data.dirs))
{
<Dump directory i>
<Update map file>
}
<Make tar.gz ball>
<Clean up>
<Print cautionary message>
}
Definesdata.dirs,dest.dir,Dump.All(links are to index).
I will be using all.dump.names to build up a string of all the dump filenames to be fed to the tar program. The correspondence between the dump files and the directories will be stored in the map file.
<Set up dump names and map name>= (<-U)
whoami <- unix("whoami")
all.dump.names <- ""
dump.map.name<- paste(whoami, "map", sep=".")
dump.map.pathname <- paste(dest.dir, dump.map.name, sep="/")
Definesall.dump.names,dump.map.name,dump.map.pathname,whoami(links are to index).
The list of data directories is best found by the find program.
<List all data directories>= (<-U) unix(paste(find.cmd, ". -name '.Data*' -type d -follow -print"))
On to dumping S objects. Let us tell the user what is going on.
<Dump directory i>= (<-U) [D->]
print(paste("Processing", data.dirs[i]))
Since many people could be doing this at the same time, we want to keep the dump file names unique. So we'll use joe.Dump.1, joe.Dump.2 etc., for the dump file names. Also we dump the objects to the file in the specified destination directory.
<Dump directory i>+= (<-U) [<-D->] dump.name <- paste(whoami, "Dump", i, sep=".") attach(data.dirs[i]) data.dump(objects(2), file = paste(dest.dir, dump.name, sep="/")) detach(data.dirs[i])
Definesdump.name(links are to index).
After a directory is done, we inform the user and update our string of dump names. We also add an entry to the map file.
<Dump directory i>+= (<-U) [<-D]
print(paste("Wrote", paste(dest.dir, dump.name, sep="/")))
all.dump.names <- paste(all.dump.names, dump.name)
The map file needs to be updated to reflect the correspondence between directories and dumps.
<Update map file>= (<-U)
unix(paste("echo", dump.name, data.dirs[i], ">>", dump.map.pathname))
Now we are ready to make our tar ball. With GNU tar, the following could be done in one step since GNU tar can compress and decompress. We'll do it the traditional way.
<Make tar.gz ball>= (<-U)
tar.name <- paste(whoami, "tar", sep=".")
unix(paste("cd", dest.dir, "; tar -cvf", tar.name, all.dump.names,
dump.map.name))
unix(paste("cd", dest.dir, "; gzip", tar.name))
Definestar.name(links are to index).
We can now remove all the dump files and the map file.
<Clean up>= (<-U)
unix(paste("cd", dest.dir, "; rm", all.dump.names, dump.map.name))
<Print cautionary message>= (<-U)
print("Warning: Before relying completely on the dumps")
print(" make sure that ")
print(" 1) no errors occured AT ALL")
print(" 2) you test the objects on the other system")
print(" before deleting the .Data directories on the current system.")
print("Dumping finished. You can now ftp the file ")
print(paste(" ", tar.name, ".gz", sep=""))
print("to the other machine. Be sure to use a binary transfer.")
return("")
We just have to undo what we did. This is far easier.
<Undump.All function>= (<-U)
Undump.All <- function(src.dir)
{
<Find and explode tar.gz ball>
<Find map name>
<Read in map file>
for (i in seq(along = map$dump.names))
{
<Prepare directory of interest>
<Attach the directory at head of list>
<Restore dump>
<Detach directory>
print(paste("Restored objects in", map$dump.dirnames[i]))
}
return("Undump.All finished.")
}
Definessrc.dir,Undump.All(links are to index).
To explode the tar ball, we run a unix command.
<Find and explode tar.gz ball>= (<-U)
whoami <- unix("whoami")
tar.gz.name <- paste(whoami,"tar.gz", sep=".")
unix(paste("cd", src.dir, "; gunzip -c", tar.gz.name, "| tar -xf -"))
Definestar.gz.name(links are to index).
The map name is userid.map.
<Find map name>= (<-U) map.name <- paste(whoami, "map", sep=".")
Definesmap.name(links are to index).
The map file contains two columns, a dump file name and the directory of which it is the dump.
<Read in map file>= (<-U)
map <- scan(paste(src.dir, map.name, sep="/"),
what = list(dump.names="", dump.dirnames=""))
Definesmap(links are to index).
Since we have assumed the user transferred all his files first, the .Data directories, though unusable, will exist. Time to get rid of objects in that directory.
<Prepare directory of interest>= (<-U)
unix(paste("cd", map$dump.dirnames[i], "; rm -rf *"))
The rest of the code is self-explanatory.
<Attach the directory at head of list>= (<-U)
attach(map$dump.dirnames[i])
detach(".Data")
<Restore dump>= (<-U) data.restore(paste(src.dir, map$dump.names[i], sep="/"))
<Detach directory>= (<-U)
attach(".Data")
detach(map$dump.dirnames[i])