Permalink
Browse files

Fixed a serious .getresponse bug (handl short reads); new redisLIndex…

…; Documentation fixes
  • Loading branch information...
B. W. Lewis
B. W. Lewis committed Mar 16, 2010
1 parent fb9aa3c commit 2895ec6bd29371613de941598aa25150b7395117
View
@@ -2,12 +2,12 @@
redisRPush <- function(key, value) {
value <- .cerealize(value)
- .sendCmd(.redismsg('RPUSH',key,length(value)), value)
+ .sendCmd(.redismsg('RPUSH',key,length(value)), value) == "OK"
}
redisLPush <- function(key, value) {
value <- .cerealize(value)
- .sendCmd(.redismsg('LPUSH',key,length(value)), value)
+ .sendCmd(.redismsg('LPUSH',key,length(value)), value) == "OK"
}
redisLLen <- function(key) {
@@ -22,19 +22,25 @@ redisLRange <- function(key, start, end) {
}
redisLTrim <- function(key,start,end) {
- .sendCmd(.redismsg('LTRIM', key, start, end))
+ start <- charToRaw(as.character(start))
+ end <- charToRaw(as.character(end))
+ cmd <- list(LTRIM=charToRaw(key),start,end)
+ .sendCmdMulti(cmd) == "OK"
}
redisLIndex <- function(key, index) {
.sendCmd(.redismsg('LINDEX', key, index))
}
redisLSet <- function(key, index, value) {
- .sendCmd(.redismsg('LSET', key, index, value))
+ key <- charToRaw(as.character(key))
+ index <- charToRaw(as.character(index))
+ cmd <- list(LSET=key,index,value)
+ .sendCmdMulti(cmd) == "OK"
}
redisLRem <- function(key, count, value) {
- .sendCmd(.redismsg('LREM', key, count, value))
+ .sendCmd(.redismsg('LREM', key, count, value)) == "OK"
}
redisRPop <- function(key) {
View
@@ -39,12 +39,25 @@
'+' = substr(l,2,nchar(l)),
':' = as.numeric(substr(l,2,nchar(l))),
'$' = {
- dat <- as.numeric(substr(l,2,nchar(l)))
- if (dat < 0) {
+ n <- as.numeric(substr(l,2,nchar(l)))
+ if (n < 0) {
return(NULL)
}
socketSelect(list(con))
- dat <- readBin(con, 'raw', n=dat)
+ dat <- tryCatch(readBin(con, 'raw', n=n),
+ error=function(e) {
+ stop("error reading from socket: ",e$message)
+ })
+ m <- length(dat)
+ while(m<n) {
+# Short read; we need to retrieve the rest of this message.
+ socketSelect(list(con))
+ dat <- c(dat, tryCatch(readBin(con, 'raw', n=(n-m)),
+ error=function(e) {
+ stop("error reading from socket: ",e$message)
+ }))
+ m <- length(dat)
+ }
l <- readLines(con,n=1)
# Try retrieving an R object, otherwise default to character:
tryCatch(unserialize(dat),
@@ -57,8 +70,8 @@
vals <- vector('list',numVars)
if(!is.null(names)) names(vals) <- names
for (i in 1:numVars) {
-# XXX This extra copy is unfortunate, but the default R behavior is
-# not acceptable (assigning a list entry to NULL removes it from the list!)
+# XXX This extra copy is unfortunate, but so is the default R behavior:
+# assigning a list entry to NULL removes it from the list!
# Does anyone have a better idea here?
vi <- .getResponse()
if(!is.null(vi)) vals[[i]] <- vi
@@ -88,7 +101,7 @@
# NA or zero-length keys are allowed, for example:
# list(SADD=charToRaw("mykey"), myvalue)
# NA or zero-length keys are simply skipped in the outgoing message.
-.sendCmdMulti <- function(keyvalues) {
+.sendCmdMulti <- function(keyvalues, ...) {
numItems <- length(keyvalues)
keys <- names(keyvalues)
if(is.null(keys)) {
@@ -112,5 +125,5 @@
.sendCmd('\r\n', checkResponse=FALSE)
}
}
- .getResponse()
+ .getResponse(...)
}
View
@@ -61,7 +61,7 @@ redisSRandMember <- function(set)
redisSAdd <- function(set, element)
{
cmd <- list(SADD=charToRaw(set),element)
- .sendCmdMulti(cmd)
+ .sendCmdMulti(cmd) == 1
}
redisSPop <- function(set)
@@ -79,7 +79,7 @@ redisSMembers <- function(set)
redisSRem <- function(set, element)
{
cmd <- list(SREM=charToRaw(set),element)
- .sendCmdMulti(cmd)
+ .sendCmdMulti(cmd) == 1
}
redisSCard <- function(set)
@@ -91,6 +91,6 @@ redisSCard <- function(set)
redisSMove <- function(setA, setB, element)
{
cmd <- list(SMOVE=charToRaw(setA),charToRaw(setB),element)
- .sendCmdMulti(cmd)
+ .sendCmdMulti(cmd) == 1
}
View
@@ -22,6 +22,10 @@ redisGetSet <- function(key, value) {
}
redisMGet <- function(keys) {
+# keylist <- as.list(keys)
+# cmd <- list(charToRaw('MGET'))
+# cmd <- c(cmd, lapply(keylist,charToRaw))
+# .sendCmdMulti(cmd, names=keys)
.sendCmd(.redismsg('MGET',paste(keys,collapse=' ')),names=keys)
}
View
@@ -4,10 +4,15 @@
\docType{package}
\title{An R client for Redis}
\description{
-Redis is a high-performance, networked, key/value database.
+Redis is a high-performance, in-memory, networked, key/value-like database.
The redis package for R provides a native R language interface
-to Redis. The R client can store and read arbitrary serializable R objects
-as well as access raw objects like strings and binary blobs from other clients.
+to Redis. The R client can store and retrieve arbitrary serializable R objects
+as well as raw data objects like strings and binary blobs from other clients.
+Redis supports a number of innovative value types beyond arbitrary
+binary data, including sets and lifo/fifo-like lists,
+database replication, database persistence, high-performance virtual
+memory management and much more. Please see the rredis vignette for
+more information and examples on using Redis and R together.
}
\details{
\tabular{ll}{
@@ -20,12 +25,12 @@ LazyLoad: \tab yes\cr
}
}
\author{
-B. W. Lewis
+B. W. Lewis, with substantial assistance from Pat Sheilds
Maintainer: B. W. Lewis <blewis@illposed.net>
}
\references{
-\link{http://code.google.com/p/redis/}
+http://code.google.com/p/redis/
}
\keyword{ package }
\examples{
View
@@ -0,0 +1,26 @@
+\name{redisAuth}
+\alias{redisAuth}
+\title{Redis authentication.}
+\description{Redis supports a trivially simple and insecure authentication
+method. This function implements it.
+}
+\usage{
+redisAuth(pwd)
+}
+\arguments{
+ \item{pwd}{
+The (required) password.
+}
+}
+\details{You should not use this function. If you need a secure key/value
+database, it's best not to use Redis for now.
+}
+\value{
+TRUE if sueccessful, FALSE otherwise.
+}
+\references{
+http://code.google.com/p/redis/
+}
+\author{
+B. W. Lewis
+}
View
@@ -0,0 +1,29 @@
+\name{redisBgRewriteAOF}
+\alias{redisBgRewriteAOF}
+\title{redisBgRewriteAOF}
+\description{
+Re-write the Redis append-only file in the background.
+}
+\usage{
+redisBgRewriteAOF()
+}
+\details{
+BGREWRITEAOF rewrites the Append Only File in the background when it gets too
+big. The Redis Append Only File is a Journal, so every operation modifying the
+dataset is logged in the Append Only File (and replayed at startup). This means
+that the Append Only File always grows. In order to rebuild its content the
+BGREWRITEAOF creates a new version of the append only file starting directly
+form the dataset in memory in order to guarantee the generation of the minimal
+number of commands needed to rebuild the database.
+(These details are copied verbatim from the Redis master documentation, see the
+references below.)
+}
+\value{
+Nothing is returned.
+}
+\references{
+http://code.google.com/p/redis/
+}
+\author{
+B. W. Lewis
+}
View
@@ -0,0 +1,19 @@
+\name{redisBgSave}
+\alias{redisBgSave}
+\title{redisBgSave}
+\description{Asynchronously save that database to disk.
+}
+\usage{
+redisBgSave()
+}
+\details{Force Redis to save the database(s) to disk in the background.
+}
+\value{Nothing is returned. Check the UNIX time of the last completed
+save operation with the redisLastsave function.
+}
+\references{
+http://code.google.com/p/redis/
+}
+\author{
+B. W. Lewis
+}
View
@@ -6,8 +6,6 @@ server.}
\usage{
redisClose()
}
-\arguments{
-}
\details{A running instance of a Redis server is required. See
http://code.google.com/p/redis/ for details.}
\value{Nothing is returned. Errors are displayed if the function fails to
View
@@ -22,7 +22,7 @@ Redis connection will be returned. The list can be used to manage multiple
Redis connections with the \code{\link{attachRedis}} function.
}
\references{
-\link{http://code.google.com/p/redis/} for details.
+See http://code.google.com/p/redis/ for details.
}
\author{
B. W. Lewis
View
@@ -20,7 +20,7 @@ Nothing is returned if the key/value pair is successfully deleted.
A warning is thrown if the they key could not be found.
}
\references{
-{\link{http://code.google.com/p/redis/}}
+http://code.google.com/p/redis/
}
\author{
B. W. Lewis
View
@@ -20,7 +20,7 @@ Returns FALSE if no matching key, TRUE if matching key exists, and NULL
if an error occured.
}
\references{
-{\link{http://code.google.com/p/redis/}}
+http://code.google.com/p/redis/
}
\author{
B. W. Lewis
View
@@ -36,7 +36,7 @@ The previous value associated with key or NULL if no previous
association exists.
}
\references{
-{\link{http://code.google.com/p/redis/}}
+http://code.google.com/p/redis/
}
\author{
B. W. Lewis
View
@@ -0,0 +1,27 @@
+\name{redisInfo}
+\alias{redisInfo}
+\title{redisInfo}
+\description{Return system information about Redis.
+}
+\usage{
+redisInfo()
+}
+\value{
+A list of various Redis system parameters is returned, including at least:
+the Redis version,
+connected clients,
+connected slaves,
+used memory,
+changes since last save,
+last save time (UNIX time),
+total connections received,
+total commands processed,
+uptime in seconds,
+uptime in days.
+}
+\references{
+http://code.google.com/p/redis/
+}
+\author{
+B. W. Lewis
+}
View
@@ -16,9 +16,10 @@ redisLSet(key, index, value)
}
}
\details{
-Out of range indices throw an error.
+Indices begin at zero. Out of range indices throw an error.
}
\value{
+TRUE if successful, FALSE otherwise.
}
\references{
http://code.google.com/p/redis/wiki/LSetCommand
@@ -27,10 +28,13 @@ http://code.google.com/p/redis/wiki/LSetCommand
B. W. Lewis
}
\seealso{
-\code{\link{redisBRpop}}
+\code{\link{redisLPush}}
}
\examples{
\dontrun{
redisConnect()
+redisLPush('list',pi)
+redisLSet('list',0,5)
+redisLIndex('list',0)
}
}
View
@@ -7,20 +7,21 @@
redisMGet(keys)
}
\arguments{
- \item{keys}{A character vector or list of keys to retrieve.}
-}
-\details{
+ \item{keys}{A vector or list of character strings corresponding to
+keys to retrieve.}
}
\value{
A list of retrieved key/value pairs. Missing values return NULL.
}
+\details{
+Values are returned in a list with names corresponding to keys.
+}
\references{
http://code.google.com/p/redis/wiki/MGetCommand
}
\author{
B. W. Lewis
}
-
\seealso{
\code{\link{redisMSet}}
}
View
@@ -8,6 +8,9 @@ redisMSet(keyvalues, NX = FALSE)
\arguments{
\item{keyvalues}{A list of values to set of the form
list(key1=value1, key2=value2, ...)}
+ \item{NX}{
+If NX = TRUE, existing values will not be replaced, otherwise they will be.
+}
}
\details{
Set one or more key/value pairs in the Redis database. Existing
Oops, something went wrong.

0 comments on commit 2895ec6

Please sign in to comment.