blob: f550c057f4559453177d6c5fac989d9dc4b63e59 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.chukwa.database;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.chukwa.util.DatabaseWriter;
public class Macro {
private static Log log = LogFactory.getLog(Macro.class);
private boolean forCharting = false;
private long current = 0;
private long start = 0;
private long end = 0;
private static DatabaseConfig dbc = new DatabaseConfig();
private DatabaseWriter db = null;
private String query = null;
private HttpServletRequest request = null;
public Macro(long timestamp, String query) {
this.current = timestamp;
this.start = timestamp;
this.end = timestamp;
this.query = query;
}
public Macro(long startTime, long endTime, String query) {
this.current = endTime;
this.start = startTime;
this.end = endTime;
forCharting = true;
this.query = query;
}
public Macro(long startTime, long endTime, String query, HttpServletRequest request) {
this.request = request;
this.current = endTime;
this.start = startTime;
this.end = endTime;
forCharting = true;
this.query = query;
}
public HashMap<String,String> findMacros(String query) throws SQLException {
boolean add=false;
HashMap<String,String> macroList = new HashMap<String,String>();
String macro="";
for(int i=0;i<query.length();i++) {
if(query.charAt(i)==']') {
add=false;
if(!macroList.containsKey(macro)) {
String subString = computeMacro(macro);
macroList.put(macro,subString);
}
macro="";
}
if(add) {
macro=macro+query.charAt(i);
}
if(query.charAt(i)=='[') {
add=true;
}
}
return macroList;
}
public String computeMacro(String macro) throws SQLException {
Pattern p = Pattern.compile("past_(.*)_minutes");
Matcher matcher = p.matcher(macro);
if(macro.indexOf("avg(")==0 || macro.indexOf("group_avg(")==0 || macro.indexOf("sum(")==0) {
String meta="";
String[] table = null;
if(forCharting) {
table = dbc.findTableNameForCharts(macro.substring(macro.indexOf("(")+1,macro.indexOf(")")), start, end);
} else {
table = dbc.findTableName(macro.substring(macro.indexOf("(")+1,macro.indexOf(")")), start, end);
}
try {
String cluster = System.getProperty("CLUSTER");
if(cluster==null) {
cluster="unknown";
}
db = new DatabaseWriter(cluster);
DatabaseMetaData dbMetaData = db.getConnection().getMetaData();
ResultSet rs = dbMetaData.getColumns ( null,null,table[0], null);
boolean first=true;
while(rs.next()) {
if(!first) {
meta = meta+",";
}
String name = rs.getString(4);
int type = rs.getInt(5);
if(type==java.sql.Types.VARCHAR) {
if(macro.indexOf("group_avg(")<0) {
meta=meta+"count("+name+") as "+name;
} else {
meta=meta+name;
}
first=false;
} else if(type==java.sql.Types.DOUBLE ||
type==java.sql.Types.FLOAT ||
type==java.sql.Types.INTEGER) {
if(macro.indexOf("sum(")==0) {
meta=meta+"sum("+name+")";
} else {
meta=meta+"avg("+name+")";
}
first=false;
} else if(type==java.sql.Types.TIMESTAMP) {
meta=meta+name;
first=false;
} else {
if(macro.indexOf("sum(")==0) {
meta=meta+"SUM("+name+")";
} else {
meta=meta+"AVG("+name+")";
}
first=false;
}
}
db.close();
if(first) {
throw new SQLException("Table is undefined.");
}
} catch(SQLException ex) {
throw new SQLException("Table does not exist:"+ table[0]);
}
return meta;
} else if(macro.indexOf("now")==0) {
return DatabaseWriter.formatTimeStamp(current);
} else if(macro.intern()=="start".intern()) {
return DatabaseWriter.formatTimeStamp(start);
} else if(macro.intern()=="end".intern()) {
return DatabaseWriter.formatTimeStamp(end);
} else if(matcher.find()) {
int period = Integer.parseInt(matcher.group(1));
long timestamp = current - (current % (period*60*1000L)) - (period*60*1000L);
return DatabaseWriter.formatTimeStamp(timestamp);
} else if(macro.indexOf("past_hour")==0) {
return DatabaseWriter.formatTimeStamp(current-3600*1000L);
} else if(macro.endsWith("_week")) {
long partition = current / DatabaseConfig.WEEK;
if(partition<=0) {
partition=1;
}
String[] buffers = macro.split("_");
StringBuffer tableName = new StringBuffer();
for(int i=0;i<buffers.length-1;i++) {
tableName.append(buffers[i]);
tableName.append("_");
}
tableName.append(partition);
tableName.append("_week");
return tableName.toString();
} else if(macro.endsWith("_month")) {
long partition = current / DatabaseConfig.MONTH;
if(partition<=0) {
partition=1;
}
String[] buffers = macro.split("_");
StringBuffer tableName = new StringBuffer();
for(int i=0;i<buffers.length-1;i++) {
tableName.append(buffers[i]);
tableName.append("_");
}
tableName.append(partition);
tableName.append("_month");
return tableName.toString();
} else if(macro.endsWith("_quarter")) {
long partition = current / DatabaseConfig.QUARTER;
if(partition<=0) {
partition=1;
}
String[] buffers = macro.split("_");
StringBuffer tableName = new StringBuffer();
for(int i=0;i<buffers.length-1;i++) {
tableName.append(buffers[i]);
tableName.append("_");
}
tableName.append(partition);
tableName.append("_quarter");
return tableName.toString();
} else if(macro.endsWith("_year")) {
long partition = current / DatabaseConfig.YEAR;
if(partition<=0) {
partition=1;
}
String[] buffers = macro.split("_");
StringBuffer tableName = new StringBuffer();
for(int i=0;i<buffers.length-1;i++) {
tableName.append(buffers[i]);
tableName.append("_");
}
tableName.append(partition);
tableName.append("_year");
return tableName.toString();
} else if(macro.endsWith("_decade")) {
long partition = current / DatabaseConfig.DECADE;
if(partition<=0) {
partition=1;
}
String[] buffers = macro.split("_");
StringBuffer tableName = new StringBuffer();
for(int i=0;i<buffers.length-1;i++) {
tableName.append(buffers[i]);
tableName.append("_");
}
tableName.append(partition);
tableName.append("_decade");
return tableName.toString();
}
if(forCharting) {
if(macro.startsWith("session(") && request!=null){
String keyword = macro.substring(macro.indexOf("(")+1,macro.indexOf(")"));
String[] objects = null;
if(request.getSession().getAttribute(keyword)!=null) {
objects = ((String)request.getSession().getAttribute(keyword)).split(",");
}
StringBuffer buf = new StringBuffer();
boolean first = true;
if(objects!=null) {
for(String object : objects) {
if(!first) {
buf.append(" or ");
}
first = false;
buf.append(macro.substring(macro.indexOf("(")+1,macro.indexOf(")"))+"='"+object+"'");
}
return buf.toString();
}
return "";
} else {
String[] tableList = dbc.findTableNameForCharts(macro, start, end);
StringBuffer buf = new StringBuffer();
boolean first = true;
for(String table : tableList) {
if(!first) {
buf.append("|");
}
first = false;
buf.append(table);
}
return buf.toString();
}
}
String[] tableList = dbc.findTableName(macro,current,current);
return tableList[0];
}
public String toString() {
try {
HashMap<String, String> macroList = findMacros(query);
for(Entry<String, String> entry : macroList.entrySet()) {
String mkey = entry.getKey();
String value = entry.getValue();
if(value.contains("|")) {
StringBuffer buf = new StringBuffer();
String[] tableList = value.split("\\|");
boolean first = true;
for(String table : tableList) {
String newQuery = query.replace("["+mkey+"]", table);
if(!first) {
buf.append(" union ");
}
buf.append("(");
buf.append(newQuery);
buf.append(")");
first = false;
}
query = buf.toString();
} else {
log.debug("replacing:"+mkey+" with "+macroList.get(mkey));
query = query.replace("["+mkey+"]", macroList.get(mkey));
}
}
} catch(SQLException ex) {
log.error(query);
log.error(ex.getMessage());
}
return query;
}
}