package org.opencloudb.handler;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opencloudb.MycatServer;
import org.opencloudb.config.Fields;
import org.opencloudb.config.model.SystemConfig;
import org.opencloudb.manager.ManagerConnection;
import org.opencloudb.mysql.PacketUtil;
import org.opencloudb.net.mysql.EOFPacket;
import org.opencloudb.net.mysql.FieldPacket;
import org.opencloudb.net.mysql.ResultSetHeaderPacket;
import org.opencloudb.net.mysql.RowDataPacket;
import org.opencloudb.util.CircularArrayList;
import org.opencloudb.util.StringUtil;
public final class ShowServerLog {
private static final int FIELD_COUNT = 1;
private static final ResultSetHeaderPacket header = PacketUtil
.getHeader(FIELD_COUNT);
private static final FieldPacket[] fields = new FieldPacket[FIELD_COUNT];
private static final EOFPacket eof = new EOFPacket();
private static final String DEFAULT_LOGFILE = "mycat.log";
static {
int i = 0;
byte packetId = 0;
header.packetId = ++packetId;
fields[i] = PacketUtil.getField("LOG", Fields.FIELD_TYPE_VAR_STRING);
fields[i++].packetId = ++packetId;
eof.packetId = ++packetId;
}
private static File getLogFile(String logFile) {
MycatServer.getInstance().getConfig().getSystem();
String daasHome = SystemConfig.getHomePath();
File file = new File(daasHome, "logs" + File.separator + logFile);
return file;
}
public static void handle(String stmt,ManagerConnection c) {
ByteBuffer buffer = c.allocate();
// write header
buffer = header.write(buffer, c);
// write fields
for (FieldPacket field : fields) {
buffer = field.write(buffer, c);
}
// write eof
buffer = eof.write(buffer, c);
// write rows
byte packetId = eof.packetId;
PackageBufINf bufInf = null;
// show log key=warn limit=0,30
Map<String, String> condPairMap = getCondPair(stmt);
if (condPairMap.isEmpty()) {
bufInf = showLogSum(c, buffer, packetId);
} else {
String logFile = condPairMap.get("file");
if (logFile == null) {
logFile = DEFAULT_LOGFILE;
}
String limitStr = condPairMap.get("limit");
limitStr = (limitStr != null) ? limitStr : "0," + 100000;
String[] limtArry = limitStr.split("\\s|,");
int start = Integer.valueOf(limtArry[0]);
int page = Integer.valueOf(limtArry[1]);
int end = Integer.valueOf(start + page);
String key = condPairMap.get("key");
String regex = condPairMap.get("regex");
bufInf = showLogRange(c, buffer, packetId, key, regex, start, end,
logFile);
}
packetId = bufInf.packetId;
buffer = bufInf.buffer;
EOFPacket lastEof = new EOFPacket();
lastEof.packetId = ++packetId;
buffer = lastEof.write(buffer, c);
// write buffer
c.write(buffer);
}
public static PackageBufINf showLogRange(ManagerConnection c,
ByteBuffer buffer, byte packetId, String key, String regex,
int start, int end, String logFile) {
PackageBufINf bufINf = new PackageBufINf();
Pattern pattern = null;
if (regex != null) {
pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
}
if (key != null) {
key = key.toLowerCase();
}
File file = getLogFile(logFile);
BufferedReader br = null;
int curLine = 0;
try {
br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null) {
curLine++;
if (curLine >= start && curLine <= end) {
if ((pattern != null && pattern.matcher(line).find())
|| (pattern == null && key == null)
|| (key != null && line.toLowerCase().contains(key))) {
RowDataPacket row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode(curLine + "->" + line,
c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c);
}
}
}
bufINf.buffer = buffer;
bufINf.packetId = packetId;
return bufINf;
} catch (Exception e) {
e.printStackTrace();
RowDataPacket row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode(e.toString(), c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c);
bufINf.buffer = buffer;
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
bufINf.packetId = packetId;
return bufINf;
}
private static PackageBufINf showLogSum(ManagerConnection c,
ByteBuffer buffer, byte packetId) {
PackageBufINf bufINf = new PackageBufINf();
File[] logFiles = new File(SystemConfig.getHomePath(), "logs")
.listFiles();
String fileNames = "";
for (File f : logFiles) {
if (f.isFile()) {
fileNames += " " + f.getName();
}
}
File file = getLogFile(DEFAULT_LOGFILE);
BufferedReader br = null;
int totalLines = 0;
CircularArrayList<String> queue = new CircularArrayList<String>(50);
try {
br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null) {
totalLines++;
if (queue.size() == queue.capacity()) {
queue.remove(0);
}
queue.add(line);
}
RowDataPacket row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode("files in log dir:" + totalLines
+ fileNames, c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c);
row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode("Total lines " + totalLines + " ,tail "
+ queue.size() + " line is following:", c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c);
int size = queue.size() - 1;
for (int i = size; i >= 0; i--) {
String data = queue.get(i);
row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode(data, c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c);
}
bufINf.buffer = buffer;
bufINf.packetId = packetId;
return bufINf;
} catch (Exception e) {
e.printStackTrace();
RowDataPacket row = new RowDataPacket(FIELD_COUNT);
row.add(StringUtil.encode(e.toString(), c.getCharset()));
row.packetId = ++packetId;
buffer = row.write(buffer, c);
bufINf.buffer = buffer;
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
bufINf.packetId = packetId;
return bufINf;
}
public static Map<String, String> getCondPair(String sql) {
HashMap<String, String> map = new HashMap<String, String>();
Pattern p = Pattern.compile("(\\S+\\s*=\\s*\\S+)");
Matcher m = p.matcher(sql);
while (m.find()) {
String item = m.group();
Pattern p2 = Pattern.compile("(\\S+)\\s*=\\s*(\\S+)");
Matcher m2 = p2.matcher(item);
if (m2.find()) {
map.put(m2.group(1), m2.group(2));
}
}
return map;
}
public static void main(String[] args) {
String sql = "show log limit =1,2 key=warn file= \"2\" ";
Map<String, String> condPairMap = getCondPair(sql);
for (Map.Entry<String, String> entry : condPairMap.entrySet()) {
System.out.println("key:" + entry.getKey() + ",value:"
+ entry.getValue());
}
String limt = "1,2";
System.out.println(Arrays.toString(limt.split("\\s|,")));
}
}
class PackageBufINf {
public byte packetId;
public ByteBuffer buffer;
}