All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.moilioncircle.redis.replicator.rdb.RdbParser Maven / Gradle / Ivy

Go to download

Redis Replicator implement Redis Replication protocol written in java. It can parse,filter,broadcast the RDB and AOF events in a real time manner. It also can synchronize redis data to your local cache or to database.

There is a newer version: 3.8.1
Show newest version
/*
 * Copyright 2016-2018 Leon Chen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.moilioncircle.redis.replicator.rdb;

import com.moilioncircle.redis.replicator.AbstractReplicator;
import com.moilioncircle.redis.replicator.event.Event;
import com.moilioncircle.redis.replicator.event.PostRdbSyncEvent;
import com.moilioncircle.redis.replicator.event.PreRdbSyncEvent;
import com.moilioncircle.redis.replicator.io.RedisInputStream;
import com.moilioncircle.redis.replicator.rdb.datatype.ContextKeyValuePair;
import com.moilioncircle.redis.replicator.rdb.datatype.DB;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

import static com.moilioncircle.redis.replicator.Constants.RDB_OPCODE_AUX;
import static com.moilioncircle.redis.replicator.Constants.RDB_OPCODE_EOF;
import static com.moilioncircle.redis.replicator.Constants.RDB_OPCODE_EXPIRETIME;
import static com.moilioncircle.redis.replicator.Constants.RDB_OPCODE_EXPIRETIME_MS;
import static com.moilioncircle.redis.replicator.Constants.RDB_OPCODE_FREQ;
import static com.moilioncircle.redis.replicator.Constants.RDB_OPCODE_IDLE;
import static com.moilioncircle.redis.replicator.Constants.RDB_OPCODE_MODULE_AUX;
import static com.moilioncircle.redis.replicator.Constants.RDB_OPCODE_RESIZEDB;
import static com.moilioncircle.redis.replicator.Constants.RDB_OPCODE_SELECTDB;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_HASH;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_HASH_ZIPLIST;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_HASH_ZIPMAP;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_LIST;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_LIST_QUICKLIST;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_LIST_ZIPLIST;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_MODULE;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_MODULE_2;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_SET;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_SET_INTSET;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_STREAM_LISTPACKS;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_STRING;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_ZSET;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_ZSET_2;
import static com.moilioncircle.redis.replicator.Constants.RDB_TYPE_ZSET_ZIPLIST;
import static com.moilioncircle.redis.replicator.Status.CONNECTED;
import static com.moilioncircle.redis.replicator.util.Tuples.of;

/**
 * Redis RDB format
 * 

* * @author Leon Chen * @see rdb.c * @see Redis rdb dump data format * @since 2.1.0 */ public class RdbParser { protected final RedisInputStream in; protected final RdbVisitor rdbVisitor; protected final AbstractReplicator replicator; protected static final Logger logger = LoggerFactory.getLogger(RdbParser.class); public RdbParser(RedisInputStream in, AbstractReplicator replicator) { this.in = in; this.replicator = replicator; this.rdbVisitor = this.replicator.getRdbVisitor(); } /** * The RDB E-BNF *

* RDB = 'REDIS', $version, [AUX], [MODULE_AUX], {SELECTDB, [RESIZEDB], {RECORD}}, '0xFF', [$checksum]; *

* RECORD = [EXPIRED], [IDLE | FREQ], KEY, VALUE; *

* SELECTDB = '0xFE', $length; *

* AUX = {'0xFA', $string, $string}; (*Introduced in rdb version 7*) *

* MODULE_AUX = {'0xF7', $length}; (*Introduced in rdb version 9*) *

* RESIZEDB = '0xFB', $length, $length; (*Introduced in rdb version 7*) *

* EXPIRED = ('0xFD', $second) | ('0xFC', $millisecond); *

* IDLE = {'0xF8', $value-type}; (*Introduced in rdb version 9*) *

* FREQ = {'0xF9', $length}; (*Introduced in rdb version 9*) *

* KEY = $string; *

* VALUE = $value-type, ( $string *

* | $list *

* | $set *

* | $zset *

* | $hash *

* | $zset2 (*Introduced in rdb version 8*) *

* | $module (*Introduced in rdb version 8*) *

* | $module2 (*Introduced in rdb version 8*) *

* | $hashzipmap *

* | $listziplist *

* | $setintset *

* | $zsetziplist *

* | $hashziplist *

* | $listquicklist (*Introduced in rdb version 7*) *

* | $streamlistpacks); (*Introduced in rdb version 9*) *

* * @return read bytes * @throws IOException when read timeout */ public long parse() throws IOException { /* * ---------------------------- * 52 45 44 49 53 # Magic String "REDIS" * 30 30 30 33 # RDB Version Number in big endian. In this case, version = 0003 = 3 * ---------------------------- */ long offset = 0L; this.replicator.submitEvent(new PreRdbSyncEvent(), of(0L, 0L)); in.mark(); rdbVisitor.applyMagic(in); int version = rdbVisitor.applyVersion(in); offset += in.unmark(); DB db = null; /* * rdb */ loop: while (this.replicator.getStatus() == CONNECTED) { Event event = null; in.mark(); int type = rdbVisitor.applyType(in); ContextKeyValuePair kv = new ContextKeyValuePair(); kv.setDb(db); switch (type) { case RDB_OPCODE_EXPIRETIME: event = rdbVisitor.applyExpireTime(in, version, kv); break; case RDB_OPCODE_EXPIRETIME_MS: event = rdbVisitor.applyExpireTimeMs(in, version, kv); break; case RDB_OPCODE_FREQ: event = rdbVisitor.applyFreq(in, version, kv); break; case RDB_OPCODE_IDLE: event = rdbVisitor.applyIdle(in, version, kv); break; case RDB_OPCODE_AUX: event = rdbVisitor.applyAux(in, version); break; case RDB_OPCODE_MODULE_AUX: event = rdbVisitor.applyModuleAux(in, version); break; case RDB_OPCODE_RESIZEDB: rdbVisitor.applyResizeDB(in, version, kv); break; case RDB_OPCODE_SELECTDB: db = rdbVisitor.applySelectDB(in, version); break; case RDB_OPCODE_EOF: long checksum = rdbVisitor.applyEof(in, version); long start = offset; offset += in.unmark(); this.replicator.submitEvent(new PostRdbSyncEvent(checksum), of(start, offset)); break loop; case RDB_TYPE_STRING: event = rdbVisitor.applyString(in, version, kv); break; case RDB_TYPE_LIST: event = rdbVisitor.applyList(in, version, kv); break; case RDB_TYPE_SET: event = rdbVisitor.applySet(in, version, kv); break; case RDB_TYPE_ZSET: event = rdbVisitor.applyZSet(in, version, kv); break; case RDB_TYPE_ZSET_2: event = rdbVisitor.applyZSet2(in, version, kv); break; case RDB_TYPE_HASH: event = rdbVisitor.applyHash(in, version, kv); break; case RDB_TYPE_HASH_ZIPMAP: event = rdbVisitor.applyHashZipMap(in, version, kv); break; case RDB_TYPE_LIST_ZIPLIST: event = rdbVisitor.applyListZipList(in, version, kv); break; case RDB_TYPE_SET_INTSET: event = rdbVisitor.applySetIntSet(in, version, kv); break; case RDB_TYPE_ZSET_ZIPLIST: event = rdbVisitor.applyZSetZipList(in, version, kv); break; case RDB_TYPE_HASH_ZIPLIST: event = rdbVisitor.applyHashZipList(in, version, kv); break; case RDB_TYPE_LIST_QUICKLIST: event = rdbVisitor.applyListQuickList(in, version, kv); break; case RDB_TYPE_MODULE: event = rdbVisitor.applyModule(in, version, kv); break; case RDB_TYPE_MODULE_2: event = rdbVisitor.applyModule2(in, version, kv); break; case RDB_TYPE_STREAM_LISTPACKS: event = rdbVisitor.applyStreamListPacks(in, version, kv); break; default: throw new AssertionError("unexpected value type:" + type + ", check your ModuleParser or ValueIterableRdbVisitor."); } long start = offset; offset += in.unmark(); if (event == null) continue; if (replicator.verbose() && logger.isDebugEnabled()) logger.debug("{}", event); this.replicator.submitEvent(event, of(start, offset)); } return offset; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy