/*
* Copyright 2013 Eediom Inc.
*
* Licensed 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.araqne.log.api;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
public class WtmpLogger extends AbstractLogger implements Reconfigurable {
private final org.slf4j.Logger slog = org.slf4j.LoggerFactory.getLogger(WtmpLogger.class);
private final File dataDir;
private String path;
public WtmpLogger(LoggerSpecification spec, LoggerFactory factory) {
super(spec, factory);
dataDir = new File(System.getProperty("araqne.data.dir"), "araqne-log-api");
dataDir.mkdirs();
path = spec.getConfig().get("path");
// try migration at boot
File oldLastFile = getLastLogFile();
if (oldLastFile.exists()) {
Map<String, LastPosition> lastPositions = LastPositionHelper.readLastPositions(oldLastFile);
setStates(LastPositionHelper.serialize(lastPositions));
oldLastFile.renameTo(new File(oldLastFile.getAbsolutePath() + ".migrated"));
}
}
@Override
public void onConfigChange(Map<String, String> oldConfigs, Map<String, String> newConfigs) {
if (!oldConfigs.get("path").equals(newConfigs.get("path"))) {
this.path = newConfigs.get("path");
setStates(new HashMap<String, Object>());
}
}
private WtmpEntryParser buildParser(String server) {
if (server == null)
return new WtmpEntryParserLinux();
server = server.toLowerCase();
if (server.equals("solaris"))
return new WtmpEntryParserSolaris();
else if (server.equals("aix"))
return new WtmpEntryParserAix();
else if (server.equals("hpux"))
return new WtmpEntryParserHpUx();
return new WtmpEntryParserLinux();
}
@Override
protected void runOnce() {
Map<String, LastPosition> lastPositions = LastPositionHelper.deserialize(getStates());
LastPosition inform = lastPositions.get(path);
if (inform == null)
inform = new LastPosition(path);
long pos = inform.getPosition();
File wtmpFile = new File(path);
if (!wtmpFile.exists()) {
slog.debug("araqne log api: logger [{}] wtmp file [{}] doesn't exist", getFullName(), path);
return;
}
if (!wtmpFile.canRead()) {
slog.debug("araqne log api: logger [{}] wtmp file [{}] no read permission", getFullName(), path);
return;
}
// log rotated case, reset read offset
if (wtmpFile.length() < pos) {
pos = 0;
}
WtmpEntryParser parser = buildParser(getConfigs().get("server"));
int blockSize = parser.getBlockSize();
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(wtmpFile, "r");
raf.seek(pos);
byte[] block = new byte[blockSize];
while (true) {
raf.readFully(block);
WtmpEntry e = parser.parseEntry(ByteBuffer.wrap(block));
Map<String, Object> data = new HashMap<String, Object>();
data.put("type", e.getType().toString());
data.put("host", e.getHost());
data.put("pid", e.getPid());
data.put("session", e.getSession());
data.put("user", e.getUser());
data.put("device", e.getDeviceName());
data.put("inittab_id", e.getInitTabId());
write(new SimpleLog(e.getDate(), getFullName(), data));
pos += blockSize;
}
} catch (EOFException e) {
// ignore
} catch (Throwable t) {
slog.error("araqne log api: logger [" + getFullName() + "] cannot load wtmp file [" + path + "]", t);
} finally {
if (raf != null) {
try {
raf.close();
} catch (IOException e) {
}
}
inform.setPosition(pos);
lastPositions.put(path, inform);
setStates(LastPositionHelper.serialize(lastPositions));
}
}
protected File getLastLogFile() {
return new File(dataDir, "wtmp-" + getName() + ".lastlog");
}
}