Hello community,

here is the log from the commit of package redis for openSUSE:Leap:15.2 checked 
in at 2020-04-28 20:11:06
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Leap:15.2/redis (Old)
 and      /work/SRC/openSUSE:Leap:15.2/.redis.new.2738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "redis"

Tue Apr 28 20:11:06 2020 rev:43 rq:797725 version:5.0.9

Changes:
--------
--- /work/SRC/openSUSE:Leap:15.2/redis/redis.changes    2020-03-26 
05:42:17.935307401 +0100
+++ /work/SRC/openSUSE:Leap:15.2/.redis.new.2738/redis.changes  2020-04-28 
20:11:07.132529482 +0200
@@ -1,0 +2,9 @@
+Sat Apr 18 07:57:40 UTC 2020 - Andreas Stieger <andreas.stie...@gmx.de>
+
+- redis 5.0.9:
+  * Critical fix when Streams with AOF ore replicas are used:
+    Prevent reprocesing some entries upon restart
+  * Speed improvement: Clients blocked on the same key are now
+    unblocked on O(1) time
+
+-------------------------------------------------------------------
@@ -8,0 +18 @@
+

Old:
----
  redis-5.0.8.tar.gz

New:
----
  redis-5.0.9.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ redis.spec ++++++
--- /var/tmp/diff_new_pack.63eLna/_old  2020-04-28 20:11:07.748530761 +0200
+++ /var/tmp/diff_new_pack.63eLna/_new  2020-04-28 20:11:07.756530777 +0200
@@ -20,7 +20,7 @@
 %define _log_dir        %{_localstatedir}/log/%{name}
 %define _conf_dir       %{_sysconfdir}/%{name}
 Name:           redis
-Version:        5.0.8
+Version:        5.0.9
 Release:        0
 Summary:        Persistent key-value database
 License:        BSD-3-Clause

++++++ redis-5.0.8.tar.gz -> redis-5.0.9.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.0.8/00-RELEASENOTES 
new/redis-5.0.9/00-RELEASENOTES
--- old/redis-5.0.8/00-RELEASENOTES     2020-03-12 16:07:44.000000000 +0100
+++ new/redis-5.0.9/00-RELEASENOTES     2020-04-17 12:45:57.000000000 +0200
@@ -12,6 +12,27 @@
 
--------------------------------------------------------------------------------
 
 
================================================================================
+Redis 5.0.9     Released Thu Apr 17 12:41:00 CET 2020
+================================================================================
+
+Upgrade urgency:CRITICAL if you use Streams with AOF ore replicas.
+                Otherwise the upgrade urgency is LOW.
+
+This release has a speed improvement and a critical fix:
+
+    * FIX: XREADGROUP when fetching data in a blocking way, would not
+           emit the XCLAIM in the AOF file and to replicas. This means
+           that the last ID is not updated, and that restarting the server
+           will have the effect of reprocessing some entries.
+    * NEW: Clients blocked on the same key are now unblocked on
+           O(1) time. Backported from Redis 6.
+
+Commits:
+
+    1fc8ef81a Fix XCLAIM propagation in AOF/replicas for blocking XREADGROUP.
+    a5e24eabc Speedup: unblock clients on keys in O(1).
+
+================================================================================
 Redis 5.0.8     Released Thu Mar 12 16:05:41 CET 2020
 
================================================================================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.0.8/src/adlist.c new/redis-5.0.9/src/adlist.c
--- old/redis-5.0.8/src/adlist.c        2020-03-12 16:07:44.000000000 +0100
+++ new/redis-5.0.9/src/adlist.c        2020-04-17 12:45:57.000000000 +0200
@@ -327,12 +327,11 @@
 }
 
 /* Rotate the list removing the tail node and inserting it to the head. */
-void listRotate(list *list) {
-    listNode *tail = list->tail;
-
+void listRotateTailToHead(list *list) {
     if (listLength(list) <= 1) return;
 
     /* Detach current tail */
+    listNode *tail = list->tail;
     list->tail = tail->prev;
     list->tail->next = NULL;
     /* Move it as head */
@@ -342,6 +341,21 @@
     list->head = tail;
 }
 
+/* Rotate the list removing the head node and inserting it to the tail. */
+void listRotateHeadToTail(list *list) {
+    if (listLength(list) <= 1) return;
+
+    listNode *head = list->head;
+    /* Detach current head */
+    list->head = head->next;
+    list->head->prev = NULL;
+    /* Move it as tail */
+    list->tail->next = head;
+    head->next = NULL;
+    head->prev = list->tail;
+    list->tail = head;
+}
+
 /* Add all the elements of the list 'o' at the end of the
  * list 'l'. The list 'other' remains empty but otherwise valid. */
 void listJoin(list *l, list *o) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.0.8/src/adlist.h new/redis-5.0.9/src/adlist.h
--- old/redis-5.0.8/src/adlist.h        2020-03-12 16:07:44.000000000 +0100
+++ new/redis-5.0.9/src/adlist.h        2020-04-17 12:45:57.000000000 +0200
@@ -85,7 +85,8 @@
 listNode *listIndex(list *list, long index);
 void listRewind(list *list, listIter *li);
 void listRewindTail(list *list, listIter *li);
-void listRotate(list *list);
+void listRotateTailToHead(list *list);
+void listRotateHeadToTail(list *list);
 void listJoin(list *l, list *o);
 
 /* Directions for iterators */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.0.8/src/blocked.c 
new/redis-5.0.9/src/blocked.c
--- old/redis-5.0.8/src/blocked.c       2020-03-12 16:07:44.000000000 +0100
+++ new/redis-5.0.9/src/blocked.c       2020-04-17 12:45:57.000000000 +0200
@@ -67,6 +67,21 @@
 
 int serveClientBlockedOnList(client *receiver, robj *key, robj *dstkey, 
redisDb *db, robj *value, int where);
 
+/* This structure represents the blocked key information that we store
+ * in the client structure. Each client blocked on keys, has a
+ * client->bpop.keys hash table. The keys of the hash table are Redis
+ * keys pointers to 'robj' structures. The value is this structure.
+ * The structure has two goals: firstly we store the list node that this
+ * client uses to be listed in the database "blocked clients for this key"
+ * list, so we can later unblock in O(1) without a list scan.
+ * Secondly for certain blocking types, we have additional info. Right now
+ * the only use for additional info we have is when clients are blocked
+ * on streams, as we have to remember the ID it blocked for. */
+typedef struct bkinfo {
+    listNode *listnode;     /* List node for db->blocking_keys[key] list. */
+    streamID stream_id;     /* Stream ID if we blocked in a stream. */
+} bkinfo;
+
 /* Get a timeout value from an object and store it into 'timeout'.
  * The final timeout is always stored as milliseconds as a time where the
  * timeout will expire, however the parsing is performed according to
@@ -291,8 +306,7 @@
                         if (receiver->btype != BLOCKED_LIST) {
                             /* Put at the tail, so that at the next call
                              * we'll not run into it again. */
-                            listDelNode(clients,clientnode);
-                            listAddNodeTail(clients,receiver);
+                            listRotateHeadToTail(clients);
                             continue;
                         }
 
@@ -353,8 +367,7 @@
                         if (receiver->btype != BLOCKED_ZSET) {
                             /* Put at the tail, so that at the next call
                              * we'll not run into it again. */
-                            listDelNode(clients,clientnode);
-                            listAddNodeTail(clients,receiver);
+                            listRotateHeadToTail(clients);
                             continue;
                         }
 
@@ -398,8 +411,9 @@
                     while((ln = listNext(&li))) {
                         client *receiver = listNodeValue(ln);
                         if (receiver->btype != BLOCKED_STREAM) continue;
-                        streamID *gt = dictFetchValue(receiver->bpop.keys,
-                                                      rl->key);
+                        bkinfo *bki = dictFetchValue(receiver->bpop.keys,
+                                                     rl->key);
+                        streamID *gt = &bki->stream_id;
 
                         /* If we blocked in the context of a consumer
                          * group, we need to resolve the group and update the
@@ -516,17 +530,15 @@
     if (target != NULL) incrRefCount(target);
 
     for (j = 0; j < numkeys; j++) {
-        /* The value associated with the key name in the bpop.keys dictionary
-         * is NULL for lists and sorted sets, or the stream ID for streams. */
-        void *key_data = NULL;
-        if (btype == BLOCKED_STREAM) {
-            key_data = zmalloc(sizeof(streamID));
-            memcpy(key_data,ids+j,sizeof(streamID));
-        }
+        /* Allocate our bkinfo structure, associated to each key the client
+         * is blocked for. */
+        bkinfo *bki = zmalloc(sizeof(*bki));
+        if (btype == BLOCKED_STREAM)
+            bki->stream_id = ids[j];
 
         /* If the key already exists in the dictionary ignore it. */
-        if (dictAdd(c->bpop.keys,keys[j],key_data) != DICT_OK) {
-            zfree(key_data);
+        if (dictAdd(c->bpop.keys,keys[j],bki) != DICT_OK) {
+            zfree(bki);
             continue;
         }
         incrRefCount(keys[j]);
@@ -545,6 +557,7 @@
             l = dictGetVal(de);
         }
         listAddNodeTail(l,c);
+        bki->listnode = listLast(l);
     }
     blockClient(c,btype);
 }
@@ -561,11 +574,12 @@
     /* The client may wait for multiple keys, so unblock it for every key. */
     while((de = dictNext(di)) != NULL) {
         robj *key = dictGetKey(de);
+        bkinfo *bki = dictGetVal(de);
 
         /* Remove this client from the list of clients waiting for this key. */
         l = dictFetchValue(c->db->blocking_keys,key);
         serverAssertWithInfo(c,key,l != NULL);
-        listDelNode(l,listSearchKey(l,c));
+        listDelNode(l,bki->listnode);
         /* If the list is empty we need to remove it to avoid wasting memory */
         if (listLength(l) == 0)
             dictDelete(c->db->blocking_keys,key);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.0.8/src/server.c new/redis-5.0.9/src/server.c
--- old/redis-5.0.8/src/server.c        2020-03-12 16:07:44.000000000 +0100
+++ new/redis-5.0.9/src/server.c        2020-04-17 12:45:57.000000000 +0200
@@ -987,7 +987,7 @@
         /* Rotate the list, take the current head, process.
          * This way if the client must be removed from the list it's the
          * first element and we don't incur into O(N) computation. */
-        listRotate(server.clients);
+        listRotateTailToHead(server.clients);
         head = listFirst(server.clients);
         c = listNodeValue(head);
         /* The following functions do different service checks on the client.
@@ -2336,8 +2336,13 @@
  * + PROPAGATE_AOF (propagate into the AOF file if is enabled)
  * + PROPAGATE_REPL (propagate into the replication link)
  *
- * This should not be used inside commands implementation. Use instead
- * alsoPropagate(), preventCommandPropagation(), forceCommandPropagation().
+ * This should not be used inside commands implementation since it will not
+ * wrap the resulting commands in MULTI/EXEC. Use instead alsoPropagate(),
+ * preventCommandPropagation(), forceCommandPropagation().
+ *
+ * However for functions that need to (also) propagate out of the context of a
+ * command execution, for example when serving a blocked client, you
+ * want to use propagate().
  */
 void propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,
                int flags)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.0.8/src/t_stream.c 
new/redis-5.0.9/src/t_stream.c
--- old/redis-5.0.8/src/t_stream.c      2020-03-12 16:07:44.000000000 +0100
+++ new/redis-5.0.9/src/t_stream.c      2020-04-17 12:45:57.000000000 +0200
@@ -842,7 +842,7 @@
     argv[11] = createStringObject("JUSTID",6);
     argv[12] = createStringObject("LASTID",6);
     argv[13] = createObjectFromStreamID(&group->last_id);
-    
alsoPropagate(server.xclaimCommand,c->db->id,argv,14,PROPAGATE_AOF|PROPAGATE_REPL);
+    
propagate(server.xclaimCommand,c->db->id,argv,14,PROPAGATE_AOF|PROPAGATE_REPL);
     decrRefCount(argv[0]);
     decrRefCount(argv[3]);
     decrRefCount(argv[4]);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/redis-5.0.8/src/version.h 
new/redis-5.0.9/src/version.h
--- old/redis-5.0.8/src/version.h       2020-03-12 16:07:44.000000000 +0100
+++ new/redis-5.0.9/src/version.h       2020-04-17 12:45:57.000000000 +0200
@@ -1 +1 @@
-#define REDIS_VERSION "5.0.8"
+#define REDIS_VERSION "5.0.9"


Reply via email to