mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-11 18:35:46 +02:00
chore: remove unused code (#4516)
Move PrimeBumpPolicy definition to cc file. Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
parent
d945b831db
commit
44506ad2a9
8 changed files with 24 additions and 636 deletions
|
@ -20,7 +20,7 @@ cxx_test(compact_object_test dfly_core LABELS DFLY)
|
|||
cxx_test(extent_tree_test dfly_core LABELS DFLY)
|
||||
cxx_test(dash_test dfly_core file redis_test_lib DATA testdata/ids.txt LABELS DFLY)
|
||||
cxx_test(interpreter_test dfly_core LABELS DFLY)
|
||||
cxx_test(lru_test dfly_core LABELS DFLY)
|
||||
|
||||
cxx_test(string_set_test dfly_core LABELS DFLY)
|
||||
cxx_test(string_map_test dfly_core LABELS DFLY)
|
||||
cxx_test(sorted_map_test dfly_core redis_test_lib LABELS DFLY)
|
||||
|
|
200
src/core/lru.h
200
src/core/lru.h
|
@ -1,200 +0,0 @@
|
|||
// Copyright 2023, DragonflyDB authors. All rights reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <absl/container/node_hash_map.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/pmr/memory_resource.h"
|
||||
|
||||
namespace dfly {
|
||||
|
||||
enum class Position {
|
||||
kHead,
|
||||
kTail,
|
||||
};
|
||||
|
||||
template <typename T> class Lru {
|
||||
struct Node {
|
||||
const T* data_ptr;
|
||||
|
||||
uint32_t prev;
|
||||
uint32_t next;
|
||||
|
||||
Node() : prev(0), next(0) {
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
explicit Lru(uint32_t capacity, PMR_NS::memory_resource* mr) : table_(mr), node_arr_(mr) {
|
||||
CHECK_GT(capacity, 1u);
|
||||
node_arr_.reserve(capacity);
|
||||
}
|
||||
|
||||
// Get prev item. In case item is head return tail.
|
||||
std::optional<T> GetPrev(const T& data) const;
|
||||
std::optional<T> GetTail() const;
|
||||
std::optional<T> GetHead() const;
|
||||
|
||||
void Put(const T& data, Position position = Position::kHead);
|
||||
bool Remove(const T& data);
|
||||
|
||||
size_t Size() const {
|
||||
DCHECK_EQ(table_.size(), node_arr_.size());
|
||||
return table_.size();
|
||||
}
|
||||
|
||||
private:
|
||||
void MoveToPosition(uint32_t index, Position position);
|
||||
using AllocatorType = PMR_NS::polymorphic_allocator<std::pair<T, uint32_t>>;
|
||||
absl::node_hash_map<T, uint32_t, absl::Hash<T>, std::equal_to<>, AllocatorType>
|
||||
table_; // map from item to index in node arr
|
||||
std::vector<Node, PMR_NS::polymorphic_allocator<Node>> node_arr_;
|
||||
uint32_t head_ = 0;
|
||||
};
|
||||
|
||||
template <typename T> std::optional<T> Lru<T>::GetPrev(const T& data) const {
|
||||
auto it = table_.find(data);
|
||||
if (it == table_.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
DCHECK_GT(node_arr_.size(), it->second);
|
||||
const auto& node = node_arr_[it->second];
|
||||
|
||||
DCHECK_EQ(node.data_ptr, &it->first);
|
||||
const auto& node_prev = node_arr_[node.prev];
|
||||
|
||||
return *node_prev.data_ptr;
|
||||
}
|
||||
|
||||
template <typename T> std::optional<T> Lru<T>::GetTail() const {
|
||||
if (table_.size() == 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
unsigned tail = node_arr_[head_].prev;
|
||||
return *node_arr_[tail].data_ptr;
|
||||
}
|
||||
|
||||
template <typename T> std::optional<T> Lru<T>::GetHead() const {
|
||||
if (table_.size() == 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return *node_arr_[head_].data_ptr;
|
||||
}
|
||||
|
||||
template <typename T> void Lru<T>::Put(const T& data, Position position) {
|
||||
DCHECK_EQ(table_.size(), node_arr_.size());
|
||||
auto [it, inserted] = table_.emplace(data, table_.size());
|
||||
if (inserted) {
|
||||
unsigned tail = 0;
|
||||
if (node_arr_.size() > 0) {
|
||||
tail = node_arr_[head_].prev;
|
||||
}
|
||||
|
||||
Node node;
|
||||
// add new item between head and tail.
|
||||
node.prev = tail;
|
||||
node.next = head_;
|
||||
node_arr_[tail].next = it->second;
|
||||
node_arr_[head_].prev = it->second;
|
||||
|
||||
node.data_ptr = &(it->first);
|
||||
node_arr_.push_back(node);
|
||||
|
||||
if (position == Position::kHead) {
|
||||
head_ = it->second;
|
||||
}
|
||||
} else { // not inserted.
|
||||
MoveToPosition(it->second, position);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> bool Lru<T>::Remove(const T& data) {
|
||||
auto it = table_.find(data);
|
||||
if (it == table_.end()) {
|
||||
return false;
|
||||
}
|
||||
uint32_t remove_index = it->second;
|
||||
auto& node = node_arr_[remove_index];
|
||||
|
||||
// remove from list
|
||||
node_arr_[node.prev].next = node.next;
|
||||
node_arr_[node.next].prev = node.prev;
|
||||
|
||||
// remove item from table.
|
||||
if (remove_index == head_) {
|
||||
head_ = node.next;
|
||||
}
|
||||
table_.erase(it);
|
||||
|
||||
if (table_.size() == remove_index) {
|
||||
node_arr_.pop_back();
|
||||
DCHECK_EQ(table_.size(), node_arr_.size());
|
||||
return true; // if the removed item was the last in the node array nothing else to do.
|
||||
}
|
||||
|
||||
// move last item from node array to the removed index
|
||||
uint32_t move_index = table_.size();
|
||||
auto& node_to_move = node_arr_[move_index];
|
||||
it = table_.find(*node_to_move.data_ptr);
|
||||
CHECK(it != table_.end());
|
||||
|
||||
it->second = remove_index;
|
||||
// now update the next and prev to point to it
|
||||
node_arr_[node_to_move.prev].next = remove_index;
|
||||
node_arr_[node_to_move.next].prev = remove_index;
|
||||
|
||||
// move the data from the node to the removed node.
|
||||
node = node_to_move;
|
||||
node_arr_.pop_back();
|
||||
|
||||
if (head_ == move_index) {
|
||||
head_ = remove_index;
|
||||
}
|
||||
DCHECK_EQ(table_.size(), node_arr_.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> void Lru<T>::MoveToPosition(uint32_t index, Position position) {
|
||||
DCHECK_LT(index, node_arr_.size());
|
||||
uint32_t tail = node_arr_[head_].prev;
|
||||
uint32_t curr_node_index = position == Position::kHead ? head_ : tail;
|
||||
if (index == curr_node_index) { // the index is already head/tail. nothing to change.
|
||||
return;
|
||||
}
|
||||
|
||||
auto& node = node_arr_[index];
|
||||
CHECK_NE(node.prev, node.next);
|
||||
|
||||
if (position == Position::kHead && index == tail) {
|
||||
head_ = index; // just shift the cycle.
|
||||
return;
|
||||
}
|
||||
if (position == Position::kTail && index == head_) {
|
||||
head_ = node.next; // just shift the cycle.
|
||||
return;
|
||||
}
|
||||
|
||||
// remove from list
|
||||
node_arr_[node.prev].next = node.next;
|
||||
node_arr_[node.next].prev = node.prev;
|
||||
|
||||
// update node next and prev
|
||||
node.prev = tail;
|
||||
node.next = head_;
|
||||
|
||||
// update tail to point to new head
|
||||
node_arr_[tail].next = index;
|
||||
|
||||
// update last head to point to new head
|
||||
node_arr_[head_].prev = index;
|
||||
|
||||
if (position == Position::kHead) {
|
||||
head_ = index;
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace dfly
|
|
@ -1,175 +0,0 @@
|
|||
// Copyright 2023, DragonflyDB authors. All rights reserved.
|
||||
// See LICENSE for licensing terms.
|
||||
//
|
||||
|
||||
#include "core/lru.h"
|
||||
|
||||
#include <absl/strings/str_cat.h>
|
||||
|
||||
#include "base/gtest.h"
|
||||
#include "base/logging.h"
|
||||
#include "core/compact_object.h"
|
||||
#include "core/mi_memory_resource.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace dfly {
|
||||
|
||||
class StringLruTest : public ::testing::Test {
|
||||
protected:
|
||||
StringLruTest() : mr_(mi_heap_get_backing()), cache_(kSize, &mr_) {
|
||||
}
|
||||
|
||||
const size_t kSize = 4;
|
||||
MiMemoryResource mr_;
|
||||
Lru<std::string> cache_;
|
||||
};
|
||||
|
||||
TEST_F(StringLruTest, PutAndGet) {
|
||||
cache_.Put("a");
|
||||
ASSERT_EQ("a", cache_.GetHead());
|
||||
ASSERT_EQ("a", cache_.GetPrev("a"));
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
cache_.Put("a");
|
||||
ASSERT_EQ("a", cache_.GetHead());
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
cache_.Put("b");
|
||||
ASSERT_EQ("b", cache_.GetHead());
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
cache_.Put("c");
|
||||
ASSERT_EQ("c", cache_.GetHead());
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
cache_.Put("d");
|
||||
ASSERT_EQ("d", cache_.GetHead());
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
cache_.Put("a");
|
||||
ASSERT_EQ("a", cache_.GetHead());
|
||||
ASSERT_EQ("b", cache_.GetTail());
|
||||
cache_.Put("e");
|
||||
ASSERT_EQ("e", cache_.GetHead());
|
||||
ASSERT_EQ("b", cache_.GetTail());
|
||||
cache_.Put("f");
|
||||
ASSERT_EQ("f", cache_.GetHead());
|
||||
ASSERT_EQ("b", cache_.GetTail());
|
||||
}
|
||||
|
||||
TEST_F(StringLruTest, PutAndPutTail) {
|
||||
cache_.Put("a");
|
||||
cache_.Put("a"); // a
|
||||
cache_.Put("b"); // b -> a
|
||||
cache_.Put("c"); // c -> b -> a
|
||||
cache_.Put("d"); // d-> c -> b -> a
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
cache_.Put("a"); // a -> d -> c -> b
|
||||
ASSERT_EQ("b", cache_.GetTail());
|
||||
ASSERT_EQ("c", cache_.GetPrev("b"));
|
||||
ASSERT_EQ("d", cache_.GetPrev("c"));
|
||||
ASSERT_EQ("b", cache_.GetPrev("a"));
|
||||
cache_.Put("d", Position::kTail); // a -> c -> b -> d
|
||||
ASSERT_EQ("d", cache_.GetTail());
|
||||
ASSERT_EQ("b", cache_.GetPrev("d"));
|
||||
ASSERT_EQ("c", cache_.GetPrev("b"));
|
||||
ASSERT_EQ("a", cache_.GetPrev("c"));
|
||||
ASSERT_EQ("d", cache_.GetPrev("a"));
|
||||
cache_.Put("a"); // a -> c -> b -> d
|
||||
ASSERT_EQ("d", cache_.GetTail());
|
||||
cache_.Put("e", Position::kTail); // a -> c -> b -> d -> e
|
||||
ASSERT_EQ("e", cache_.GetTail());
|
||||
ASSERT_EQ("d", cache_.GetPrev("e"));
|
||||
ASSERT_EQ("b", cache_.GetPrev("d"));
|
||||
ASSERT_EQ("a", cache_.GetPrev("c"));
|
||||
ASSERT_EQ("e", cache_.GetPrev("a"));
|
||||
cache_.Put("e", Position::kTail); // a -> c -> b -> d -> e
|
||||
ASSERT_EQ("e", cache_.GetTail());
|
||||
ASSERT_EQ("d", cache_.GetPrev("e"));
|
||||
ASSERT_EQ("b", cache_.GetPrev("d"));
|
||||
ASSERT_EQ("a", cache_.GetPrev("c"));
|
||||
ASSERT_EQ("e", cache_.GetPrev("a"));
|
||||
}
|
||||
|
||||
TEST_F(StringLruTest, BumpTest) {
|
||||
cache_.Put("a");
|
||||
cache_.Put("b");
|
||||
cache_.Put("c");
|
||||
cache_.Put("d");
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
cache_.Put("c");
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
ASSERT_EQ("d", cache_.GetPrev("b"));
|
||||
ASSERT_EQ("c", cache_.GetPrev("d"));
|
||||
}
|
||||
|
||||
TEST_F(StringLruTest, DifferentOrder) {
|
||||
for (uint32_t i = 0; i < kSize * 2; ++i) {
|
||||
cache_.Put(absl::StrCat(i));
|
||||
}
|
||||
ASSERT_EQ("0", cache_.GetTail());
|
||||
|
||||
for (uint32_t i = kSize; i > 0; --i) {
|
||||
cache_.Put(absl::StrCat(i));
|
||||
}
|
||||
ASSERT_EQ("0", cache_.GetTail());
|
||||
cache_.Put("0");
|
||||
ASSERT_EQ("5", cache_.GetTail());
|
||||
}
|
||||
|
||||
TEST_F(StringLruTest, Delete) {
|
||||
cache_.Put("a"); // a
|
||||
cache_.Put("b"); // b -> a
|
||||
cache_.Put("c"); // c -> b -> a
|
||||
cache_.Put("d"); // d-> c -> b -> a
|
||||
cache_.Put("e"); // e -> d-> c -> b -> a
|
||||
ASSERT_EQ("e", cache_.GetHead());
|
||||
ASSERT_TRUE(cache_.Remove("e")); // d-> c -> b -> a
|
||||
ASSERT_EQ("d", cache_.GetHead());
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
ASSERT_EQ("b", cache_.GetPrev("a"));
|
||||
ASSERT_EQ("c", cache_.GetPrev("b"));
|
||||
ASSERT_EQ("d", cache_.GetPrev("c"));
|
||||
ASSERT_EQ("a", cache_.GetPrev("d"));
|
||||
ASSERT_FALSE(cache_.Remove("e")); // d-> c -> b -> a
|
||||
|
||||
ASSERT_TRUE(cache_.Remove("c")); // d -> b -> a
|
||||
ASSERT_EQ("d", cache_.GetHead());
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
ASSERT_EQ("b", cache_.GetPrev("a"));
|
||||
ASSERT_EQ("d", cache_.GetPrev("b"));
|
||||
ASSERT_EQ("a", cache_.GetPrev("d"));
|
||||
cache_.Put("c"); // c -> d -> b -> a
|
||||
ASSERT_EQ("c", cache_.GetHead());
|
||||
ASSERT_EQ("a", cache_.GetTail());
|
||||
ASSERT_EQ("b", cache_.GetPrev("a"));
|
||||
ASSERT_EQ("d", cache_.GetPrev("b"));
|
||||
ASSERT_EQ("c", cache_.GetPrev("d"));
|
||||
ASSERT_EQ("a", cache_.GetPrev("c"));
|
||||
ASSERT_TRUE(cache_.Remove("a")); // c -> d -> b
|
||||
ASSERT_EQ("b", cache_.GetTail());
|
||||
ASSERT_EQ("d", cache_.GetPrev("b"));
|
||||
ASSERT_EQ("c", cache_.GetPrev("d"));
|
||||
ASSERT_EQ("b", cache_.GetPrev("c"));
|
||||
}
|
||||
|
||||
class COVLruTest : public ::testing::Test {
|
||||
protected:
|
||||
COVLruTest() : mr_(mi_heap_get_backing()), cache_(kSize, &mr_) {
|
||||
}
|
||||
|
||||
const size_t kSize = 100;
|
||||
MiMemoryResource mr_;
|
||||
Lru<CompactObjectView> cache_;
|
||||
};
|
||||
|
||||
TEST_F(COVLruTest, MemoryUsagePrint) {
|
||||
size_t before = mr_.used();
|
||||
std::array<CompactObj, 100> obj_arr;
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
obj_arr[i].SetString(absl::StrCat(i));
|
||||
cache_.Put(obj_arr[i]);
|
||||
}
|
||||
|
||||
size_t after = mr_.used();
|
||||
LOG(INFO) << "CompactObjectView lru 100 items memory : " << absl::StrCat(after - before)
|
||||
<< " bytes";
|
||||
}
|
||||
|
||||
} // namespace dfly
|
|
@ -35,7 +35,6 @@
|
|||
#include "zmalloc.h"
|
||||
#include "config.h"
|
||||
#include "listpack.h"
|
||||
#include "util.h" /* for ll2string */
|
||||
#include "lzfP.h"
|
||||
|
||||
|
||||
|
|
205
src/redis/util.c
205
src/redis/util.c
|
@ -164,111 +164,6 @@ int stringmatchlen(const char *pattern, int patternLen,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int stringmatch(const char *pattern, const char *string, int nocase) {
|
||||
return stringmatchlen(pattern,strlen(pattern),string,strlen(string),nocase);
|
||||
}
|
||||
|
||||
/* Fuzz stringmatchlen() trying to crash it with bad input. */
|
||||
int stringmatchlen_fuzz_test(void) {
|
||||
char str[32];
|
||||
char pat[32];
|
||||
int cycles = 10000000;
|
||||
int total_matches = 0;
|
||||
while(cycles--) {
|
||||
int strlen = rand() % sizeof(str);
|
||||
int patlen = rand() % sizeof(pat);
|
||||
for (int j = 0; j < strlen; j++) str[j] = rand() % 128;
|
||||
for (int j = 0; j < patlen; j++) pat[j] = rand() % 128;
|
||||
total_matches += stringmatchlen(pat, patlen, str, strlen, 0);
|
||||
}
|
||||
return total_matches;
|
||||
}
|
||||
|
||||
/* Convert a string representing an amount of memory into the number of
|
||||
* bytes, so for instance memtoll("1Gb") will return 1073741824 that is
|
||||
* (1024*1024*1024).
|
||||
*
|
||||
* On parsing error, if *err is not NULL, it's set to 1, otherwise it's
|
||||
* set to 0. On error the function return value is 0, regardless of the
|
||||
* fact 'err' is NULL or not. */
|
||||
long long memtoll(const char *p, int *err) {
|
||||
const char *u;
|
||||
char buf[128];
|
||||
long mul; /* unit multiplier */
|
||||
long long val;
|
||||
unsigned int digits;
|
||||
|
||||
if (err) *err = 0;
|
||||
|
||||
/* Search the first non digit character. */
|
||||
u = p;
|
||||
if (*u == '-') u++;
|
||||
while(*u && isdigit(*u)) u++;
|
||||
if (*u == '\0' || !strcasecmp(u,"b")) {
|
||||
mul = 1;
|
||||
} else if (!strcasecmp(u,"k")) {
|
||||
mul = 1000;
|
||||
} else if (!strcasecmp(u,"kb")) {
|
||||
mul = 1024;
|
||||
} else if (!strcasecmp(u,"m")) {
|
||||
mul = 1000*1000;
|
||||
} else if (!strcasecmp(u,"mb")) {
|
||||
mul = 1024*1024;
|
||||
} else if (!strcasecmp(u,"g")) {
|
||||
mul = 1000L*1000*1000;
|
||||
} else if (!strcasecmp(u,"gb")) {
|
||||
mul = 1024L*1024*1024;
|
||||
} else {
|
||||
if (err) *err = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the digits into a buffer, we'll use strtoll() to convert
|
||||
* the digit (without the unit) into a number. */
|
||||
digits = u-p;
|
||||
if (digits >= sizeof(buf)) {
|
||||
if (err) *err = 1;
|
||||
return 0;
|
||||
}
|
||||
memcpy(buf,p,digits);
|
||||
buf[digits] = '\0';
|
||||
|
||||
char *endptr;
|
||||
errno = 0;
|
||||
val = strtoll(buf,&endptr,10);
|
||||
if ((val == 0 && errno == EINVAL) || *endptr != '\0') {
|
||||
if (err) *err = 1;
|
||||
return 0;
|
||||
}
|
||||
return val*mul;
|
||||
}
|
||||
|
||||
/* Search a memory buffer for any set of bytes, like strpbrk().
|
||||
* Returns pointer to first found char or NULL.
|
||||
*/
|
||||
const char *mempbrk(const char *s, size_t len, const char *chars, size_t charslen) {
|
||||
for (size_t j = 0; j < len; j++) {
|
||||
for (size_t n = 0; n < charslen; n++)
|
||||
if (s[j] == chars[n]) return &s[j];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Modify the buffer replacing all occurrences of chars from the 'from'
|
||||
* set with the corresponding char in the 'to' set. Always returns s.
|
||||
*/
|
||||
char *memmapchars(char *s, size_t len, const char *from, const char *to, size_t setlen) {
|
||||
for (size_t j = 0; j < len; j++) {
|
||||
for (size_t i = 0; i < setlen; i++) {
|
||||
if (s[j] == from[i]) {
|
||||
s[j] = to[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
/* Return the number of digits of 'v' when converted to string in radix 10.
|
||||
* See ll2string() for more information. */
|
||||
uint32_t digits10(uint64_t v) {
|
||||
|
@ -446,42 +341,6 @@ int string2ll(const char *s, size_t slen, long long *value) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Helper function to convert a string to an unsigned long long value.
|
||||
* The function attempts to use the faster string2ll() function inside
|
||||
* Redis: if it fails, strtoull() is used instead. The function returns
|
||||
* 1 if the conversion happened successfully or 0 if the number is
|
||||
* invalid or out of range. */
|
||||
int string2ull(const char *s, unsigned long long *value) {
|
||||
long long ll;
|
||||
if (string2ll(s,strlen(s),&ll)) {
|
||||
if (ll < 0) return 0; /* Negative values are out of range. */
|
||||
*value = ll;
|
||||
return 1;
|
||||
}
|
||||
errno = 0;
|
||||
char *endptr = NULL;
|
||||
*value = strtoull(s,&endptr,10);
|
||||
if (errno == EINVAL || errno == ERANGE || !(*s != '\0' && *endptr == '\0'))
|
||||
return 0; /* strtoull() failed. */
|
||||
return 1; /* Conversion done! */
|
||||
}
|
||||
|
||||
/* Convert a string into a long. Returns 1 if the string could be parsed into a
|
||||
* (non-overflowing) long, 0 otherwise. The value will be set to the parsed
|
||||
* value when appropriate. */
|
||||
int string2l(const char *s, size_t slen, long *lval) {
|
||||
long long llval;
|
||||
|
||||
if (!string2ll(s,slen,&llval))
|
||||
return 0;
|
||||
|
||||
if (llval < LONG_MIN || llval > LONG_MAX)
|
||||
return 0;
|
||||
|
||||
*lval = (long)llval;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Convert a string into a double. Returns 1 if the string could be parsed
|
||||
* into a (non-overflowing) double, 0 otherwise. The value will be set to
|
||||
* the parsed value when appropriate.
|
||||
|
@ -510,66 +369,4 @@ int string2ld(const char *s, size_t slen, long double *dp) {
|
|||
|
||||
if (dp) *dp = value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create a string object from a long double.
|
||||
* If mode is humanfriendly it does not use exponential format and trims trailing
|
||||
* zeroes at the end (may result in loss of precision).
|
||||
* If mode is default exp format is used and the output of snprintf()
|
||||
* is not modified (may result in loss of precision).
|
||||
* If mode is hex hexadecimal format is used (no loss of precision)
|
||||
*
|
||||
* The function returns the length of the string or zero if there was not
|
||||
* enough buffer room to store it. */
|
||||
int ld2string(char *buf, size_t len, long double value, ld2string_mode mode) {
|
||||
size_t l = 0;
|
||||
|
||||
if (isinf(value)) {
|
||||
/* Libc in odd systems (Hi Solaris!) will format infinite in a
|
||||
* different way, so better to handle it in an explicit way. */
|
||||
if (len < 5) return 0; /* No room. 5 is "-inf\0" */
|
||||
if (value > 0) {
|
||||
memcpy(buf,"inf",3);
|
||||
l = 3;
|
||||
} else {
|
||||
memcpy(buf,"-inf",4);
|
||||
l = 4;
|
||||
}
|
||||
} else {
|
||||
switch (mode) {
|
||||
case LD_STR_AUTO:
|
||||
l = snprintf(buf,len,"%.17Lg",value);
|
||||
if (l+1 > len) return 0; /* No room. */
|
||||
break;
|
||||
case LD_STR_HEX:
|
||||
l = snprintf(buf,len,"%La",value);
|
||||
if (l+1 > len) return 0; /* No room. */
|
||||
break;
|
||||
case LD_STR_HUMAN:
|
||||
/* We use 17 digits precision since with 128 bit floats that precision
|
||||
* after rounding is able to represent most small decimal numbers in a
|
||||
* way that is "non surprising" for the user (that is, most small
|
||||
* decimal numbers will be represented in a way that when converted
|
||||
* back into a string are exactly the same as what the user typed.) */
|
||||
l = snprintf(buf,len,"%.17Lf",value);
|
||||
if (l+1 > len) return 0; /* No room. */
|
||||
/* Now remove trailing zeroes after the '.' */
|
||||
if (strchr(buf,'.') != NULL) {
|
||||
char *p = buf+l-1;
|
||||
while(*p == '0') {
|
||||
p--;
|
||||
l--;
|
||||
}
|
||||
if (*p == '.') l--;
|
||||
}
|
||||
if (l == 2 && buf[0] == '-' && buf[1] == '0') {
|
||||
buf[0] = '0';
|
||||
l = 1;
|
||||
}
|
||||
break;
|
||||
default: return 0; /* Invalid mode. */
|
||||
}
|
||||
}
|
||||
buf[l] = '\0';
|
||||
return l;
|
||||
}
|
||||
}
|
|
@ -44,28 +44,12 @@
|
|||
#define C_OK 0
|
||||
#define C_ERR -1
|
||||
|
||||
/* long double to string conversion options */
|
||||
typedef enum {
|
||||
LD_STR_AUTO, /* %.17Lg */
|
||||
LD_STR_HUMAN, /* %.17Lf + Trimming of trailing zeros */
|
||||
LD_STR_HEX /* %La */
|
||||
} ld2string_mode;
|
||||
|
||||
int stringmatchlen(const char *p, int plen, const char *s, int slen, int nocase);
|
||||
int stringmatch(const char *p, const char *s, int nocase);
|
||||
int stringmatchlen_fuzz_test(void);
|
||||
long long memtoll(const char *p, int *err);
|
||||
const char *mempbrk(const char *s, size_t len, const char *chars, size_t charslen);
|
||||
char *memmapchars(char *s, size_t len, const char *from, const char *to, size_t setlen);
|
||||
uint32_t digits10(uint64_t v);
|
||||
uint32_t sdigits10(int64_t v);
|
||||
|
||||
|
||||
int ll2string(char *s, size_t len, long long value);
|
||||
int string2ll(const char *s, size_t slen, long long *value);
|
||||
int string2ull(const char *s, unsigned long long *value);
|
||||
int string2l(const char *s, size_t slen, long *value);
|
||||
int string2ld(const char *s, size_t slen, long double *dp);
|
||||
int d2string(char *buf, size_t len, double value);
|
||||
int ld2string(char *buf, size_t len, long double value, ld2string_mode mode);
|
||||
|
||||
#define LOG_MAX_LEN 1024 /* Default maximum length of syslog messages.*/
|
||||
|
||||
|
@ -77,10 +61,6 @@ int ld2string(char *buf, size_t len, long double value, ld2string_mode mode);
|
|||
#define LL_RAW (1<<10) /* Modifier to log without timestamp */
|
||||
|
||||
|
||||
#define LRU_BITS 24
|
||||
#define LRU_CLOCK_MAX ((1<<LRU_BITS)-1) /* Max value of obj->lru */
|
||||
#define LRU_CLOCK_RESOLUTION 1000 /* LRU clock resolution in ms */
|
||||
|
||||
/* Bytes needed for long -> str + '\0' */
|
||||
#define LONG_STR_SIZE 21
|
||||
|
||||
|
|
|
@ -218,16 +218,6 @@ unsigned PrimeEvictionPolicy::Evict(const PrimeTable::HotspotBuckets& eb, PrimeT
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Deprecated and should be removed.
|
||||
class FetchedItemsRestorer {
|
||||
public:
|
||||
template <typename U> explicit FetchedItemsRestorer(U&& u) {
|
||||
}
|
||||
|
||||
~FetchedItemsRestorer() {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#define ADD(x) (x) += o.x
|
||||
|
@ -270,6 +260,24 @@ SliceEvents& SliceEvents::operator+=(const SliceEvents& o) {
|
|||
|
||||
#undef ADD
|
||||
|
||||
class DbSlice::PrimeBumpPolicy {
|
||||
public:
|
||||
PrimeBumpPolicy(absl::flat_hash_set<uint64_t, FpHasher>* items) : fetched_items_(items) {
|
||||
}
|
||||
|
||||
// returns true if we can change the object location in dash table.
|
||||
bool CanBump(const CompactObj& obj) const {
|
||||
if (obj.IsSticky()) {
|
||||
return false;
|
||||
}
|
||||
auto hc = obj.HashCode();
|
||||
return fetched_items_->insert(hc).second;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable absl::flat_hash_set<uint64_t, FpHasher>* fetched_items_;
|
||||
};
|
||||
|
||||
DbSlice::DbSlice(uint32_t index, bool cache_mode, EngineShard* owner)
|
||||
: shard_id_(index),
|
||||
cache_mode_(cache_mode),
|
||||
|
@ -474,7 +482,6 @@ OpResult<DbSlice::PrimeItAndExp> DbSlice::FindInternal(const Context& cntx, std:
|
|||
|
||||
if (IsCacheMode() && IsValid(res.it)) {
|
||||
if (!change_cb_.empty()) {
|
||||
FetchedItemsRestorer fetched_restorer(&fetched_items_);
|
||||
auto bump_cb = [&](PrimeTable::bucket_iterator bit) {
|
||||
CallChangeCallbacks(cntx.db_index, key, bit);
|
||||
};
|
||||
|
@ -567,8 +574,6 @@ OpResult<DbSlice::AddOrFindResult> DbSlice::AddOrFindInternal(const Context& cnt
|
|||
auto status = res.status();
|
||||
CHECK(status == OpStatus::KEY_NOTFOUND || status == OpStatus::OUT_OF_MEMORY) << status;
|
||||
|
||||
FetchedItemsRestorer fetched_restorer(&fetched_items_);
|
||||
|
||||
// It's a new entry.
|
||||
CallChangeCallbacks(cntx.db_index, key, {key});
|
||||
|
||||
|
@ -1059,7 +1064,6 @@ bool DbSlice::CheckLock(IntentLock::Mode mode, DbIndex dbid, uint64_t fp) const
|
|||
}
|
||||
|
||||
void DbSlice::PreUpdate(DbIndex db_ind, Iterator it, std::string_view key) {
|
||||
FetchedItemsRestorer fetched_restorer(&fetched_items_);
|
||||
CallChangeCallbacks(db_ind, key, ChangeReq{it.GetInnerIt()});
|
||||
it.GetInnerIt().SetVersion(NextVersion());
|
||||
}
|
||||
|
@ -1178,8 +1182,7 @@ uint64_t DbSlice::RegisterOnChange(ChangeCallback cb) {
|
|||
}
|
||||
|
||||
void DbSlice::FlushChangeToEarlierCallbacks(DbIndex db_ind, Iterator it, uint64_t upper_bound) {
|
||||
FetchedItemsRestorer fetched_restorer(&fetched_items_);
|
||||
std::unique_lock<LocalBlockingCounter> lk(block_counter_);
|
||||
unique_lock<LocalBlockingCounter> lk(block_counter_);
|
||||
|
||||
uint64_t bucket_version = it.GetVersion();
|
||||
// change_cb_ is ordered by version.
|
||||
|
|
|
@ -657,23 +657,7 @@ class DbSlice {
|
|||
absl::container_internal::hash_default_eq<std::string>, AllocatorType>
|
||||
client_tracking_map_;
|
||||
|
||||
class PrimeBumpPolicy {
|
||||
public:
|
||||
PrimeBumpPolicy(absl::flat_hash_set<uint64_t, FpHasher>* items) : fetched_items_(items) {
|
||||
}
|
||||
|
||||
// returns true if we can change the object location in dash table.
|
||||
bool CanBump(const CompactObj& obj) const {
|
||||
if (obj.IsSticky()) {
|
||||
return false;
|
||||
}
|
||||
auto hc = obj.HashCode();
|
||||
return fetched_items_->insert(hc).second;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable absl::flat_hash_set<uint64_t, FpHasher>* fetched_items_;
|
||||
};
|
||||
class PrimeBumpPolicy;
|
||||
};
|
||||
|
||||
inline bool IsValid(const DbSlice::Iterator& it) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue