Commit Graph

124 Commits

Author SHA1 Message Date
60ff8095d6 No more trailing spaces in Redis source code. 2014-06-26 18:52:16 +02:00
b4f9761d85 Fix blocking operations from missing new lists
Behrad Zari discovered [1] and Josiah reported [2]: if you block
and wait for a list to exist, but the list creates from
a non-push command, the blocked client never gets notified.

This commit adds notification of blocked clients into
the DB layer and away from individual commands.

Lists can be created by [LR]PUSH, SORT..STORE, RENAME, MOVE,
and RESTORE.  Previously, blocked client notifications were
only triggered by [LR]PUSH.  Your client would never get
notified if a list were created by SORT..STORE or RENAME or
a RESTORE, etc.

Blocked client notification now happens in one unified place:
  - dbAdd() triggers notification when adding a list to the DB

Two new tests are added that fail prior to this commit.

All test pass.

Fixes #1668

[1]: https://groups.google.com/forum/#!topic/redis-db/k4oWfMkN1NU
[2]: #1668
2014-06-09 11:39:44 +02:00
e9d0d86dbf Check key expiration before deleting
Deleting an expired key should return 0, not success.

Fixes #1648
2014-04-23 16:14:40 +02:00
9e178afae9 String value unsharing refactored into proper function.
All the Redis functions that need to modify the string value of a key in
a destructive way (APPEND, SETBIT, SETRANGE, ...) require to make the
object unshared (if refcount > 1) and encoded in raw format (if encoding
is not already REDIS_ENCODING_RAW).

This was cut & pasted many times in multiple places of the code. This
commit puts the small logic needed into a function called
dbUnshareStringValue().
2014-04-16 15:22:56 +02:00
3e4968339b Sentinel: allow SHUTDOWN command in Sentinel mode. 2014-02-07 11:22:30 +01:00
c5bc592650 Scripting: expire keys in scripts only at first access.
Keys expiring in the middle of the execution of Lua scripts are to
create inconsistencies in masters and / or AOF files. See the following
example:

    if redis.call("exists",KEYS[1]) == 1
    then
        redis.call("incr","mycounter")
    end

    if redis.call("exists",KEYS[1]) == 1
    then
        return redis.call("incr","mycounter")
    end

The script executes two times the same *if key exists then incrementcounter*
logic. However the two executions will work differently in the master and
the slaves, provided some unlucky timing happens.

In the master the first time the key may still exist, while the second time
the key may no longer exist. This will result in the key incremented just one
time. However as a side effect the master will generate a synthetic
`DEL` command in the replication channel in order to force the slaves to
expire the key (given that key expiration is master-driven).

When the same script will run in the slave, the key will no longer be
there, so the script will not increment the key.

The key idea used to implement the expire-at-first-lookup semantics was
provided by Marc Gravell.
2014-02-03 16:29:25 +01:00
b6610a569d dict.c: added optional callback to dictEmpty().
Redis hash table implementation has many non-blocking features like
incremental rehashing, however while deleting a large hash table there
was no way to have a callback called to do some incremental work.

This commit adds this support, as an optiona callback argument to
dictEmpty() that is currently called at a fixed interval (one time every
65k deletions).
2013-12-10 18:18:36 +01:00
7f6743a581 Fixed grammar: before H the article is a, not an. 2013-12-05 16:37:21 +01:00
3a66e0c157 Fixed typo in parseScanCursorOrReply(): ad -> at.
Thanks to @badboy for reporting it.
2013-11-05 17:25:34 +01:00
060d56e7eb SCAN code refactored to parse cursor first.
The previous implementation of SCAN parsed the cursor in the generic
function implementing SCAN, SSCAN, HSCAN and ZSCAN.

The actual higher-level command implementation only checked for empty
keys and return ASAP in that case. The result was that inverting the
arguments of, for instance, SSCAN for example and write:

    SSCAN 0 key

Instead of

    SSCAN key 0

Resulted into no error, since 0 is a non-existing key name very likely.
Just the iterator returned no elements at all.

In order to fix this issue the code was refactored to extract the
function to parse the cursor and return the error. Every higher level
command implementation now parses the cursor and later checks if the key
exist or not.
2013-11-05 17:25:29 +01:00
162acd8ac2 SCAN: when iterating ziplists or intsets always return cursor of 0.
The previous implementation assumed that the first call always happens
with cursor set to 0, this may not be the case, and we want to return 0
anyway otherwise the (broken) client code will loop forever.
2013-11-05 17:24:33 +01:00
406be0ea28 Use strtoul() instead of sscanf() in SCAN implementation. 2013-11-05 17:24:30 +01:00
54a5a7dff8 HSCAN/ZSCAN: skip value when matching.
This fixes issue #1360 and #1362.
2013-11-05 17:24:22 +01:00
bebbc7f9f7 Pass int64_t to intsetGet() instead of long long. 2013-11-05 17:24:17 +01:00
59b30b327d SCAN: no sdsEncodedObject() API in Redis 2.8. 2013-10-31 18:22:29 +01:00
3cc7d486bc Inverted variable boolean value and name after scanGenericCommand() refactoring. 2013-10-31 10:38:52 +01:00
06455014aa scanGenericCommand() refactoring and handling of integer encoded elements.
This commit fixes issue #1354.
2013-10-31 10:38:48 +01:00
1cc7e646af HSCAN implemented. 2013-10-29 16:21:13 +01:00
9e62d9e79c SCAN: refactored into scanGenericCommand.
The new implementation is capable of iterating the keyspace but also
sets, hashes, and sorted sets, and can be used to implement SSCAN, ZSCAN
and HSCAN.
2013-10-29 16:20:06 +01:00
1d659784f4 SCAN: stay inside 80 cols. 2013-10-29 16:19:54 +01:00
854b8be616 Revert "Fixed typo in SCAN comment. iff -> if."
Probably here Pieter means "if and only if".

This reverts commit 43fdf3b404.
2013-10-29 16:19:49 +01:00
5fa5153bf5 SCAN: simplify keys list cleanup using listSetFreeMethod(). 2013-10-29 16:19:45 +01:00
21da9b06a4 SCAN: improve variable names for readability. 2013-10-29 16:19:37 +01:00
907e06cd61 SCAN: remove additional newlines to conform to Redis code base. 2013-10-29 16:19:33 +01:00
b44f1589a4 SCAN: remove useless assertion, already enforced by command table. 2013-10-29 16:19:28 +01:00
d1c1f62ed5 SCAN: use define REDIS_LONGSTR_SIZE instead of fixed len. 2013-10-29 16:19:25 +01:00
8cdaf604ce Fixed typo in SCAN comment. iff -> if. 2013-10-29 16:19:21 +01:00
33409b4c6c SCAN option name changed: pattern -> match. 2013-10-29 16:19:17 +01:00
8c4ff679fe SCAN requires at least 1 argument 2013-10-29 16:19:08 +01:00
0dd95e23ab Add SCAN command 2013-10-29 16:18:24 +01:00
0a0fd37e5b Allow SHUTDOWN in loading state. 2013-06-27 12:14:23 +02:00
e6e07042a1 EXPIRE should not resurrect keys. Issue #1026. 2013-03-28 12:48:38 +01:00
a452b54849 TTL / PTTL commands: two bugs fixed.
This commit fixes two corner cases for the TTL command.

1) When the key was already logically expired (expire time older
than current time) the command returned -1 instead of -2.

2) When the key was existing and the expire was found to be exactly 0
(the key was just about to expire), the command reported -1 (that is, no
expire) instead of a TTL of zero (that is, about to expire).
2013-03-26 13:59:33 +01:00
700e5eb4fc PSYNC: work in progress, preview #2, rebased to unstable. 2013-02-12 12:57:40 +01:00
d3cf778d82 Send 'expired' events when a key expires by lookup. 2013-01-28 13:18:57 +01:00
b9bc4f9132 Keyspace events: it is now possible to select subclasses of events.
When keyspace events are enabled, the overhead is not sever but
noticeable, so this commit introduces the ability to select subclasses
of events in order to avoid to generate events the user is not
interested in.

The events can be selected using redis.conf or CONFIG SET / GET.
2013-01-28 13:18:36 +01:00
4ff138fbbe Keyspace events added for more commands. 2013-01-28 13:17:30 +01:00
fdfb59beae Initial test events for the new keyspace notification API. 2013-01-28 13:17:18 +01:00
dd2ce743ca Fixed over-80-cols comment in db.c 2013-01-28 13:17:15 +01:00
39f0a33f78 Whitelist SIGUSR1 to avoid auto-triggering errors.
This commit fixes issue #875 that was caused by the following events:

1) There is an active child doing BGSAVE.
2) flushall is called (or any other condition that makes Redis killing
the saving child process).
3) An error is sensed by Redis as the child exited with an error (killed
by a singal), that stops accepting write commands until a BGSAVE happens
to be executed with success.

Whitelisting SIGUSR1 and making sure Redis always uses this signal in
order to kill its own children fixes the issue.
2013-01-19 13:30:46 +01:00
1caf09399e Fixed many typos.
Conflicts fixed, mainly because 2.8 has no cluster support / files:
	00-RELEASENOTES
	src/cluster.c
	src/crc16.c
	src/redis-trib.rb
	src/redis.h
2013-01-19 11:03:19 +01:00
50c41de752 TTL API change: TTL returns -2 for non existing keys.
The previous behavior was to return -1 if:

1) Existing key but without an expire set.
2) Non existing key.

Now the second case is handled in a different, and TTL will return -2
if the key does not exist at all.

PTTL follows the same behavior as well.
2012-11-12 23:05:56 +01:00
8ddb23b90c BSD license added to every C source and header file. 2012-11-08 18:34:04 +01:00
b58f03a0e8 Make sure that SELECT argument is an integer or return an error.
Unfortunately we had still the lame atoi() without any error checking in
place, so "SELECT foo" would work as "SELECT 0". This was not an huge
problem per se but some people expected that DB can be strings and not
just numbers, and without errors you get the feeling that they can be
numbers, but not the behavior.

Now getLongFromObjectOrReply() is used as almost everybody else across
the code, generating an error if the number is not an integer or
overflows the long type.

Thanks to @mipearson for reporting that on Twitter.
2012-09-11 10:34:48 +02:00
9311d2b527 Use safe dictionary iterator from KEYS
Every matched key in a KEYS call is checked for expiration. When the key
is set to expire, the call to `getExpire` will assert that the key also
exists in the main dictionary. This in turn causes a rehashing step to
be executed. Rehashing a dictionary when there is an iterator active may
result in the iterator emitting duplicate entries, or not emitting some
entries at all. By using a safe iterator, the rehash step is omitted.
2012-04-30 10:16:20 -07:00
4f0bd607d9 Never used function stringObjectEqualsMs() removed. 2012-04-07 11:26:56 +02:00
3aad0de2e9 expireGenericCommand(): better variable names and a top-comment that describes the function's behavior. 2012-04-06 00:40:36 +02:00
81a28fe131 for (p)expireat use absolute time, without double recomputation 2012-04-06 00:40:31 +02:00
b518a83525 fix mstime() ommited while comparing if key is already expired 2012-04-06 00:40:26 +02:00
92dd4e4301 fix time() instead of mstime() in expireIfNeeded 2012-03-27 23:04:34 +02:00