Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
f2aa84bd
Commit
f2aa84bd
authored
Mar 26, 2009
by
antirez
Browse files
Lua client added thanks to Daniele Alessandri
parent
e63943a4
Changes
7
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
f2aa84bd
...
...
@@ -6,3 +6,4 @@ redis-benchmark
doc-tools
mkrelease.sh
release
myredis.conf
client-libraries/README
View file @
f2aa84bd
...
...
@@ -26,4 +26,7 @@ Perl lib source code:
Redis-php PHP C module:
http://code.google.com/p/phpredis/
Lua lib source code:
http://github.com/nrk/redis-lua/tree/master
For all the rest check the Redis tarball or Git repository.
client-libraries/lua/.LICENSE.swp
0 → 100644
View file @
f2aa84bd
File added
client-libraries/lua/LICENSE
0 → 100644
View file @
f2aa84bd
Copyright (c) 2009
Daniele Alessandri
http://www.clorophilla.net/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
client-libraries/lua/README
0 → 100644
View file @
f2aa84bd
redis-lua
-------------------------------------------------------------------------------
A Lua client library for the redis key value storage system.
\ No newline at end of file
client-libraries/lua/redis.lua
0 → 100644
View file @
f2aa84bd
module
(
'Redis'
,
package
.
seeall
)
require
(
'socket'
)
-- requires LuaSocket as a dependency
-- ############################################################################
local
protocol
=
{
newline
=
'
\r\n
'
,
ok
=
'OK'
,
err
=
'ERR'
,
null
=
'nil'
,
}
-- ############################################################################
local
function
toboolean
(
value
)
return
value
==
1
end
local
function
_write
(
self
,
buffer
)
local
_
,
err
=
self
.
socket
:
send
(
buffer
)
if
err
then
error
(
err
)
end
end
local
function
_read
(
self
,
len
)
if
len
==
nil
then
len
=
'*l'
end
local
line
,
err
=
self
.
socket
:
receive
(
len
)
if
not
err
then
return
line
else
error
(
'Connection error: '
..
err
)
end
end
-- ############################################################################
local
function
_read_response
(
self
)
if
options
and
options
.
close
==
true
then
return
end
local
res
=
_read
(
self
)
local
prefix
=
res
:
sub
(
1
,
-#
res
)
local
response_handler
=
protocol
.
prefixes
[
prefix
]
if
not
response_handler
then
error
(
"Unknown response prefix: "
..
prefix
)
else
return
response_handler
(
self
,
res
)
end
end
local
function
_send_raw
(
self
,
buffer
)
-- TODO: optimize
local
bufferType
=
type
(
buffer
)
if
bufferType
==
'string'
then
_write
(
self
,
buffer
)
elseif
bufferType
==
'table'
then
_write
(
self
,
table.concat
(
buffer
))
else
error
(
'Argument error: '
..
bufferType
)
end
return
_read_response
(
self
)
end
local
function
_send_inline
(
self
,
command
,
...
)
if
arg
.
n
==
0
then
_write
(
self
,
command
..
protocol
.
newline
)
else
local
arguments
=
arg
arguments
.
n
=
nil
if
#
arguments
>
0
then
arguments
=
table.concat
(
arguments
,
' '
)
else
arguments
=
''
end
_write
(
self
,
command
..
' '
..
arguments
..
protocol
.
newline
)
end
return
_read_response
(
self
)
end
local
function
_send_bulk
(
self
,
command
,
...
)
local
arguments
=
arg
local
data
=
tostring
(
table.remove
(
arguments
))
arguments
.
n
=
nil
-- TODO: optimize
if
#
arguments
>
0
then
arguments
=
table.concat
(
arguments
,
' '
)
else
arguments
=
''
end
return
_send_raw
(
self
,
{
command
,
' '
,
arguments
,
' '
,
#
data
,
protocol
.
newline
,
data
,
protocol
.
newline
})
end
local
function
_read_line
(
self
,
response
)
return
response
:
sub
(
2
)
end
local
function
_read_error
(
self
,
response
)
local
err_line
=
response
:
sub
(
2
)
if
err_line
:
sub
(
1
,
3
)
==
protocol
.
err
then
error
(
"Redis error: "
..
err_line
:
sub
(
5
))
else
error
(
"Redis error: "
..
err_line
)
end
end
local
function
_read_bulk
(
self
,
response
)
local
str
=
response
:
sub
(
2
)
local
len
=
tonumber
(
str
)
if
not
len
then
error
(
'Cannot parse '
..
str
..
' as data length.'
)
else
if
len
==
-
1
then
return
nil
end
local
data
=
_read
(
self
,
len
+
2
)
return
data
:
sub
(
1
,
-
3
);
end
end
local
function
_read_multibulk
(
self
,
response
)
local
str
=
response
:
sub
(
2
)
-- TODO: add a check if the returned value is indeed a number
local
list_count
=
tonumber
(
str
)
if
list_count
==
-
1
then
return
nil
else
local
list
=
{}
if
list_count
>
0
then
for
i
=
1
,
list_count
do
table.insert
(
list
,
i
,
_read_bulk
(
self
,
_read
(
self
)))
end
end
return
list
end
end
local
function
_read_integer
(
self
,
response
)
local
res
=
response
:
sub
(
2
)
local
number
=
tonumber
(
res
)
if
not
number
then
if
res
==
protocol
.
null
then
return
nil
else
error
(
'Cannot parse '
..
res
..
' as numeric response.'
)
end
end
return
number
end
-- ############################################################################
protocol
.
prefixes
=
{
[
'+'
]
=
_read_line
,
[
'-'
]
=
_read_error
,
[
'$'
]
=
_read_bulk
,
[
'*'
]
=
_read_multibulk
,
[
':'
]
=
_read_integer
,
}
-- ############################################################################
local
methods
=
{
-- miscellaneous commands
ping
=
{
'PING'
,
_send_inline
,
function
(
response
)
if
response
==
'PONG'
then
return
true
else
return
false
end
end
},
echo
=
{
'ECHO'
,
_send_bulk
},
-- TODO: the server returns an empty -ERR on authentication failure
auth
=
{
'AUTH'
},
-- connection handling
quit
=
{
'QUIT'
,
function
(
self
,
command
)
_write
(
self
,
command
..
protocol
.
newline
)
end
},
-- commands operating on string values
set
=
{
'SET'
,
_send_bulk
},
set_preserve
=
{
'SETNX'
,
_send_bulk
,
toboolean
},
get
=
{
'GET'
},
get_multiple
=
{
'MGET'
},
increment
=
{
'INCR'
},
increment_by
=
{
'INCRBY'
},
decrement
=
{
'DECR'
},
decrement_by
=
{
'DECRBY'
},
exists
=
{
'EXISTS'
,
_send_inline
,
toboolean
},
delete
=
{
'DEL'
,
_send_inline
,
toboolean
},
type
=
{
'TYPE'
},
-- commands operating on the key space
keys
=
{
'KEYS'
,
_send_inline
,
function
(
response
)
local
keys
=
{}
response
:
gsub
(
'%w+'
,
function
(
key
)
table.insert
(
keys
,
key
)
end
)
return
keys
end
},
random_key
=
{
'RANDOMKEY'
},
rename
=
{
'RENAME'
},
rename_preserve
=
{
'RENAMENX'
},
database_size
=
{
'DBSIZE'
},
-- commands operating on lists
push_tail
=
{
'RPUSH'
,
_send_bulk
},
push_head
=
{
'LPUSH'
,
_send_bulk
},
list_length
=
{
'LLEN'
,
_send_inline
,
function
(
response
,
key
)
--[[ TODO: redis seems to return a -ERR when the specified key does
not hold a list value, but this behaviour is not
consistent with the specs docs. This might be due to the
-ERR response paradigm being new, which supersedes the
check for negative numbers to identify errors. ]]
if
response
==
-
2
then
error
(
'Key '
..
key
..
' does not hold a list value'
)
end
return
response
end
},
list_range
=
{
'LRANGE'
},
list_trim
=
{
'LTRIM'
},
list_index
=
{
'LINDEX'
},
list_set
=
{
'LSET'
,
_send_bulk
},
list_remove
=
{
'LREM'
,
_send_bulk
},
pop_first
=
{
'LPOP'
},
pop_last
=
{
'RPOP'
},
-- commands operating on sets
set_add
=
{
'SADD'
},
set_remove
=
{
'SREM'
},
set_cardinality
=
{
'SCARD'
},
set_is_member
=
{
'SISMEMBER'
},
set_intersection
=
{
'SINTER'
},
set_intersection_store
=
{
'SINTERSTORE'
},
set_members
=
{
'SMEMBERS'
},
-- multiple databases handling commands
select_database
=
{
'SELECT'
},
move_key
=
{
'MOVE'
},
flush_database
=
{
'FLUSHDB'
},
flush_databases
=
{
'FLUSHALL'
},
-- sorting
--[[
TODO: should we pass sort parameters as a table? e.g:
params = {
by = 'weight_*',
get = 'object_*',
limit = { 0, 10 },
sort = { 'desc', 'alpha' }
}
--]]
sort
=
{
'SORT'
},
-- persistence control commands
save
=
{
'SAVE'
},
background_save
=
{
'BGSAVE'
},
last_save
=
{
'LASTSAVE'
},
shutdown
=
{
'SHUTDOWN'
,
function
(
self
,
command
)
_write
(
self
,
command
..
protocol
.
newline
)
end
},
-- remote server control commands
info
=
{
'INFO'
,
_send_inline
,
function
(
response
)
local
info
=
{}
response
:
gsub
(
'
(
[^\r\n]*
)
\
r
\
n
', function(kv)
local k,v = kv:match(('
([
^
:]
*
):([
^
:]
*
)
'):rep(1))
info[k] = v
end)
return info
end
},
}
function connect(host, port)
local client_socket = socket.connect(host, port)
if not client_socket then
error('
Could
not
connect
to
' .. host .. '
:
' .. port)
end
local redis_client = {
socket = client_socket,
raw_cmd = function(self, buffer)
return _send_raw(self, buffer .. protocol.newline)
end,
}
return setmetatable(redis_client, {
__index = function(self, method)
local redis_meth = methods[method]
if redis_meth then
return function(self, ...)
if not redis_meth[2] then
table.insert(redis_meth, 2, _send_inline)
end
local response = redis_meth[2](self, redis_meth[1], ...)
if redis_meth[3] then
return redis_meth[3](response, ...)
else
return response
end
end
end
end
})
end
redis.conf
View file @
f2aa84bd
...
...
@@ -62,6 +62,17 @@ databases 16
# slaveof <masterip> <masterport>
################################## SECURITY ###################################
# Require clients to issue AUTH <PASSWORD> before processing any other
# commands. This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#requirepass foobared
############################### ADVANCED CONFIG ###############################
# Glue small output buffers together in order to send small replies in a
...
...
@@ -74,12 +85,3 @@ glueoutputbuf yes
# pool so it uses more CPU and can be a bit slower. Usually it's a good
# idea.
shareobjects
no
# Require clients to issue AUTH <PASSWORD> before processing any other
# commands. This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#requirepass foobared
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment