Please consider the following example (using 2 R sessions):
library(svSocket)
startSocketServer()
library(svSocket)
con <- socketConnection(host = "localhost", port = 8888, blocking = FALSE)
value<-"setosa"
evalServer(con, tmp, value) # first call to the server
evalServer(con, head(iris[iris$Species==tmp,])) # second call to the server
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
To send the above query I need a 2-step process where I first save my parameter in the server and then I use them to query the table.
Do the same in one step only. For example, building the query using paste and send it to the server like I would in PHP + MySQL. Basically, I need to avoid that a different user overwrites tmp between the first and the second call to the server. The above commands will be running behind web apps with 30 to 50 users simultaneously connected, so I reckon that this inconvenience might happen.
One possible answer
$ query <- paste0('evalServer(con,"head(iris[iris$Species==\'', value,'\',])")')
$ eval(parse(text=query))
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
This does the job but it's kind of a dial... The code is very messy and difficult to read.
I ended up modifying/simplifying evalServer. This version accept only a character string with the expression to evaluate in the server
evalServer2 <- function (con, expr)
{
if(!is.character(expr)) stop("expr must be a character string containing the expression to evaluate in the server.")
cat("..Last.value <- try(eval(parse(text = \"", expr, "\"))); .f <- file(); dump(\"..Last.value\", file = .f); flush(.f); seek(.f, 0); cat(\"\\n<<<startflag>>>\", gsub(\"<pointer: [0-9a-fx]+>\", \"NULL\", readLines(.f)), \"<<<endflag>>>\\n\", sep = \"\\n\"); close(.f); rm(.f, ..Last.value); flush.console()\n",
file = con, sep = "")
objdump <- ""
endloc <- NULL
while (!length(endloc)) {
obj <- readLines(con, n = 1000, warn = FALSE)
if (!length(obj)) {
Sys.sleep(0.01)
next
}
endloc <- grep("<<<endflag>>>", obj)
if (length(endloc))
obj <- obj[0:(endloc[length(endloc)] - 1)]
objdump <- c(objdump, obj)
}
startloc <- grep("<<<startflag>>>", objdump)
if (!length(startloc))
stop("Unable to find <<<startflag>>>")
objdump <- objdump[-(1:startloc[length(startloc)])]
nospace <- grep("[^ ]$", objdump)
nospace <- nospace[nospace < length(objdump)]
for (i in rev(nospace)) {
objdump[i] <- paste(objdump[i], objdump[i + 1], sep = "")
objdump[i + 1] <- ""
}
objcon <- textConnection(objdump)
on.exit(close(objcon))
source(objcon, local = TRUE, echo = FALSE, verbose = FALSE)
return(..Last.value)
}
which allows:
> x <- "5 + 4"
> evalServer2(con, x)
[1] 9
Instead, evalServer would retrieve a variable called x stored in the R server
> evalServer(con, x, 23)
[1] TRUE
> evalServer(con, x)
[1] 23
> evalServer2(con, "x")
[1] 23
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With