package com.alvazan.play.logging;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.joda.time.LocalDateTime;
import com.alvazan.orm.api.base.NoSqlEntityManager;
import com.alvazan.orm.api.base.spi.UniqueKeyGenerator;
import com.alvazan.orm.api.z8spi.KeyValue;
import com.alvazan.orm.api.z8spi.iter.AbstractCursor;
import com.alvazan.orm.api.z8spi.iter.Cursor;
import com.alvazan.play.NoSql;
public class LogDao {
public static Cursor<LogEvent> fetchAllLogs(NoSqlEntityManager mgr, int batchSize) {
ServersThatLog servers = NoSql.em().find(ServersThatLog.class, ServersThatLog.THE_ONE_KEY);
List<String> serverNames = new ArrayList<String>();
if(servers != null)
serverNames = servers.getServers();
String host = UniqueKeyGenerator.getHostname();
if(!serverNames.contains(host))
serverNames.add(host);
return new LogIterator(mgr, serverNames, batchSize);
}
public static Cursor<KeyValue<LogEvent>> fetchLatestLogs(NoSqlEntityManager mgr, int count) {
ServersThatLog servers = NoSql.em().find(ServersThatLog.class, ServersThatLog.THE_ONE_KEY);
List<String> serverNames = new ArrayList<String>();
String serverName = null;
if(servers != null) {
serverNames = servers.getServers();
serverName = servers.getServers().get(0);
}
Integer index = null;
int row = 0;
Answer t = new Answer(null, row);
do {
findLatestRow(mgr, serverName, t);
index = t.getAnswer();
row = t.getRow();
} while(index == null);
int min = Math.max(0, index-count);
int max = index;
List<String> keys = createKeys(serverNames, min, max);
return mgr.findAll(LogEvent.class, keys);
}
private static List<String> createKeys(List<String> serverNames, int min, int max) {
List<String> keys = new ArrayList<String>();
for(int i = min; i < max; i++) {
for(String name : serverNames) {
String newName = name+i;
keys.add(newName);
}
}
return keys;
}
private static void findLatestRow(NoSqlEntityManager mgr, String serverName, Answer ans) {
int row = ans.getRow();
List<String> keys = new ArrayList<String>();
for(int i = row; i < 200+row; i++) {
String name = serverName + i;
keys.add(name);
}
mgr.clear();
Cursor<KeyValue<LogEvent>> cursor = mgr.findAll(LogEvent.class, keys);
long time = 0;
LocalDateTime current = new LocalDateTime(time);
while(cursor.next()) {
KeyValue<LogEvent> kv = cursor.getCurrent();
LogEvent value = kv.getValue();
if(value == null) {
ans.setAnswer(row);
return;
}
LocalDateTime t1 = value.getTime();
if(current.isAfter(t1)) {
ans.setAnswer(row);
return;
}
current = t1;
row++;
}
ans.setRow(row);
}
private static Iterable<KeyValue<LogEvent>> fetchSessionLogs(NoSqlEntityManager mgr, String sessionId, int numDigits) {
return LogEvent.findBySession(mgr, sessionId, numDigits);
}
public static List<LogEvent> fetchOrderedSessionLogs(NoSqlEntityManager mgr, String sessionId, int numDigits) {
Iterable<KeyValue<LogEvent>> iter = fetchSessionLogs(mgr, sessionId, numDigits);
List<LogEvent> events = new ArrayList<LogEvent>();
for(KeyValue<LogEvent> evts : iter) {
if(evts.getValue() != null) {
events.add(evts.getValue());
}
}
Collections.sort(events, new ByDate());
return events;
}
private static class LogIterator extends AbstractCursor<LogEvent> {
private NoSqlEntityManager mgr;
private List<String> serverNames;
private int batchSize;
private AbstractCursor<KeyValue<LogEvent>> event = null;
private int counter = 0;
public LogIterator(NoSqlEntityManager mgr, List<String> serverNames, int batchSize) {
this.mgr = mgr;
this.serverNames = serverNames;
this.batchSize = batchSize;
}
@Override
public void beforeFirst() {
counter = 0;
fetchNewBatch();
}
//TODO:JSC none of this works if I can't figure out what the last index/size/number of results is...
@Override
public void afterLast() {
counter = 0; //<-- JSC here
fetchNewBatchFromEnd();
}
@Override
public com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder<LogEvent> nextImpl() {
if(event == null)
fetchNewBatch();
Holder<KeyValue<LogEvent>> nextImpl = event.nextImpl();
if(nextImpl == null) {
fetchNewBatch();
nextImpl = event.nextImpl();
}
if(nextImpl == null)
return null;
KeyValue<LogEvent> kv = nextImpl.getValue();
if(kv.getValue() == null)
return null;
return new Holder<LogEvent>(kv.getValue());
}
@Override
public com.alvazan.orm.api.z8spi.iter.AbstractCursor.Holder<LogEvent> previousImpl() {
if(event == null)
fetchNewBatchFromEnd();
Holder<KeyValue<LogEvent>> prevImpl = event.previousImpl();
if(prevImpl == null) {
fetchNewBatchFromEnd();
prevImpl = event.previousImpl();
}
if(prevImpl == null)
return null;
KeyValue<LogEvent> kv = prevImpl.getValue();
if(kv.getValue() == null)
return null;
return new Holder<LogEvent>(kv.getValue());
}
// @Override
// public boolean hasNext() {
// log.info("has next being called");
// if(nextVal != null)
// return true;
// else if(counter > maxCount)
// return false;
//
// log.info("fetch batch maybe");
// fetchBatch();
// if(!event.hasNext())
// return false;
// KeyValue<LogEvent> next = event.next();
// if(next.getValue() == null)
// return false;
// nextVal = next.getValue();
// return true;
// }
private void fetchNewBatch() {
List<String> keys = createKeys(serverNames, counter, counter+batchSize);
counter = counter+batchSize;
mgr.clear();
event = (AbstractCursor<KeyValue<LogEvent>>) mgr.findAll(LogEvent.class, keys);
}
private void fetchNewBatchFromEnd() {
List<String> keys = createKeys(serverNames, counter-batchSize, counter);
counter = counter-batchSize;
mgr.clear();
event = (AbstractCursor<KeyValue<LogEvent>>) mgr.findAll(LogEvent.class, keys);
}
// @Override
// public LogEvent next() {
// if(!hasNext())
// throw new IllegalStateException("no more elements, check hasNext first");
// LogEvent temp = nextVal;
// nextVal = null;
// return temp;
// }
//
// @Override
// public void remove() {
// throw new UnsupportedOperationException("not supported");
// }
}
}