static int _zremiterator(rlite *db, const unsigned char *key, long keylen, long levels_page_number, rl_zset_iterator *iterator, rl_btree *scores, long scores_page, rl_skiplist *skiplist, long skiplist_page, long *changed) { long _changed = 0; double score; unsigned char *member; long memberlen; int retval; while ((retval = rl_zset_iterator_next(iterator, &score, &member, &memberlen)) == RL_OK) { retval = remove_member_score(db, key, keylen, levels_page_number, scores, scores_page, skiplist, skiplist_page, member, memberlen, score); rl_free(member); if (retval != RL_OK && retval != RL_DELETED) { rl_zset_iterator_destroy(iterator); goto cleanup; } _changed++; } if (retval != RL_END) { goto cleanup; } *changed = _changed; retval = RL_OK; cleanup: return retval; }
static int zunionstore_sum(rlite *db, long keys_size, unsigned char **keys, long *keys_len, double *weights) { rl_skiplist_iterator *iterator = NULL; rl_skiplist *skiplist; double score; unsigned char *member; long memberlen; int retval; long i; for (i = 1; i < keys_size; i++) { retval = rl_zset_get_objects(db, keys[i], keys_len[i], NULL, NULL, NULL, &skiplist, NULL, 0, 0); if (retval == RL_NOT_FOUND) { continue; } if (retval != RL_OK) { goto cleanup; } RL_CALL(rl_skiplist_iterator_create, RL_OK, db, &iterator, skiplist, 0, 1, 0); while ((retval = rl_zset_iterator_next(iterator, &score, &member, &memberlen)) == RL_OK) { if (weights) { score *= weights[i - 1]; } if (isnan(score)) { score = 0.0; } retval = incrby(db, keys[0], keys_len[0], score, member, memberlen, NULL, 1); rl_free(member); if (retval != RL_OK) { goto cleanup; } } iterator = NULL; if (retval != RL_END) { goto cleanup; } } retval = RL_OK; cleanup: if (iterator) { rl_zset_iterator_destroy(iterator); } return retval; }
static int zunionstore_minmax(rlite *db, long keys_size, unsigned char **keys, long *keys_len, double *weights, int aggregate) { rl_btree *target_scores; long target_scores_page, target_skiplist_page; rl_skiplist *target_skiplist; int retval; rl_skiplist_iterator **iterators = NULL;; rl_skiplist *skiplist; double *scores = NULL, score; unsigned char **members = NULL; long *memberslen = NULL, i; long position; RL_CALL(rl_zset_get_objects, RL_OK, db, keys[0], keys_len[0], NULL, &target_scores, &target_scores_page, &target_skiplist, &target_skiplist_page, 1, 1); RL_MALLOC(scores, sizeof(double) * keys_size); RL_MALLOC(members, sizeof(unsigned char *) * keys_size); for (i = 0; i < keys_size; i++) { members[i] = NULL; } RL_MALLOC(memberslen, sizeof(long) * keys_size); RL_MALLOC(iterators, sizeof(rl_skiplist_iterator *) * keys_size); for (i = 0; i < keys_size; i++) { iterators[i] = NULL; } for (i = 0; i < keys_size; i++) { retval = rl_zset_get_objects(db, keys[i], keys_len[i], NULL, NULL, NULL, &skiplist, NULL, 0, 0); if (retval == RL_NOT_FOUND) { iterators[i] = NULL; continue; } if (retval != RL_OK) { goto cleanup; } RL_CALL(rl_skiplist_iterator_create, RL_OK, db, &iterators[i], skiplist, 0, aggregate == RL_ZSET_AGGREGATE_MAX ? -1 : 1, 0); retval = rl_zset_iterator_next(iterators[i], &scores[i], &members[i], &memberslen[i]); if (retval != RL_OK) { iterators[i] = NULL; if (retval != RL_END) { goto cleanup; } } } while (1) { position = -1; for (i = 0; i < keys_size; i++) { if (!iterators[i]) { continue; } if (position == -1) { position = i; continue; } score = weights ? weights[position - 1] * scores[position] : scores[position]; if (isnan(score)) { score = 0.0; } if ((aggregate == RL_ZSET_AGGREGATE_MAX && scores[i] > score) || (aggregate == RL_ZSET_AGGREGATE_MIN && scores[i] < score)) { position = i; } } if (position == -1) { break; } score = weights ? weights[position - 1] * scores[position] : scores[position]; if (isnan(score)) { score = 0.0; } retval = add_member(db, target_scores, target_scores_page, target_skiplist, target_skiplist_page, score, members[position], memberslen[position]); if (retval != RL_FOUND && retval != RL_OK) { goto cleanup; } rl_free(members[position]); members[position] = NULL; retval = rl_zset_iterator_next(iterators[position], &scores[position], &members[position], &memberslen[position]); if (retval != RL_OK) { iterators[position] = NULL; if (retval != RL_END) { goto cleanup; } } } if (target_scores->number_of_elements == 0) { RL_CALL(rl_key_delete_with_value, RL_OK, db, keys[0], keys_len[0]); } retval = RL_OK; cleanup: if (iterators) { for (i = 0; i < keys_size; i++) { if (iterators[i]) { rl_zset_iterator_destroy(iterators[i]); } rl_free(members[i]); } } rl_free(iterators); rl_free(memberslen); rl_free(members); rl_free(scores); return retval; }
int rl_dump(struct rlite *db, const unsigned char *key, long keylen, unsigned char **data, long *datalen) { int retval; uint64_t crc; unsigned char type; unsigned char *value = NULL, *value2 = NULL; unsigned char *buf = NULL; long buflen; long valuelen, value2len; unsigned char **values = NULL; long i = -1, *valueslen = NULL; uint32_t length; double score; char f[40]; RL_CALL(rl_key_get, RL_FOUND, db, key, keylen, &type, NULL, NULL, NULL, NULL); if (type == RL_TYPE_STRING) { RL_CALL(rl_get, RL_OK, db, key, keylen, &value, &valuelen); RL_MALLOC(buf, sizeof(unsigned char) * (16 + valuelen)); buf[0] = REDIS_RDB_TYPE_STRING; buf[1] = (REDIS_RDB_32BITLEN << 6); length = htonl(valuelen); memcpy(&buf[2], &length, 4); memcpy(&buf[6], value, valuelen); buflen = valuelen + 6; } else if (type == RL_TYPE_LIST) { RL_CALL(rl_lrange, RL_OK, db, key, keylen, 0, -1, &valuelen, &values, &valueslen); buflen = 16; for (i = 0; i < valuelen; i++) { buflen += 5 + valueslen[i]; } RL_MALLOC(buf, sizeof(unsigned char) * buflen); buf[0] = REDIS_RDB_TYPE_LIST; buf[1] = (REDIS_RDB_32BITLEN << 6); length = htonl(valuelen); memcpy(&buf[2], &length, 4); buflen = 6; for (i = 0; i < valuelen; i++) { buf[buflen++] = (REDIS_RDB_32BITLEN << 6); length = htonl(valueslen[i]); memcpy(&buf[buflen], &length, 4); buflen += 4; memcpy(&buf[buflen], values[i], valueslen[i]); buflen += valueslen[i]; } } else if (type == RL_TYPE_SET) { rl_set_iterator *iterator; RL_CALL(rl_smembers, RL_OK, db, &iterator, key, keylen); buflen = 16; length = 0; while ((retval = rl_set_iterator_next(iterator, NULL, &valuelen)) == RL_OK) { buflen += 5 + valuelen; length++; } if (retval != RL_END) { goto cleanup; } RL_MALLOC(buf, sizeof(unsigned char) * buflen); buf[0] = REDIS_RDB_TYPE_SET; buf[1] = (REDIS_RDB_32BITLEN << 6); length = htonl(length); memcpy(&buf[2], &length, 4); buflen = 6; RL_CALL(rl_smembers, RL_OK, db, &iterator, key, keylen); while ((retval = rl_set_iterator_next(iterator, &value, &valuelen)) == RL_OK) { buf[buflen++] = (REDIS_RDB_32BITLEN << 6); length = htonl(valuelen); memcpy(&buf[buflen], &length, 4); buflen += 4; memcpy(&buf[buflen], value, valuelen); buflen += valuelen; rl_free(value); value = NULL; } if (retval != RL_END) { goto cleanup; } } else if (type == RL_TYPE_ZSET) { rl_zset_iterator *iterator; RL_CALL(rl_zrange, RL_OK, db, key, keylen, 0, -1, &iterator); buflen = 16; length = 0; while ((retval = rl_zset_iterator_next(iterator, &score, NULL, &valuelen)) == RL_OK) { buflen += 6 + valuelen + snprintf(f, 40, "%lf", score); length++; } if (retval != RL_END) { goto cleanup; } RL_MALLOC(buf, sizeof(unsigned char) * buflen); buf[0] = REDIS_RDB_TYPE_ZSET; buf[1] = (REDIS_RDB_32BITLEN << 6); length = htonl(length); memcpy(&buf[2], &length, 4); buflen = 6; RL_CALL(rl_zrange, RL_OK, db, key, keylen, 0, -1, &iterator); while ((retval = rl_zset_iterator_next(iterator, &score, &value, &valuelen)) == RL_OK) { buf[buflen++] = (REDIS_RDB_32BITLEN << 6); length = htonl(valuelen); memcpy(&buf[buflen], &length, 4); buflen += 4; memcpy(&buf[buflen], value, valuelen); buflen += valuelen; rl_free(value); value = NULL; valuelen = snprintf(f, 40, "%lf", score); buf[buflen++] = valuelen; memcpy(&buf[buflen], f, valuelen); buflen += valuelen; } if (retval != RL_END) { goto cleanup; } } else if (type == RL_TYPE_HASH) { rl_hash_iterator *iterator; RL_CALL(rl_hgetall, RL_OK, db, &iterator, key, keylen); buflen = 16; length = 0; while ((retval = rl_hash_iterator_next(iterator, NULL, &value2len, NULL, &valuelen)) == RL_OK) { buflen += 10 + valuelen + value2len; length++; } if (retval != RL_END) { goto cleanup; } RL_MALLOC(buf, sizeof(unsigned char) * buflen); buf[0] = REDIS_RDB_TYPE_HASH; buf[1] = (REDIS_RDB_32BITLEN << 6); length = htonl(length); memcpy(&buf[2], &length, 4); buflen = 6; RL_CALL(rl_hgetall, RL_OK, db, &iterator, key, keylen); while ((retval = rl_hash_iterator_next(iterator, &value, &valuelen, &value2, &value2len)) == RL_OK) { buf[buflen++] = (REDIS_RDB_32BITLEN << 6); length = htonl(valuelen); memcpy(&buf[buflen], &length, 4); buflen += 4; memcpy(&buf[buflen], value, valuelen); buflen += valuelen; rl_free(value); value = NULL; buf[buflen++] = (REDIS_RDB_32BITLEN << 6); length = htonl(value2len); memcpy(&buf[buflen], &length, 4); buflen += 4; memcpy(&buf[buflen], value2, value2len); buflen += value2len; rl_free(value2); value2 = NULL; } } else { retval = RL_UNEXPECTED; goto cleanup; } buf[buflen++] = REDIS_RDB_VERSION; buf[buflen++] = REDIS_RDB_VERSION >> 8; crc = rl_crc64(0, buf, buflen); memrev64ifbe(&crc); memcpy(&buf[buflen], &crc, 8); buflen += 8; *data = buf; *datalen = buflen; retval = RL_OK; cleanup: if (values) { for (i = 0; i < valuelen; i++) { rl_free(values[i]); } rl_free(values); } rl_free(valueslen); rl_free(value); rl_free(value2); return retval; }