.packageName <- "taskPR"
.First.lib <- function (lib, pkg) {
    library.dynam("taskPR", pkg, lib)
    if (length(system("lamnodes", TRUE, TRUE)) == 0) {
      if (interactive()) {
        print("The LAM/MPI daemon does not appear to be running.", quote=FALSE)
		print("If you want the ability to spawn worker processes,", quote=FALSE)
        print("please use the lamboot command to start the daemon.", quote=FALSE)
        print("(From inside R, use the command 'system(\"lamboot\")')", quote=FALSE)
      }
    }
}
                                                                                
.Last.lib <- function(libpath){
    library.dynam.unload("taskPR", libpath)
}

StartPE <- function(num = 2, port = 32000, verbose=0, spawn=TRUE) {
    if (spawn) {
		script = system.file("exec", "pRBatch.R", package="taskPR")
		arg = c("--no-save", "CMD", "BATCH", script, "NULL")
		host = Sys.info()[names(Sys.info()) == "nodename"]
		prog = file.path(R.home(), "bin", "R")
		str(arg)
		ret = 0
		.C("R_SpawnMPIProcesses", as.character(prog), as.integer(num),
			as.character(arg), as.integer(ret), PACKAGE="taskPR")
		if (ret < 0) error("Processing spawning via MPI failed.  Startup aborted.")
	}
    s = 0 * (1:num)
	# .C("ExtInit", PACKAGE="base")
	sock = .Call("OpenSocketAndListen", port, TRUE, num, PACKAGE="taskPR");
    for (i in 1:num) {
		if (spawn) {
			.C("NotifySpawnedMPIProcesses", as.character(host),
					as.integer(i-1), PACKAGE="taskPR")
		}
		s[i] = .Call("AcceptConnFromSocket", sock, PACKAGE="taskPR")
    }
    PE.WorkerConnections <- s
    if (verbose > 0) {
        .Call("EnableVerboseParallelExecution", num, verbose + 1, sys.frame(1),
				PACKAGE="taskPR");
    } else {
        .Call("EnableParallelExecution", num, sys.frame(1), PACKAGE="taskPR")
    }
    return(s)
}

PE <- function(x, global=FALSE) {
	.Call("CallPE", substitute(x), global, rho=sys.frame(-1),
			PACKAGE="taskPR")
}
POBJ <- function(x) {
	name = deparse(substitute(x))
		
	.Call("CallPOBJ", as.symbol(name), rho=sys.frame(-1),
		PACKAGE="taskPR")
}

StopPE <- function() .Call("DisableParallelExecution", PACKAGE="taskPR")
StartWorker <- function(host = "localhost", port=32000, retries=2, sleeptime=1, quiet=TRUE) {
	# Note: All variables which need to survive the setVar/unserialize call have
	# "PRW" (Parallel R Worker) prepended to them.

	# Timeout is set at 1 hour.  Some applications may need to change this.
	options(timeout=3600)
	for (i in 1:(retries + 1)) {
		PRWcon = try( socketConnection(host, port, block = TRUE, open="a+b") )
		if (inherits(PRWcon, "try-error")) Sys.sleep(eval(sleeptime))
		else break
	}

	while (1 == 1) {
		PRWglobal = 0
		PRWinputs = "PRWinputs"
		if (!quiet) print("Waiting for job")
		NumberOfInputs = readBin(PRWcon, "integer")
		if (NumberOfInputs == -1) {
			print("Received exit signal.")
			return(0)
		}
		if (NumberOfInputs == -2) {
			print("Received global execute signal.")
			PRWglobal = 1
			NumberOfInputs = readBin(PRWcon, "integer")
		}

		if (!quiet) {
			mesg = paste("Receiving job with", NumberOfInputs, "inputs:")
			print(mesg)
		}
		if (NumberOfInputs != 0)
			for (PRWi in 1:NumberOfInputs) {
				LengthOfString = readBin(PRWcon, "integer")
				PRWname = readBin(PRWcon, "character", 1, LengthOfString)
				PRWinputs = c(PRWinputs, PRWname)
				if (!quiet) {
					PRWmesg = paste("Receiving input '", PRWname, "' :", sep="")
					print(PRWmesg)
				}
				if (exists(PRWname)) rm(list=PRWname)

				# Unserialize the inputs directly into the variables instead
				# of going through a setVar call to try to reduce memory
				# usage.  I do not know any other reason for or against
				# either this method or the previous method.
				PRWexpr = paste(PRWname, "<- try( unserialize(PRWcon) )")
				eval(parse(text=PRWexpr))
			}

		# Removed code to recovered from a unserialization failure.
		# It should never happen in a non-repeatable way without a failure
		# in the lower level networking.

		LengthOfString = readBin(PRWcon, "integer")
		PRWOutputName = readBin(PRWcon, "character", 1, LengthOfString)
		
		if (!quiet) print("Receiving expression:")
		PRWexpr = unserialize(PRWcon)
		if (!quiet) print(PRWexpr)
		answer = try(eval(PRWexpr))
		rm(list=PRWinputs, envir=parent.frame())
		t = .Call("R_serialize", answer, NULL, FALSE, NULL, PACKAGE="base")
		if (!quiet) print(paste("Length of answer =",length(t)))
		writeBin(as.integer(length(t)), PRWcon)
		rm(t)
		serialize(answer, PRWcon)
		rm(answer)
		if (PRWglobal == 0) rm(list=PRWOutputName)
#		gc()
	}
}

