package com.alibaba.doris.dataserver.store.handlersocket;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.doris.common.data.CompareStatus;
import com.alibaba.doris.common.data.Key;
import com.alibaba.doris.common.data.Pair;
import com.alibaba.doris.common.data.Value;
import com.alibaba.doris.common.data.impl.ValueImpl;
import com.alibaba.doris.common.data.util.ByteUtils;
import com.alibaba.doris.dataserver.store.Storage;
import com.alibaba.doris.dataserver.store.StorageType;
import com.alibaba.doris.dataserver.store.exception.VersionConflictException;
import com.alibaba.hsclient.HSClient;
import com.alibaba.hsclient.IndexSession;
import com.alibaba.hsclient.bean.ResultInfo;
import com.alibaba.hsclient.impl.HSClientImpl;
public class HandlerSocketStorage implements Storage {
private HSClient hsClient;
private IndexSession indexSession;
private HandlerSocketStorageConfig config;
private static final Logger logger = LoggerFactory
.getLogger(HandlerSocketStorage.class);
public HandlerSocketStorage(HandlerSocketStorageConfig config) {
if (config == null) {
throw new IllegalArgumentException(
"The HandlerSocket cofing can't be null!");
}
this.config = config;
try {
this.hsClient = new HSClientImpl(config);
this.hsClient.connect();
} catch (IOException e) {
throw new HandlerSocketException("Failed to create connection ");
}
}
private String getTableName(Key key) {
//同一个Key,只会散列到同一个VNode,以VNode作为表名
//需要考虑create table方式,是事先根据VNode手动创建呢,还是采用mysql jdbc方式进行create table
return "Table_"+key.getVNode();
}
public Value get(Key key) {
try {
if (null == key || StringUtils.isBlank(key.getKey())) {
throw new IllegalArgumentException("Key can't be null!");
}
if (this.hsClient.getIndexMap().isEmpty())
{
indexSession = this.hsClient.openIndexSession(this.config.getDbName(), getTableName(key),
"PRIMARY", new String[] { "keyColumn","valueColumn","created"});
}
ResultInfo resultInfo = this.indexSession.find(new String[] { key.getKey() });
if (resultInfo == null) {
return null;
}
//value的值只能一个,但带version信息
if (resultInfo.getMessages() == null || resultInfo.getMessages().size() != 3) {
throw new HandlerSocketException(
"the messages size must be 3");
}
//实际设置Value的timestamp需要由返回的结果进行设置,而非系统时间
return new ValueImpl(ByteUtils.stringToByte(resultInfo.getMessages().get(1), this.getConfig()
.getEncoding()));
} catch (Exception e) {
throw new HandlerSocketException("Get value exception", e);
}
}
public Map<Key, Value> getAll(Iterable<Key> keyIterator) {
int size = ((Collection<?>) keyIterator).size();
Map<Key, Value> result = new HashMap<Key, Value>(size);
for (Key key : keyIterator) {
Value value = get(key);
if (value != null) {
result.put(key, value);
}
}
return result;
}
public void set(Key key, Value value) {
try {
if (null == key || StringUtils.isBlank(key.getKey())) {
throw new IllegalArgumentException("Key can't be null!");
}
if (null == value) {
throw new IllegalArgumentException("Value can't be null!");
}
if (this.hsClient.getIndexMap().isEmpty())
{
indexSession = this.hsClient.openIndexSession(this.config.getDbName(), getTableName(key),
"PRIMARY", new String[] { "keyColumn","valueColumn","created"});
}
boolean result = this.indexSession.insert(
new String[] {
key.getKey(),
new String(value.getValueBytes(), this.config
.getEncoding()) });
if (!result) {
throw new HandlerSocketException("set key,value exception");
}
} catch (Exception e) {
throw new HandlerSocketException("set value exception", e);
}
}
public void set(Key key, Value value, boolean isSetWithCompareVersion) {
if (null == key || StringUtils.isBlank(key.getKey())) {
throw new IllegalArgumentException("Key can't be null!");
}
if (null == value) {
throw new IllegalArgumentException("Value can't be null!");
}
if (logger.isDebugEnabled()) {
logger.debug("set: key=" + key + " timestamp="
+ value.getTimestamp());
}
try {
Value v = get(key);
if (isSetWithCompareVersion && v != null)
{
if (v.compareVersion(value) == CompareStatus.AFTER) {
throw new VersionConflictException(
"Key "
+ key.getKey()
+ " Namespace "
+ key.getNamespace()
+ " "
+ value.getTimestamp()
+ " is obsolete, it is no greater than the current version of "
+ v.getTimestamp() + ".");
}
}
else {
// 是否需要执行delete操作,待确定
}
set(key, value);
} catch (Exception e) {
throw new HandlerSocketException(e);
}
}
public boolean delete(Key key) {
try {
if (null == key || StringUtils.isBlank(key.getKey())) {
throw new IllegalArgumentException("Key can't be null!");
}
if (this.hsClient.getIndexMap().isEmpty())
{
indexSession = this.hsClient.openIndexSession(this.config.getDbName(), getTableName(key),
"PRIMARY", new String[] { "keyColumn","valueColumn","created"});
}
boolean result = this.indexSession.delete(new String[] { key.getKey() });
if (!result) {
return false;
}
return true;
} catch (Exception e) {
throw new HandlerSocketException("delete key exception", e);
}
}
public boolean delete(Key key, Value value) {
return false;
}
public boolean delete(List<Integer> vnodeList) {
return false;
}
public Iterator<Pair> iterator() {
return null;
}
public Iterator<Pair> iterator(List<Integer> vnodeList) {
return null;
}
public void open() {
// createTable操作?
}
public void close() {
try {
this.hsClient.close();
} catch (IOException e) {
throw new HandlerSocketException("Failed to close connection");
}
}
public StorageType getType() {
return HandlerSocketStorageType.HandlerSocket;
}
public HandlerSocketStorageConfig getConfig() {
return config;
}
public void setConfig(HandlerSocketStorageConfig config) {
this.config = config;
}
}