package codeine.db.mysql.connectors;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import codeine.db.IAlertsDatabaseConnector;
import codeine.db.mysql.DbUtils;
import codeine.jsons.global.ExperimentalConfJsonStore;
import codeine.jsons.mails.AlertsCollectionType;
import codeine.jsons.mails.CollectorNotificationJson;
import codeine.utils.ExceptionUtils;
import com.google.common.base.Function;
import com.google.common.base.Stopwatch;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.gson.Gson;
//TODO remove after all components using notifications
public class AlertsMysqlConnector implements IAlertsDatabaseConnector{
private static final Logger log = Logger.getLogger(AlertsMysqlConnector.class);
private DbUtils dbUtils;
private Gson gson;
private ExperimentalConfJsonStore webConfJsonStore;
private static final String TABLE_NAME = "Alerts";
@Inject
public AlertsMysqlConnector(DbUtils dbUtils, Gson gson, ExperimentalConfJsonStore webConfJsonStore) {
super();
this.dbUtils = dbUtils;
this.gson = gson;
this.webConfJsonStore = webConfJsonStore;
}
public void createTables() {
if (webConfJsonStore.get().readonly_web_server()) {
log.info("read only mode");
return;
}
String colsDefinition = "id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, data text, collection_type_update_time BIGINT, collection_type BIGINT";
dbUtils.executeUpdate("create table if not exists " + TABLE_NAME + " (" + colsDefinition + ")");
}
@Override
public void put(CollectorNotificationJson collectorNotificationJson) {
String json = gson.toJson(collectorNotificationJson);
dbUtils.executeUpdate("INSERT INTO "+TABLE_NAME+" (data) VALUES (?)", json);
}
@Override
public Multimap<String, CollectorNotificationJson> getAlertsAndUpdate(final AlertsCollectionType collType) {
long time = System.currentTimeMillis();
Stopwatch s = Stopwatch.createStarted();
MapWithId $ = query(collType);
String queryMessage = "query took " + s;
s = Stopwatch.createStarted();
updateCollectionType(collType, time, $.maxId);
log.info(queryMessage + ", update took " + s + " on " + dbUtils);
return $.map;
}
private void updateCollectionType(final AlertsCollectionType collType, long time, int maxId) {
if (webConfJsonStore.get().readonly_web_server()) {
log.info("read only mode");
}
String updateString = "UPDATE " + TABLE_NAME + " SET collection_type_update_time=" + time +
",collection_type=" + collType.toLong() +
" WHERE id<=" + maxId + " AND ("
+ "(collection_type < " + collType.toLong() + " AND collection_type >= " + collType.previousType().toLong() + ")";
if (collType == AlertsCollectionType.Immediately) {
updateString += " OR collection_type IS NULL";
}
updateString += ")";
dbUtils.executeUpdate(updateString);
}
private static class MapWithId {
Multimap<String, CollectorNotificationJson> map;
int maxId;
public MapWithId(Multimap<String, CollectorNotificationJson> map, int maxId) {
this.map = map;
this.maxId = maxId;
}
}
private MapWithId query(final AlertsCollectionType collType) {
final AtomicInteger count = new AtomicInteger(0);
final AtomicInteger maxId = new AtomicInteger(0);
final Multimap<String, CollectorNotificationJson> $ = HashMultimap.create();
Function<ResultSet, Void> function = new Function<ResultSet, Void>() {
@Override
public Void apply(ResultSet rs){
if (webConfJsonStore.get().readonly_web_server()) {
return null;
}
try {
String data = rs.getString("data");
// Long type = rs.getLong("collection_type");
int id = rs.getInt("id");
maxId.set(Math.max(maxId.get(), id));
CollectorNotificationJson n = gson.fromJson(data, CollectorNotificationJson.class);
$.put(n.project_name(),n);
count.incrementAndGet();
return null;
} catch (SQLException e) {
throw ExceptionUtils.asUnchecked(e);
}
}
};
dbUtils.executeQueryCompressed("SELECT id, data, collection_type_update_time, collection_type FROM " + TABLE_NAME +
" WHERE collection_type < " + collType.toLong() + " OR collection_type IS NULL" , function);
if (count.intValue() > 0){
log.info("handled col type " + collType + " with num of events " + count.intValue() + " on " + dbUtils);
}
return new MapWithId($, maxId.get());
}
@Override
public void removeOldAlerts() {
if (webConfJsonStore.get().readonly_web_server()) {
log.info("read only mode");
return;
}
long timeToRemove = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(3);
log.info("will remove older than " + timeToRemove + " on " + dbUtils);
String deleteSql = "delete from " + TABLE_NAME + " where collection_type_update_time < " + timeToRemove + " AND collection_type = " + AlertsCollectionType.Daily.toLong();
dbUtils.executeUpdate(deleteSql);
}
@Override
public String toString() {
return "AlertsMysqlConnector [dbUtils=" + dbUtils + "]";
}
}