Esempio n. 1
0
 def auth(self, password):
     if config.get('requirepass') == config.EMPTY:
         raise DredisError("client sent AUTH, but no password is set")
     if password != config.get('requirepass'):
         self.authenticated = False
         raise DredisError("invalid password")
     else:
         self.authenticated = True
Esempio n. 2
0
def cmd_zadd(keyspace, key, *args):
    nx = False
    xx = False
    start_index = 0

    for i, arg in enumerate(args):
        if arg.lower() == 'nx':
            nx = True
        elif arg.lower() == 'xx':
            xx = True
        else:
            break
        start_index = i + 1

    if nx and xx:
        raise DredisError(
            "XX and NX options at the same time are not compatible")

    args = args[start_index:]
    if len(args) % 2 != 0:
        raise DredisSyntaxError()

    count = 0
    pairs = zip(args[0::2], args[1::2])  # [1, 2, 3, 4] -> [(1,2), (3,4)]
    for score, value in pairs:
        _validate_zset_score(score)
        count += keyspace.zadd(key, score, value, nx=nx, xx=xx)
    return count
Esempio n. 3
0
File: rdb.py Progetto: Yipit/dredis
 def _dump_encoded_string(self, value):
     if (value >= -(1 << 7)) and (value <= (1 << 7) - 1):
         return struct.pack('<Bb', (RDB_ENCVAL << 6) | RDB_ENC_INT8, value)
     elif (value >= -(1 << 15)) and (value <= (1 << 15) - 1):
         return struct.pack('<Bh', (RDB_ENCVAL << 6) | RDB_ENC_INT16, value)
     elif (value >= -(1 << 31)) and (value <= (1 << 31) - 1):
         return struct.pack('<Bi', (RDB_ENCVAL << 6) | RDB_ENC_INT32, value)
     else:
         raise DredisError("can't encode %r as integer" % value)
Esempio n. 4
0
File: rdb.py Progetto: Yipit/dredis
 def dump(self, key, key_type):
     if key_type == 'string':
         return self.dump_string(key)
     if key_type == 'set':
         return self.dump_set(key)
     if key_type == 'hash':
         return self.dump_hash(key)
     if key_type == 'zset':
         return self.dump_zset(key)
     raise DredisError("Can't convert %r" % key_type)
Esempio n. 5
0
File: rdb.py Progetto: Yipit/dredis
def verify_payload(payload):
    bad_payload = DredisError('DUMP payload version or checksum are wrong')
    if len(payload) < 10:
        raise bad_payload
    data, footer = payload[:-10], payload[-10:]
    rdb_version, crc = footer[:2], footer[2:]
    if rdb_version > get_rdb_version():
        raise bad_payload
    if crc64.checksum(data + rdb_version) != crc:
        raise bad_payload
Esempio n. 6
0
File: rdb.py Progetto: Yipit/dredis
    def load_rdb(self):
        """
        inspired heavily by rdb.c:rdbLoad()
        """
        header = self.file.read(self.REDIS_VERSION_HEADER_LENGTH)
        if not header.startswith("REDIS"):
            raise DredisError("Wrong signature trying to load DB from file")
        version = header[-self.REDIS_VERSION_LENGTH:]
        if not version.isdigit() or int(version) > RDB_VERSION:
            raise DredisError("Can't handle RDB format version %s" % version)

        while True:
            obj_type = self.load_type()
            if obj_type == RDB_OPCODE_EXPIRETIME:
                self.file.read(4)  # rdbLoadTime() reads 4 bytes
                obj_type = self.load_type()
                logger.warning(
                    "Key expiration isn't supported, skipping expiration (RDB_OPCODE_EXPIRETIME)"
                )
            elif obj_type == RDB_OPCODE_EXPIRETIME_MS:
                self.file.read(8)  # rdbLoadMillisecondTime() reads 8 bytes
                obj_type = self.load_type()
                logger.warning(
                    "Key expiration isn't supported, skipping expiration (RDB_OPCODE_EXPIRETIME_MS)"
                )
            elif obj_type == RDB_OPCODE_EOF:
                break
            elif obj_type == RDB_OPCODE_SELECTDB:
                # FIXME: at the moment only add keys to the default db
                self.load_len()
                continue
            elif obj_type == RDB_OPCODE_AUX:
                # ignoring aux field=value
                self._load_string()
                self._load_string()
                continue
            elif obj_type == RDB_OPCODE_RESIZEDB:
                # ignoring db_size & expires_size
                self.load_len()
                self.load_len()
                continue
            key = self._load_string()
            self._load(key, obj_type)
Esempio n. 7
0
def set(option, value):
    if option in _SERVER_CONFIG:
        if option == 'debug':
            value = _validate_bool(option, value)
            if value == TRUE:
                logging.getLogger('dredis').setLevel(logging.DEBUG)
            else:
                logging.getLogger('dredis').setLevel(logging.INFO)
        elif option == 'readonly':
            value = _validate_bool(option, value)
        _SERVER_CONFIG[option] = value
    else:
        raise DredisError('Unsupported CONFIG parameter: {}'.format(option))
Esempio n. 8
0
File: rdb.py Progetto: Yipit/dredis
 def _load_encoded_string(self, enctype):
     if enctype == RDB_ENC_INT8:
         result = read_signed_char(self.file)
     elif enctype == RDB_ENC_INT16:
         result = read_signed_short(self.file)
     elif enctype == RDB_ENC_INT32:
         result = read_signed_int(self.file)
     elif enctype == RDB_ENC_LZF:
         compressed_len = self.load_len()
         out_max_len = self.load_len()
         data = self.file.read(compressed_len)
         result = lzf.decompress(data, out_max_len)
     else:
         raise DredisError("Unknown RDB string encoding type %d" % enctype)
     return bytes(result)
Esempio n. 9
0
def _validate_scan_params(args, cursor):
    match = None
    count = 10
    args = list(args)
    try:
        cursor = int(cursor)
    except ValueError:
        raise DredisError("invalid cursor")
    while args:
        arg = args.pop(0)
        if len(args) < 1:
            raise DredisSyntaxError()
        else:
            if arg.lower() == 'match':
                match = args.pop(0)
            elif arg.lower() == 'count':
                try:
                    count = int(args.pop(0))
                except ValueError:
                    raise DredisError(
                        "value is not an integer or out of range")
            else:
                raise DredisSyntaxError()
    return cursor, count, match
Esempio n. 10
0
def run_command(keyspace, cmd, args):
    logger.debug('[run_command] cmd={}, args={}'.format(repr(cmd), repr(args)))

    str_args = map(str, args)
    if cmd.upper() not in REDIS_COMMANDS:
        raise CommandNotFound("unknown command '{}'".format(cmd))
    else:
        cmd_fn = REDIS_COMMANDS[cmd.upper()]
        if config.get(
                'requirepass'
        ) != config.EMPTY and not keyspace.authenticated and cmd_fn != cmd_auth:
            raise AuthenticationRequiredError()
        if config.get('readonly') == config.TRUE and cmd_fn.flags & CMD_WRITE:
            raise DredisError("Can't execute %r in readonly mode" % cmd)
        else:
            return cmd_fn(keyspace, *str_args)
Esempio n. 11
0
def cmd_config(keyspace, action, *params):
    if action.lower() == 'help':
        # copied from
        # https://github.com/antirez/redis/blob/cb51bb4320d2240001e8fc4a522d59fb28259703/src/config.c#L2244-L2245
        help = [
            "GET <pattern> -- Return parameters matching the glob-like <pattern> and their values.",
            "SET <parameter> <value> -- Set parameter to value.",
        ]
        return help
    elif action.lower() == 'get' and len(params) == 1:
        return config.get_all(params[0])
    elif action.lower() == 'set' and len(params) == 2:
        config.set(params[0], params[1])
        return SimpleString('OK')
    else:
        raise DredisError(
            "Unknown subcommand or wrong number of arguments for '{}'. Try CONFIG HELP."
            .format(action))
Esempio n. 12
0
File: rdb.py Progetto: Yipit/dredis
 def load_intset(self, key):
     """
     based on intset.h and https://github.com/sripathikrishnan/redis-rdb-tools/blob/543a73e84702e911ddcd31325ecfde77d7fd230b/rdbtools/parser.py#L665-L681
     """  # noqa
     intset = BytesIO(self._load_string())
     encoding = read_unsigned_int(intset)
     length = read_unsigned_int(intset)
     for _ in xrange(length):
         if encoding == INTSET_ENC_INT16:
             entry = read_signed_short(intset)
         elif encoding == INTSET_ENC_INT32:
             entry = read_signed_int(intset)
         elif encoding == INTSET_ENC_INT64:
             entry = read_signed_long(intset)
         else:
             raise DredisError('Invalid encoding %r for intset (key = %r)' %
                               (encoding, key))
         self.keyspace.sadd(key, entry)
Esempio n. 13
0
File: rdb.py Progetto: Yipit/dredis
    def _load_ziplist(self, key):
        """
        From ziplist.c:
            * ZIPLIST OVERALL LAYOUT:
            * The general layout of the ziplist is as follows:
            * <zlbytes><zltail><zllen><entry><entry><zlend>
        """
        ziplist = BytesIO(self._load_string())
        zlbytes = read_unsigned_int(ziplist)  # noqa
        zltail = read_unsigned_int(ziplist)  # noqa
        zllen = read_unsigned_short(ziplist)

        for _ in xrange(zllen):
            yield bytes(self._read_ziplist_entry(ziplist, key))

        zlend = read_unsigned_char(ziplist)
        if zlend != ZIP_END:
            raise DredisError("Invalid ziplist end %r (key = %r)" %
                              (zlend, key))
Esempio n. 14
0
 def rename(self, old_name, new_name):
     if self.exists(old_name):
         if old_name == new_name:
             return
         # replace the key that holds the key ID and don't touch the rest
         key_type = self.type(old_name)
         if key_type == 'zset':
             old_db_key = KEY_CODEC.encode_zset(old_name)
             new_db_key = KEY_CODEC.encode_zset(new_name)
         elif key_type == 'hash':
             old_db_key = KEY_CODEC.encode_hash(old_name)
             new_db_key = KEY_CODEC.encode_hash(new_name)
         elif key_type == 'set':
             old_db_key = KEY_CODEC.encode_set(old_name)
             new_db_key = KEY_CODEC.encode_set(new_name)
         elif key_type == 'string':
             old_db_key = KEY_CODEC.encode_string(old_name)
             new_db_key = KEY_CODEC.encode_string(new_name)
         else:
             raise DredisError("invalid key type")
         self._replace_db_key(new_db_key, old_db_key)
     else:
         raise NoKeyError()
Esempio n. 15
0
File: rdb.py Progetto: Yipit/dredis
 def _read_ziplist_entry(self, f, key):
     """
     Copied and adapted from
     https://github.com/sripathikrishnan/redis-rdb-tools/blob/543a73e84702e911ddcd31325ecfde77d7fd230b/rdbtools/parser.py#L757-L787
     """  # noqa
     length = 0
     value = None
     prev_length = read_unsigned_char(f)
     if prev_length == ZIP_BIGLEN:
         prev_length = read_unsigned_int(f)
     entry_header = read_unsigned_char(f)
     if (entry_header >> 6) == 0:
         length = entry_header & 0x3F
         value = f.read(length)
     elif (entry_header >> 6) == 1:
         length = ((entry_header & 0x3F) << 8) | read_unsigned_char(f)
         value = f.read(length)
     elif (entry_header >> 6) == 2:
         length = read_unsigned_int_be(f)
         value = f.read(length)
     elif (entry_header >> 4) == 12:
         value = read_signed_short(f)
     elif (entry_header >> 4) == 13:
         value = read_signed_int(f)
     elif (entry_header >> 4) == 14:
         value = read_signed_long(f)
     elif (entry_header == 240):
         value = read_24bit_signed_number(f)
     elif (entry_header == 254):
         value = read_signed_char(f)
     elif (entry_header >= 241 and entry_header <= 253):
         value = entry_header - 241
     else:
         raise DredisError('Invalid ziplist entry_header %d for key %s' %
                           (entry_header, key))
     return value
Esempio n. 16
0
def _validate_bool(option, value):
    if value.lower() not in (TRUE, FALSE):
        raise DredisError("Invalid argument '{}' for CONFIG SET '{}'".format(
            value, option))
    return value.lower()
Esempio n. 17
0
File: rdb.py Progetto: Yipit/dredis
RDB_ENCVAL = 3
RDB_ENC_INT8 = 0
RDB_ENC_INT16 = 1
RDB_ENC_INT32 = 2
RDB_ENC_LZF = 3

RDB_OPCODE_AUX = 250
RDB_OPCODE_RESIZEDB = 251
RDB_OPCODE_EXPIRETIME_MS = 252
RDB_OPCODE_EXPIRETIME = 253
RDB_OPCODE_SELECTDB = 254
RDB_OPCODE_EOF = 255

RDB_VERSION = 7

BAD_DATA_FORMAT_ERR = DredisError("Bad data format")


def get_rdb_version():
    """
    :return: little endian encoded 2-byte RDB version
    """
    return struct.pack('<BB', RDB_VERSION & 0xff, (RDB_VERSION >> 8) & 0xff)


def load_object(keyspace, key, rdb_file):
    object_loader = ObjectLoader(keyspace, rdb_file)
    object_loader.load(key)


def generate_payload(keyspace, key):