package org.zbus.server.mq.store;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.zbus.common.json.JSON;
import org.zbus.common.logging.Logger;
import org.zbus.common.logging.LoggerFactory;
import org.zbus.common.protocol.MessageMode;
import org.zbus.common.protocol.MqInfo;
import org.zbus.common.remoting.Message;
import org.zbus.common.remoting.MessageCodec;
import org.zbus.common.remoting.nio.IoBuffer;
import org.zbus.server.mq.MessageQueue;
import org.zbus.server.mq.RequestQueue;
import redis.clients.jedis.Jedis;
/**
* NOT yet fully tested
* @author 洪磊明(rushmore)
*
*/
public class MessageStoreRedis implements MessageStore {
private static final Logger log = LoggerFactory.getLogger(MessageStoreRedis.class);private Jedis jedis;
private static final MessageCodec codec = new MessageCodec();
private final Properties props = new Properties();
private final static String CONFIG_FILE = "redis.properties";
private final String brokerKey;
public MessageStoreRedis(String broker){
this.brokerKey = broker;
//从配置文件中读取配置信息
InputStream stream = getClass().getClassLoader().getResourceAsStream(CONFIG_FILE);
try {
if(stream != null){
props.load(stream);
} else {
log.warn("missing properties: "+ CONFIG_FILE);
}
} catch (IOException e) {
log.error(e.getMessage(), e);
}
String host = props.getProperty("host", "localhost").trim();
String portString = props.getProperty("port", "6379").trim();
String password = props.getProperty("password", "").trim();
int port = 6379;
try{
port = Integer.valueOf(portString);
} catch (Exception e){
}
this.jedis = new Jedis(host, port);
if(!"".equals(password)){
jedis.auth(password);
}
}
private String msgKey(Message msg){
return msg.getMsgId();
}
private String mqKey(String mq){
return String.format("%s%s", brokerKey, mq);
}
@Override
public void saveMessage(Message msg) {
String msgKey = msgKey(msg);
String mqKey = mqKey(msg.getMq());
jedis.set(msgKey, msg.toString());
jedis.rpush(mqKey, msgKey);
}
@Override
public void removeMessage(Message msg) {
String msgKey = msgKey(msg);
String mqKey = mqKey(msg.getMq());
jedis.del(msgKey);
jedis.lrem(mqKey, 1, msgKey);
}
@Override
public void onMessageQueueCreated(MessageQueue mq) {
String json = JSON.toJSONString(mq.getMqInfo());
jedis.hset(this.brokerKey, mq.getName(), json);
}
@Override
public void onMessageQueueRemoved(MessageQueue mq) {
jedis.hdel(this.brokerKey, mq.getName());
}
@Override
public ConcurrentMap<String, MessageQueue> loadMqTable() {
Map<String, String> mqs = jedis.hgetAll(this.brokerKey);
ConcurrentHashMap<String, MessageQueue> res = new ConcurrentHashMap<String, MessageQueue>();
Iterator<Entry<String, String>> iter = mqs.entrySet().iterator();
while(iter.hasNext()){
Entry<String, String> e = iter.next();
String mqName = e.getKey();
String mqInfoString = e.getValue();
MqInfo info = JSON.parseObject(mqInfoString, MqInfo.class);
int mode = info.getMode();
if(!MessageMode.isEnabled(mode, MessageMode.MQ)){
log.warn("message queue mode not support");
continue;
}
RequestQueue mq = new RequestQueue(info.getBroker(),
mqName, null, mode);
mq.setCreator(info.getCreator());
mq.setMessageStore(this);
String mqKey = mqKey(mqName);
//TODO batch
List<String> msgIds = jedis.lrange(mqKey, 0, -1);
if(msgIds.size() == 0) continue;
List<String> msgStrings = jedis.mget(msgIds.toArray(new String[0]));
List<Message> msgs = new ArrayList<Message>();
for(String msgString : msgStrings){
if(msgString == null){
log.warn("message missing");
continue;
}
IoBuffer buf = IoBuffer.wrap(msgString);
Message msg = (Message) codec.decode(buf);
if(msg != null){
msgs.add(msg);
} else {
log.error("message decode error");
}
}
mq.loadMessageList(msgs);
res.put(mqName, mq);
}
return res;
}
@Override
public void start() {
}
@Override
public void shutdown() {
}
}