本文主要研究一下claudb的string command
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/GetCommand.java
@ReadOnly
@Command("get")
@ParamLength(1)
@ParamType(DataType.STRING)
public class GetCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
return convert(db.get(safeKey(request.getParam(0))));
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/MultiGetCommand.java
@ReadOnly
@Command("mget")
@ParamLength(1)
public class MultiGetCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
ImmutableArray<DatabaseValue> result = request.getParams()
.map(DatabaseKey::safeKey)
.filter(key -> db.isType(key, DataType.STRING))
.map(db::get);
return convert(result);
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/SetCommand.java
@Command("set")
@ParamLength(2)
public class SetCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
return com.github.tonivade.purefun.type.Try.of(() -> parse(request))
.map(params -> onSuccess(db, request, params))
.recover(this::onFailure)
.get();
}
private RedisToken onSuccess(Database db, Request request, Parameters parameters) {
DatabaseKey key = safeKey(request.getParam(0));
DatabaseValue value = parseValue(request, parameters);
return value.equals(saveValue(db, parameters, key, value)) ? responseOk() : nullString();
}
private DatabaseValue parseValue(Request request, Parameters parameters) {
DatabaseValue value = string(request.getParam(1));
if (parameters.ttl != null) {
value = value.expiredAt(Instant.now().plus(parameters.ttl));
}
return value;
}
private RedisToken onFailure(Throwable e) {
return Pattern1.<Throwable, RedisToken>build()
.when(instanceOf(SyntaxException.class))
.returns(error("syntax error"))
.when(instanceOf(NumberFormatException.class))
.returns(error("value is not an integer or out of range"))
.otherwise()
.returns(error("error: " + e.getMessage()))
.apply(e);
}
private DatabaseValue saveValue(Database db, Parameters params, DatabaseKey key, DatabaseValue value) {
DatabaseValue savedValue = null;
if (params.ifExists) {
savedValue = putValueIfExists(db, key, value);
} else if (params.ifNotExists) {
savedValue = putValueIfNotExists(db, key, value);
} else {
savedValue = putValue(db, key, value);
}
return savedValue;
}
private DatabaseValue putValue(Database db, DatabaseKey key, DatabaseValue value) {
db.put(key, value);
return value;
}
private DatabaseValue putValueIfExists(Database db, DatabaseKey key, DatabaseValue value) {
DatabaseValue oldValue = db.get(key);
if (oldValue != null) {
return putValue(db, key, value);
}
return oldValue;
}
private DatabaseValue putValueIfNotExists(Database db, DatabaseKey key, DatabaseValue value) {
return db.merge(key, value, (oldValue, newValue) -> oldValue);
}
private Parameters parse(Request request) {
Parameters parameters = new Parameters();
if (request.getLength() > 2) {
for (int i = 2; i < request.getLength(); i++) {
SafeString option = request.getParam(i);
if (match("EX", option)) {
if (parameters.ttl != null) {
throw new SyntaxException();
}
parameters.ttl = parseTtl(request, ++i)
.map(Duration::ofSeconds)
.getOrElseThrow(SyntaxException::new);
} else if (match("PX", option)) {
if (parameters.ttl != null) {
throw new SyntaxException();
}
parameters.ttl = parseTtl(request, ++i)
.map(Duration::ofMillis)
.getOrElseThrow(SyntaxException::new);
} else if (match("NX", option)) {
if (parameters.ifExists) {
throw new SyntaxException();
}
parameters.ifNotExists = true;
} else if (match("XX", option)) {
if (parameters.ifNotExists) {
throw new SyntaxException();
}
parameters.ifExists = true;
} else {
throw new SyntaxException();
}
}
}
return parameters;
}
private boolean match(String string, SafeString option) {
return string.equalsIgnoreCase(option.toString());
}
private Option<Integer> parseTtl(Request request, int i) {
Option<SafeString> ttlOption = request.getOptionalParam(i);
return ttlOption.map(SafeString::toString).map(Integer::parseInt);
}
private static class Parameters {
private boolean ifExists;
private boolean ifNotExists;
private TemporalAmount ttl;
}
private static class SyntaxException extends RuntimeException {
private static final long serialVersionUID = 6960370945568192189L;
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/MultiSetCommand.java
@Command("mset")
@ParamLength(2)
public class MultiSetCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
SafeString key = null;
for (SafeString value : request.getParams()) {
if (key != null) {
db.put(safeKey(key), string(value));
key = null;
} else {
key = value;
}
}
return status("OK");
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/GetSetCommand.java
@Command("getset")
@ParamLength(2)
@ParamType(DataType.STRING)
public class GetSetCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
return convert(db.put(safeKey(request.getParam(0)), string(request.getParam(1))));
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/IncrementCommand.java
@Command("incr")
@ParamLength(1)
@ParamType(DataType.STRING)
public class IncrementCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
try {
DatabaseValue value = db.merge(safeKey(request.getParam(0)), string("1"),
(oldValue, newValue) -> {
int current = Integer.parseInt(oldValue.getString().toString());
return string(String.valueOf(current + 1));
});
return integer(Integer.parseInt(value.getString().toString()));
} catch (NumberFormatException e) {
return error("ERR value is not an integer or out of range");
}
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/IncrementByCommand.java
@Command("incrby")
@ParamLength(2)
@ParamType(DataType.STRING)
public class IncrementByCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
try {
DatabaseValue value = db.merge(safeKey(request.getParam(0)), string(request.getParam(1)),
(oldValue, newValue) -> {
int increment = Integer.parseInt(newValue.getString().toString());
int current = Integer.parseInt(oldValue.getString().toString());
return string(String.valueOf(current + increment));
});
return integer(Integer.parseInt(value.getString().toString()));
} catch (NumberFormatException e) {
return error("ERR value is not an integer or out of range");
}
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/DecrementCommand.java
@Command("decr")
@ParamLength(1)
@ParamType(DataType.STRING)
public class DecrementCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
try {
DatabaseValue value = db.merge(safeKey(request.getParam(0)), string("-1"),
(oldValue, newValue) -> {
int current = Integer.parseInt(oldValue.getString().toString());
return string(String.valueOf(current - 1));
});
return integer(Integer.parseInt(value.getString().toString()));
} catch (NumberFormatException e) {
return error("ERR value is not an integer or out of range");
}
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/DecrementByCommand.java
@Command("decrby")
@ParamLength(2)
@ParamType(DataType.STRING)
public class DecrementByCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
try {
DatabaseValue value = db.merge(safeKey(request.getParam(0)), string("-" + request.getParam(1)),
(oldValue, newValue) -> {
int decrement = Integer.parseInt(newValue.getString().toString());
int current = Integer.parseInt(oldValue.getString().toString());
return string(String.valueOf(current + decrement));
});
return integer(Integer.parseInt(value.getString().toString()));
} catch (NumberFormatException e) {
return error("ERR value is not an integer or out of range");
}
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/StringLengthCommand.java
@ReadOnly
@Command("strlen")
@ParamLength(1)
@ParamType(DataType.STRING)
public class StringLengthCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
DatabaseValue value = db.getOrDefault(safeKey(request.getParam(0)), DatabaseValue.EMPTY_STRING);
SafeString string = value.getString();
return integer(string.length());
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/SetExpiredCommand.java
@Command("setex")
@ParamLength(3)
public class SetExpiredCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
try {
db.put(safeKey(request.getParam(0)), string(request.getParam(2))
.expiredAt(parseTtl(request.getParam(1))));
return responseOk();
} catch (NumberFormatException e) {
return error("ERR value is not an integer or out of range");
}
}
private int parseTtl(SafeString safeString) {
return Integer.parseInt(safeString.toString());
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/bitset/BitCountCommand.java
@Command("bitcount")
@ParamLength(1)
@ParamType(DataType.STRING)
public class BitCountCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
DatabaseValue value = db.getOrDefault(safeKey(request.getParam(0)), bitset());
BitSet bitSet = BitSet.valueOf(value.getString().getBuffer());
return integer(bitSet.cardinality());
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/bitset/SetBitCommand.java
@Command("setbit")
@ParamLength(3)
@ParamType(DataType.STRING)
public class SetBitCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
try {
int offset = Integer.parseInt(request.getParam(1).toString());
int bit = Integer.parseInt(request.getParam(2).toString());
Queue<Boolean> queue = new LinkedList<>();
db.merge(safeKey(request.getParam(0)), bitset(), (oldValue, newValue) -> {
BitSet bitSet = BitSet.valueOf(oldValue.getString().getBuffer());
queue.add(bitSet.get(offset));
bitSet.set(offset, bit != 0);
return oldValue;
});
return integer(queue.poll());
} catch (NumberFormatException e) {
return error("bit or offset is not an integer");
}
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/bitset/GetBitCommand.java
@Command("getbit")
@ParamLength(2)
@ParamType(DataType.STRING)
public class GetBitCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
try {
int offset = Integer.parseInt(request.getParam(1).toString());
DatabaseValue value = db.getOrDefault(safeKey(request.getParam(0)), bitset());
BitSet bitSet = BitSet.valueOf(value.getString().getBuffer());
return integer(bitSet.get(offset));
} catch (NumberFormatException e) {
return error("bit offset is not an integer");
}
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/SetIfNotExistsCommand.java
@Command("setnx")
@ParamLength(2)
public class SetIfNotExistsCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
DatabaseKey key = safeKey(request.getParam(0));
DatabaseValue value = string(request.getParam(1));
return integer(putValueIfNotExists(db, key, value).equals(value));
}
private DatabaseValue putValueIfNotExists(Database db, DatabaseKey key, DatabaseValue value) {
return db.merge(key, value, (oldValue, newValue) -> oldValue);
}
}
claudb-1.7.1/src/main/java/com/github/tonivade/claudb/command/string/MultiSetIfNotExistsCommand.java
@Command("msetnx")
@ParamLength(2)
public class MultiSetIfNotExistsCommand implements DBCommand {
@Override
public RedisToken execute(Database db, Request request) {
Set<Tuple2<SafeString, SafeString>> pairs = toPairs(request);
if (noneExists(db, pairs)) {
pairs.forEach(entry -> db.put(safeKey(entry.get1()), string(entry.get2())));
return integer(1);
}
return integer(0);
}
private boolean noneExists(Database db, Set<Tuple2<SafeString, SafeString>> pairs) {
return pairs.stream()
.map(Tuple2::get1)
.map(DatabaseKey::safeKey)
.noneMatch(db::containsKey);
}
private Set<Tuple2<SafeString, SafeString>> toPairs(Request request) {
Set<Tuple2<SafeString, SafeString>> pairs = new HashSet<>();
SafeString key = null;
for (SafeString value : request.getParams()) {
if (key != null) {
pairs.add(entry(key, value));
key = null;
} else {
key = value;
}
}
return pairs;
}
}
claudb string相关的command有GetCommand、MultiGetCommand、SetCommand、MultiSetCommand、GetSetCommand、IncrementCommand、IncrementByCommand、DecrementCommand、DecrementByCommand、StringLengthCommand、SetExpiredCommand、BitCountCommand、GetBitCommand、SetIfNotExistsCommand、MultiSetIfNotExistsCommand
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。