• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

leonchen83 / redis-replicator / #2187

07 Jun 2025 09:11AM UTC coverage: 69.535% (-0.5%) from 69.989%
#2187

push

leonchen83
redis-8.0

1 of 123 new or added lines in 13 files covered. (0.81%)

1 existing line in 1 file now uncovered.

6642 of 9552 relevant lines covered (69.54%)

0.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.5
/src/main/java/com/moilioncircle/redis/replicator/rdb/iterable/ValueIterableEventListener.java
1
/*
2
 * Copyright 2016-2018 Leon Chen
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package com.moilioncircle.redis.replicator.rdb.iterable;
18

19
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_SET;
20
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_SET_INTSET;
21
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_SET_LISTPACK;
22
import static com.moilioncircle.redis.replicator.rdb.datatype.KeyValuePairs.hash;
23
import static com.moilioncircle.redis.replicator.rdb.datatype.KeyValuePairs.list;
24
import static com.moilioncircle.redis.replicator.rdb.datatype.KeyValuePairs.ttlHash;
25
import static com.moilioncircle.redis.replicator.rdb.datatype.KeyValuePairs.module;
26
import static com.moilioncircle.redis.replicator.rdb.datatype.KeyValuePairs.set;
27
import static com.moilioncircle.redis.replicator.rdb.datatype.KeyValuePairs.stream;
28
import static com.moilioncircle.redis.replicator.rdb.datatype.KeyValuePairs.string;
29
import static com.moilioncircle.redis.replicator.rdb.datatype.KeyValuePairs.zset;
30

31
import java.util.HashSet;
32
import java.util.Iterator;
33
import java.util.LinkedHashSet;
34
import java.util.List;
35
import java.util.Map;
36
import java.util.Set;
37

38
import com.moilioncircle.redis.replicator.Replicator;
39
import com.moilioncircle.redis.replicator.event.Event;
40
import com.moilioncircle.redis.replicator.event.EventListener;
41
import com.moilioncircle.redis.replicator.rdb.datatype.TTLValue;
42
import com.moilioncircle.redis.replicator.rdb.datatype.KeyStringValueModule;
43
import com.moilioncircle.redis.replicator.rdb.datatype.KeyStringValueStream;
44
import com.moilioncircle.redis.replicator.rdb.datatype.KeyStringValueString;
45
import com.moilioncircle.redis.replicator.rdb.datatype.KeyValuePair;
46
import com.moilioncircle.redis.replicator.rdb.datatype.Module;
47
import com.moilioncircle.redis.replicator.rdb.datatype.Stream;
48
import com.moilioncircle.redis.replicator.rdb.datatype.ZSetEntry;
49
import com.moilioncircle.redis.replicator.rdb.iterable.datatype.KeyStringValueByteArrayIterator;
50
import com.moilioncircle.redis.replicator.rdb.iterable.datatype.KeyStringValueTTLMapEntryIterator;
51
import com.moilioncircle.redis.replicator.rdb.iterable.datatype.KeyStringValueMapEntryIterator;
52
import com.moilioncircle.redis.replicator.rdb.iterable.datatype.KeyStringValueZSetEntryIterator;
53
import com.moilioncircle.redis.replicator.util.TTLByteArrayMap;
54
import com.moilioncircle.redis.replicator.util.ByteArrayList;
55
import com.moilioncircle.redis.replicator.util.ByteArrayMap;
56
import com.moilioncircle.redis.replicator.util.ByteArraySet;
57

58
/**
59
 * @author Leon Chen
60
 * @since 2.5.0
61
 */
62
public class ValueIterableEventListener implements EventListener {
63
    
64
    private final int batchSize;
65
    private final boolean order;
66
    private final EventListener listener;
67
    
68
    public ValueIterableEventListener(EventListener listener) {
69
        this(64, listener);
1✔
70
    }
1✔
71
    
72
    public ValueIterableEventListener(int batchSize, EventListener listener) {
73
        this(true, batchSize, listener);
1✔
74
    }
1✔
75
    
76
    public ValueIterableEventListener(boolean order, int batchSize, EventListener listener) {
1✔
77
        if (batchSize <= 0) throw new IllegalArgumentException(String.valueOf(batchSize));
1✔
78
        this.order = order;
1✔
79
        this.batchSize = batchSize;
1✔
80
        this.listener = listener;
1✔
81
    }
1✔
82
    
83
    @Override
84
    public void onEvent(Replicator replicator, Event event) {
85
        if (!(event instanceof KeyValuePair<?, ?>)) {
1✔
86
            listener.onEvent(replicator, event);
1✔
87
            return;
1✔
88
        }
89
        KeyValuePair<?, ?> kv = (KeyValuePair<?, ?>) event;
1✔
90
        // Note that:
91
        // Every Iterator MUST be consumed.
92
        // Before every it.next() MUST check precondition it.hasNext()
93
        int batch = 0;
1✔
94
        final int type = kv.getValueRdbType();
1✔
95
        if (kv instanceof KeyStringValueString) {
1✔
96
            KeyStringValueString ksvs = (KeyStringValueString) kv;
1✔
97
            listener.onEvent(replicator, string(ksvs, ksvs.getValue(), batch, true));
1✔
98
        } else if (kv instanceof KeyStringValueByteArrayIterator) {
1✔
99
            if (type == RDB_TYPE_SET || type == RDB_TYPE_SET_INTSET || type == RDB_TYPE_SET_LISTPACK) {
1✔
100
                KeyStringValueByteArrayIterator skv = (KeyStringValueByteArrayIterator) kv;
1✔
101
                Iterator<byte[]> it = skv.getValue();
1✔
102
                Set<byte[]> prev = null, next = new ByteArraySet(order, batchSize);
1✔
103
                while (it.hasNext()) {
1✔
104
                    next.add(it.next());
1✔
105
                    if (next.size() == batchSize) {
1✔
106
                        if (prev != null)
1✔
107
                            listener.onEvent(replicator, set(skv, prev, batch++, false));
1✔
108
                        prev = next;
1✔
109
                        next = create(order, batchSize);
1✔
110
                    }
111
                }
112
                final boolean last = next.isEmpty();
1✔
113
                if (prev != null) listener.onEvent(replicator, set(skv, prev, batch++, last));
1✔
114
                if (!last) listener.onEvent(replicator, set(skv, next, batch++, true));
1✔
115
            } else {
1✔
116
                KeyStringValueByteArrayIterator lkv = (KeyStringValueByteArrayIterator) kv;
1✔
117
                Iterator<byte[]> it = lkv.getValue();
1✔
118
                List<byte[]> prev = null, next = new ByteArrayList(batchSize);
1✔
119
                while (it.hasNext()) {
1✔
120
                    try {
121
                        next.add(it.next());
1✔
122
                        if (next.size() == batchSize) {
1✔
123
                            if (prev != null)
1✔
124
                                listener.onEvent(replicator, list(lkv, prev, batch++, false));
1✔
125
                            prev = next;
1✔
126
                            next = new ByteArrayList(batchSize);
1✔
127
                        }
128
                    } catch (IllegalStateException ignore) {
×
129
                        // see ValueIterableRdbVisitor.QuickListIter.next().
130
                        // see ValueIterableRdbVisitor.QuickList2Iter.next().
131
                    }
1✔
132
                }
133
                final boolean last = next.isEmpty();
1✔
134
                if (prev != null) listener.onEvent(replicator, list(lkv, prev, batch++, last));
1✔
135
                if (!last) listener.onEvent(replicator, list(lkv, next, batch++, true));
1✔
136
            }
1✔
137
        } else if (kv instanceof KeyStringValueMapEntryIterator) {
1✔
138
            KeyStringValueMapEntryIterator mkv = (KeyStringValueMapEntryIterator) kv;
1✔
139
            Iterator<Map.Entry<byte[], byte[]>> it = mkv.getValue();
1✔
140
            Map<byte[], byte[]> prev = null, next = new ByteArrayMap(order, batchSize);
1✔
141
            while (it.hasNext()) {
1✔
142
                Map.Entry<byte[], byte[]> entry = it.next();
1✔
143
                next.put(entry.getKey(), entry.getValue());
1✔
144
                if (next.size() == batchSize) {
1✔
145
                    if (prev != null)
1✔
146
                        listener.onEvent(replicator, hash(mkv, prev, batch++, false));
1✔
147
                    prev = next;
1✔
148
                    next = new ByteArrayMap(order, batchSize);
1✔
149
                }
150
            }
1✔
151
            final boolean last = next.isEmpty();
1✔
152
            if (prev != null) listener.onEvent(replicator, hash(mkv, prev, batch++, last));
1✔
153
            if (!last) listener.onEvent(replicator, hash(mkv, next, batch++, true));
1✔
154
        } else if (kv instanceof KeyStringValueTTLMapEntryIterator) {
1✔
NEW
155
            KeyStringValueTTLMapEntryIterator mkv = (KeyStringValueTTLMapEntryIterator) kv;
×
NEW
156
            Iterator<Map.Entry<byte[], TTLValue>> it = mkv.getValue();
×
NEW
157
            Map<byte[], TTLValue> prev = null, next = new TTLByteArrayMap(order, batchSize);
×
158
            while (it.hasNext()) {
×
NEW
159
                Map.Entry<byte[], TTLValue> entry = it.next();
×
160
                next.put(entry.getKey(), entry.getValue());
×
161
                if (next.size() == batchSize) {
×
162
                    if (prev != null)
×
NEW
163
                        listener.onEvent(replicator, ttlHash(mkv, prev, batch++, false));
×
164
                    prev = next;
×
NEW
165
                    next = new TTLByteArrayMap(order, batchSize);
×
166
                }
167
            }
×
168
            final boolean last = next.isEmpty();
×
NEW
169
            if (prev != null) listener.onEvent(replicator, ttlHash(mkv, prev, batch++, last));
×
NEW
170
            if (!last) listener.onEvent(replicator, ttlHash(mkv, next, batch++, true));
×
171
        } else if (kv instanceof KeyStringValueZSetEntryIterator) {
1✔
172
            KeyStringValueZSetEntryIterator zkv = (KeyStringValueZSetEntryIterator) kv;
1✔
173
            Iterator<ZSetEntry> it = zkv.getValue();
1✔
174
            Set<ZSetEntry> prev = null, next = create(order, batchSize);
1✔
175
            while (it.hasNext()) {
1✔
176
                next.add(it.next());
1✔
177
                if (next.size() == batchSize) {
1✔
178
                    if (prev != null)
1✔
179
                        listener.onEvent(replicator, zset(zkv, prev, batch++, false));
1✔
180
                    prev = next;
1✔
181
                    next = create(order, batchSize);
1✔
182
                }
183
            }
184
            final boolean last = next.isEmpty();
1✔
185
            if (prev != null) listener.onEvent(replicator, zset(zkv, prev, batch++, last));
1✔
186
            if (!last) listener.onEvent(replicator, zset(zkv, next, batch++, true));
1✔
187
        } else if (kv instanceof KeyStringValueModule) {
1✔
188
            listener.onEvent(replicator, module((KeyStringValueModule) kv, (Module) kv.getValue(), batch, true));
×
189
        } else if (kv instanceof KeyStringValueStream) {
1✔
190
            listener.onEvent(replicator, stream((KeyStringValueStream) kv, (Stream) kv.getValue(), batch, true));
1✔
191
        }
192
    }
1✔
193
    
194
    private <T> Set<T> create(boolean order, int batchSize) {
195
        return order ? new LinkedHashSet<T>(batchSize) : new HashSet<T>(batchSize);
1✔
196
    }
197
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc