package com.meidusa.amoeba.mongodb.test;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import org.apache.log4j.Logger;
import org.bson.BasicBSONObject;
import com.meidusa.amoeba.benchmark.AbstractBenchmarkClient;
import com.meidusa.amoeba.benchmark.AbstractBenchmark.TaskRunnable;
import com.meidusa.amoeba.config.ParameterMapping;
import com.meidusa.amoeba.mongodb.io.MongodbFramedInputStream;
import com.meidusa.amoeba.mongodb.io.MongodbFramingOutputStream;
import com.meidusa.amoeba.mongodb.io.MongodbPacketConstant;
import com.meidusa.amoeba.mongodb.packet.AbstractMongodbPacket;
import com.meidusa.amoeba.mongodb.packet.DeleteMongodbPacket;
import com.meidusa.amoeba.mongodb.packet.GetMoreMongodbPacket;
import com.meidusa.amoeba.mongodb.packet.InsertMongodbPacket;
import com.meidusa.amoeba.mongodb.packet.KillCursorsMongodbPacket;
import com.meidusa.amoeba.mongodb.packet.MessageMongodbPacket;
import com.meidusa.amoeba.mongodb.packet.MongodbPacketBuffer;
import com.meidusa.amoeba.mongodb.packet.QueryMongodbPacket;
import com.meidusa.amoeba.mongodb.packet.ResponseMongodbPacket;
import com.meidusa.amoeba.mongodb.packet.UpdateMongodbPacket;
import com.meidusa.amoeba.net.Connection;
import com.meidusa.amoeba.net.io.PacketInputStream;
import com.meidusa.amoeba.net.io.PacketOutputStream;
import com.meidusa.amoeba.net.packet.AbstractPacket;
import com.meidusa.amoeba.util.StringUtil;
/**
*
* @author Struct
*
*/
public class MongodbBenchmarkClient extends AbstractBenchmarkClient<AbstractMongodbPacket> {
private static Logger logger = Logger.getLogger(MongodbBenchmarkClient.class);
private boolean isLastModifyOperation = false;
public MongodbBenchmarkClient(Connection conn, CountDownLatch requestLatcher,CountDownLatch responseLatcher,TaskRunnable task) {
super(conn,requestLatcher,responseLatcher,task);
}
public boolean needPing(long now) {
return false;
}
public AbstractMongodbPacket decodeRecievedPacket(byte[] message) {
int type = MongodbPacketBuffer.getOPMessageType(message);
AbstractMongodbPacket packet = null;
switch(type){
case MongodbPacketConstant.OP_QUERY:
packet = new QueryMongodbPacket();
break;
case MongodbPacketConstant.OP_GET_MORE:
packet = new GetMoreMongodbPacket();
break;
case MongodbPacketConstant.OP_DELETE:
packet = new DeleteMongodbPacket();
break;
case MongodbPacketConstant.OP_KILL_CURSORS:
packet = new KillCursorsMongodbPacket();
break;
case MongodbPacketConstant.OP_UPDATE:
packet = new UpdateMongodbPacket();
break;
case MongodbPacketConstant.OP_INSERT:
packet = new InsertMongodbPacket();
break;
case MongodbPacketConstant.OP_MSG:
packet = new MessageMongodbPacket();
break;
case MongodbPacketConstant.OP_REPLY:
packet = new ResponseMongodbPacket();
break;
default:
logger.error("error type="+type+"\r\n"+StringUtil.dumpAsHex(message, message.length));
}
packet.init(message, this.getConnection());
return packet;
}
public AbstractMongodbPacket createRequestPacket() {
Properties properties = this.getRequestProperties();
AbstractMongodbPacket packet = null;
try {
packet = (AbstractMongodbPacket)Class.forName((String)properties.get("class")).newInstance();
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
ParameterMapping.mappingObjectField(packet, properties,this.getNextRequestContextMap(),this, AbstractPacket.class);
return packet;
}
protected PacketInputStream createPacketInputStream() {
return new MongodbFramedInputStream(true);
}
protected PacketOutputStream createPacketOutputStream() {
return new MongodbFramingOutputStream(true);
}
public void init(){
super.init();
}
@Override
public void startBenchmark() {
AbstractMongodbPacket packet = this.createRequestPacket();
if(packet.opCode == MongodbPacketConstant.OP_DELETE
|| packet.opCode == MongodbPacketConstant.OP_INSERT
|| packet.opCode == MongodbPacketConstant.OP_UPDATE){
isLastModifyOperation = true;
}else{
isLastModifyOperation = false;
}
if(isLastModifyOperation){
byte[] packetMessage = packet.toByteBuffer(this.getConnection()).array();
byte[] lastError = getLastErrorPacket().toByteBuffer(this.getConnection()).array();
byte[] message = new byte[packetMessage.length+lastError.length];
System.arraycopy(packetMessage, 0, message, 0, packetMessage.length);
System.arraycopy(lastError, 0, message, packetMessage.length,lastError.length);
getConnection().postMessage(message);
}else{
getConnection().postMessage(packet.toByteBuffer(this.getConnection()));
}
}
protected QueryMongodbPacket getLastErrorPacket(){
QueryMongodbPacket packet = new QueryMongodbPacket();
packet.fullCollectionName = "admin.$cmd";
packet.numberToReturn = -1;
BasicBSONObject document = new BasicBSONObject();
document.put("getlasterror",1);
packet.query = document;
return packet;
}
protected void postPacketToServer(){
if(isLastModifyOperation){
byte[] packetMessage = createRequestPacket().toByteBuffer(this.getConnection()).array();
byte[] lastError = getLastErrorPacket().toByteBuffer(this.getConnection()).array();
byte[] message = new byte[packetMessage.length+lastError.length];
System.arraycopy(packetMessage, 0, message, 0, packetMessage.length);
System.arraycopy(lastError, 0, message, packetMessage.length,lastError.length);
getConnection().postMessage(message);
}else{
getConnection().postMessage(createRequestPacket().toByteBuffer(this.getConnection()));
}
}
}