├── .gitignore
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── github
│ └── xlogger
│ ├── XLogger.java
│ ├── client
│ └── XLoggerClient.java
│ ├── common
│ └── XLoggerData.java
│ └── server
│ ├── XLoggerServer.java
│ ├── codec
│ └── XLoggerDecoder.java
│ └── store
│ ├── Storage.java
│ ├── StorageFactory.java
│ └── imp
│ └── JDBCStorage.java
└── test
└── java
└── com
└── github
└── xlogger
├── XLoggerServerTest.java
└── XLoggerTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .project
2 | .classpath
3 | .settings/
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | XLogger
2 | =======
3 |
4 | XLogger 是个基于Netty的日志记录系统
5 |
6 | XLogger 目前支持可以直接将java序列化的类直接写入到数据库,但数据库的格式目前有依赖。
7 | 例如:如果你的Log表的结构,第一个字段是一个唯一性数据(自增长的Id或者别的唯一性的主键)
8 | 第二个字段是数据的插入时间,当然你如果不能满足需求,或者需求差异可以直接修改代码。
9 |
10 | 客户端要是使用,直接初始化:
11 |
12 | XLogger.initXLogger("localhost", (short) 4000, 30000);
13 | 数据记录:
14 | XLogger.log("Test", "1111", i);
15 | 第一个是表的名称,后面则是你的数据字段。
16 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 | com.github
4 | XLogger
5 | 0.0.1
6 | XLogger
7 |
8 | UTF-8
9 |
10 |
11 |
12 |
13 |
14 | org.apache.maven.plugins
15 | maven-compiler-plugin
16 | 2.0.2
17 |
18 | 1.6
19 | 1.6
20 |
21 |
22 |
23 |
24 |
25 |
26 | io.netty
27 | netty
28 | 3.5.3.Final
29 |
30 |
31 | mysql
32 | mysql-connector-java
33 | 5.1.20
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/main/java/com/github/xlogger/XLogger.java:
--------------------------------------------------------------------------------
1 | package com.github.xlogger;
2 |
3 | import com.github.xlogger.client.XLoggerClient;
4 | import com.github.xlogger.common.XLoggerData;
5 |
6 | public final class XLogger {
7 |
8 | private static XLoggerClient client = null;
9 |
10 | private static Thread clientThread = null;
11 | /**
12 | * 设置服务器地址和端口,以及Timout
13 | * @param host
14 | * @param port
15 | * @param timeout
16 | */
17 | synchronized public static void initXLogger(String host, short port, int timeout) {
18 | if (client == null) {
19 | client = new XLoggerClient(host, port, timeout);
20 | client.connect();
21 | clientThread = new Thread(client);
22 | clientThread.start();
23 | }
24 | }
25 |
26 | public static void log(String tabName, Object ... args) {
27 | final XLoggerData data = new XLoggerData(tabName, System.currentTimeMillis(), args);
28 | client.sendLog(data);
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/github/xlogger/client/XLoggerClient.java:
--------------------------------------------------------------------------------
1 | package com.github.xlogger.client;
2 |
3 | import java.net.InetSocketAddress;
4 | import java.util.Queue;
5 | import java.util.concurrent.ConcurrentLinkedQueue;
6 | import java.util.concurrent.Executors;
7 | import java.util.logging.Level;
8 | import java.util.logging.Logger;
9 |
10 | import org.jboss.netty.bootstrap.ClientBootstrap;
11 | import org.jboss.netty.channel.Channel;
12 | import org.jboss.netty.channel.ChannelFuture;
13 | import org.jboss.netty.channel.ChannelFutureListener;
14 | import org.jboss.netty.channel.ChannelHandlerContext;
15 | import org.jboss.netty.channel.ChannelPipeline;
16 | import org.jboss.netty.channel.ChannelPipelineFactory;
17 | import org.jboss.netty.channel.ChannelStateEvent;
18 | import org.jboss.netty.channel.Channels;
19 | import org.jboss.netty.channel.ExceptionEvent;
20 | import org.jboss.netty.channel.MessageEvent;
21 | import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
22 | import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
23 |
24 | import com.github.xlogger.common.XLoggerData;
25 |
26 | public class XLoggerClient implements Runnable {
27 |
28 | private static final Logger logger = Logger.getLogger(XLoggerClient.class.getName());
29 |
30 | private Queue loggerQueue = new ConcurrentLinkedQueue();
31 |
32 | private class XLoggerHandler extends SimpleChannelUpstreamHandler {
33 |
34 | private Channel channel = null;
35 |
36 | public void flushData() {
37 | if (connected && channel != null) {
38 | XLoggerData data = null;
39 | while ((data = loggerQueue.poll()) != null) {
40 | if (channel.isOpen())
41 | channel.write(data.toBuffer());
42 | else {
43 | connected = false;
44 | loggerQueue.add(data);
45 | connect();
46 | break;
47 | }
48 | }
49 | }
50 | }
51 |
52 | @Override
53 | public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
54 | this.channel = ctx.getChannel();
55 | connected = true;
56 | lastIoTime = System.currentTimeMillis();
57 | }
58 |
59 | @Override
60 | public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
61 | lastIoTime = System.currentTimeMillis();
62 | }
63 |
64 | @Override
65 | public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
66 | logger.log(Level.WARNING,
67 | "Unexpected exception from downstream.", e.getCause().getMessage());
68 | if (channel != null)
69 | e.getChannel().close();
70 | connected = false;
71 | }
72 | }
73 |
74 | private XLoggerHandler handler = new XLoggerHandler();
75 |
76 | private volatile boolean connected;
77 |
78 | private boolean isConnected() {
79 | return connected;
80 | }
81 |
82 | private String host;
83 |
84 | private short port;
85 |
86 | private int timeout;
87 |
88 | private ClientBootstrap bootstrap;
89 |
90 | private volatile boolean isRunning = false;
91 |
92 | public XLoggerClient(String host, short port, int timeout) {
93 | this.host = host;
94 | this.port = port;
95 | this.timeout = timeout;
96 | bootstrap = new ClientBootstrap(
97 | new NioClientSocketChannelFactory(
98 | Executors.newCachedThreadPool(),
99 | Executors.newCachedThreadPool()));
100 | // Set up the pipeline factory.
101 | bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
102 | public ChannelPipeline getPipeline() throws Exception {
103 | return Channels.pipeline(handler);
104 | }
105 | });
106 |
107 | bootstrap.setOption("tcpNoDelay", "true");
108 | bootstrap.setOption("keepAlive", true);
109 | isRunning = true;
110 | }
111 |
112 | public boolean connect() {
113 | // Start the connection attempt.
114 | try {
115 | ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
116 | future.awaitUninterruptibly();
117 | logger.info("success = " + future.isSuccess());
118 | future.addListener(new ChannelFutureListener() {
119 | public void operationComplete(ChannelFuture future) throws Exception {
120 | if (future.isSuccess()) {
121 | connected = true;
122 | logger.info("connected ok");
123 | }
124 | }
125 | });
126 | return true;
127 | } catch (Exception e) {
128 | logger.info(e.getMessage());
129 | }
130 | return false;
131 | }
132 |
133 | private void onShutdown() {
134 | connected = false;
135 | bootstrap.releaseExternalResources();
136 | }
137 |
138 | public void sendLog(final XLoggerData data) {
139 | synchronized (loggerQueue) {
140 | loggerQueue.add(data);
141 | loggerQueue.notifyAll();
142 | }
143 | }
144 |
145 | private long lastIoTime;
146 |
147 | /**
148 | * 检测连接是否超时和定时发送ping消息
149 | */
150 | @Override
151 | public void run() {
152 | while (isRunning) {
153 | if (!isConnected()) {
154 | try {
155 | Thread.sleep(100);
156 | } catch (InterruptedException e) {
157 | }
158 | }
159 | long now = System.currentTimeMillis();
160 | if (now - lastIoTime >= timeout) {
161 | // io 超时
162 | // 连接远程服务器超时,需要重连
163 | connect();
164 | try {
165 | Thread.sleep(2000);
166 | } catch (InterruptedException e) {
167 | // ignore
168 | }
169 | }
170 | synchronized (loggerQueue) {
171 | if (loggerQueue.isEmpty()) {
172 | try {
173 | loggerQueue.wait();
174 | } catch (InterruptedException e) {
175 | e.printStackTrace();
176 | }
177 | }
178 | }
179 | handler.flushData();
180 | }
181 | onShutdown();
182 | }
183 |
184 | }
185 |
--------------------------------------------------------------------------------
/src/main/java/com/github/xlogger/common/XLoggerData.java:
--------------------------------------------------------------------------------
1 | package com.github.xlogger.common;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.IOException;
6 | import java.io.ObjectInputStream;
7 | import java.io.ObjectOutputStream;
8 |
9 | import org.jboss.netty.buffer.ChannelBuffer;
10 | import org.jboss.netty.buffer.ChannelBuffers;
11 |
12 | public class XLoggerData {
13 |
14 | public String getTabName() {
15 | return tabName;
16 | }
17 |
18 | public long getEventId() {
19 | return eventId;
20 | }
21 |
22 | public Object[] getArgs() {
23 | return args;
24 | }
25 |
26 | public XLoggerData(String tabName, long eventId, Object[] args) {
27 | super();
28 | this.tabName = tabName;
29 | this.eventId = eventId;
30 | this.args = args;
31 | }
32 |
33 | public XLoggerData(ChannelBuffer buffer) {
34 | short tablen = buffer.readShort();
35 | byte[] tabbytes = new byte[tablen];
36 | buffer.readBytes(tabbytes);
37 | this.tabName = new String(tabbytes);
38 | this.eventId = buffer.readLong();
39 | int objlen = buffer.readInt();
40 | this.args = new Object[objlen];
41 | byte[] objsbyte = new byte[buffer.readableBytes()];
42 | buffer.readBytes(objsbyte);
43 | ByteArrayInputStream bais = new ByteArrayInputStream(objsbyte);
44 | ObjectInputStream ois;
45 | try {
46 | ois = new ObjectInputStream(bais);
47 | for (int i = 0; i < objlen; i++) {
48 | this.args[i] = ois.readObject();
49 | }
50 | } catch (IOException e) {
51 | e.printStackTrace();
52 | } catch (ClassNotFoundException e) {
53 | e.printStackTrace();
54 | }
55 | }
56 |
57 | private String tabName;
58 |
59 | private long eventId;
60 |
61 | private Object[] args;
62 |
63 | public ChannelBuffer toBuffer() {
64 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
65 | ObjectOutputStream oos = null;
66 | try {
67 | oos = new ObjectOutputStream(baos);
68 | for (Object obj: args) {
69 | oos.writeObject(obj);
70 | }
71 | byte[] data = baos.toByteArray();
72 | byte[] tabbytes = tabName.getBytes();
73 | int bufferlen = data.length + 8 + tabbytes.length + 2 + 4;
74 | ChannelBuffer buffer = ChannelBuffers.buffer(bufferlen + 4);
75 | buffer.writeInt(bufferlen);
76 | buffer.writeShort(tabbytes.length);
77 | buffer.writeBytes(tabbytes);
78 | buffer.writeLong(eventId);
79 | buffer.writeInt(args.length);
80 | buffer.writeBytes(data);
81 | return buffer;
82 | } catch (IOException e) {
83 | e.printStackTrace();
84 | return null;
85 | } finally {
86 | if (oos != null) {
87 | try {
88 | oos.close();
89 | } catch (IOException e) {
90 | }
91 | }
92 | try {
93 | baos.close();
94 | } catch (IOException e) {
95 | }
96 | }
97 | }
98 |
99 | public String toSQL() {
100 | StringBuilder sb = new StringBuilder();
101 | sb.append("insert delayed `").append(tabName).append("` values(null, null");
102 | for (int i = 0; i < args.length; i++) {
103 | sb.append(",?");
104 | }
105 | sb.append(")");
106 | return sb.toString();
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/java/com/github/xlogger/server/XLoggerServer.java:
--------------------------------------------------------------------------------
1 | package com.github.xlogger.server;
2 |
3 | import java.net.InetSocketAddress;
4 | import java.util.Timer;
5 | import java.util.TimerTask;
6 | import java.util.concurrent.ConcurrentHashMap;
7 | import java.util.concurrent.ConcurrentLinkedQueue;
8 | import java.util.concurrent.ConcurrentMap;
9 | import java.util.concurrent.Executors;
10 | import java.util.concurrent.atomic.AtomicInteger;
11 | import java.util.logging.Level;
12 | import java.util.logging.Logger;
13 |
14 | import org.jboss.netty.bootstrap.ServerBootstrap;
15 | import org.jboss.netty.buffer.ChannelBuffer;
16 | import org.jboss.netty.buffer.ChannelBuffers;
17 | import org.jboss.netty.channel.Channel;
18 | import org.jboss.netty.channel.ChannelHandlerContext;
19 | import org.jboss.netty.channel.ChannelPipeline;
20 | import org.jboss.netty.channel.ChannelPipelineFactory;
21 | import org.jboss.netty.channel.ChannelStateEvent;
22 | import org.jboss.netty.channel.Channels;
23 | import org.jboss.netty.channel.ExceptionEvent;
24 | import org.jboss.netty.channel.MessageEvent;
25 | import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
26 | import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
27 |
28 | import com.github.xlogger.common.XLoggerData;
29 | import com.github.xlogger.server.codec.XLoggerDecoder;
30 | import com.github.xlogger.server.store.StorageFactory;
31 |
32 | public class XLoggerServer {
33 | private static final Logger logger = Logger.getLogger(LoggerHandler.class.getName());
34 |
35 | private static final ConcurrentMap connectionMap = new ConcurrentHashMap();
36 |
37 | private static final ConcurrentLinkedQueue unWroteQueue = new ConcurrentLinkedQueue();
38 |
39 | private static class LoggerHandler extends SimpleChannelUpstreamHandler {
40 | AtomicInteger count = new AtomicInteger();
41 |
42 | @Override
43 | public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
44 | connectionMap.put(ctx.getChannel(), System.currentTimeMillis());
45 | }
46 |
47 | @Override
48 | public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
49 | connectionMap.remove(ctx.getChannel());
50 | }
51 |
52 | @Override
53 | public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
54 | // e.getChannel().write(e.getMessage());
55 | if (e.getMessage() instanceof XLoggerData) {
56 | final XLoggerData data = (XLoggerData)e.getMessage();
57 | try {
58 | StorageFactory.saveLog(data);
59 | } catch (Exception e1) {
60 | e1.printStackTrace();
61 | unWroteQueue.add(data);
62 | if (unWroteQueue.size() > 100) {
63 | logger.warning("too many messages not wrote!!!");
64 | }
65 | }
66 | if (count.incrementAndGet() % 10000 == 0)
67 | logger.info(data.getTabName() + " time = " + data.getEventId());
68 | }
69 | }
70 |
71 | @Override
72 | public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
73 | // Close the connection when an exception is raised.
74 | logger.log(Level.WARNING, "Unexpected exception from downstream.", e.getCause());
75 | e.getChannel().close();
76 | }
77 | }
78 |
79 | private static LoggerHandler handler = new LoggerHandler();
80 |
81 | public static void start(String host, short port) {
82 | ServerBootstrap bootstrap = new ServerBootstrap(
83 | new NioServerSocketChannelFactory(
84 | Executors.newCachedThreadPool(),
85 | Executors.newCachedThreadPool()));
86 |
87 | bootstrap.setOption("tcpNoDelay", true);
88 | // Set up the pipeline factory.
89 | bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
90 | public ChannelPipeline getPipeline() throws Exception {
91 | return Channels.pipeline(new XLoggerDecoder(1024 * 10, 0, 4), handler);
92 | }
93 | });
94 | // Bind and start to accept incoming connections.
95 | bootstrap.bind(new InetSocketAddress(host, port));
96 | Timer idleTimer = new Timer("IdleTimer", true);
97 | idleTimer.scheduleAtFixedRate(new TimerTask() {
98 |
99 | @Override
100 | public void run() {
101 | for (Channel c: connectionMap.keySet()) {
102 | if (c.isConnected()) {
103 | try {
104 | ChannelBuffer cb = ChannelBuffers.buffer(1);
105 | cb.writeByte(100);
106 | c.write(cb);
107 | } catch (Exception e) {
108 | logger.info(e.getCause().getMessage());
109 | }
110 | }
111 | }
112 | }
113 | }, 1000, 10000);
114 | }
115 |
116 | public static void startInThread(final String host, final short port) {
117 | Thread t = new Thread(new Runnable() {
118 | @Override
119 | public void run() {
120 | start(host, port);
121 | }
122 | }, "XLoggerServer");
123 | t.setDaemon(true);
124 | t.start();
125 | }
126 |
127 | public static void main(String[] args) {
128 | if (args.length < 3) {
129 | System.err.println("You have to configurate the jdbcDriver, url, user, passwd");
130 | return;
131 | } else {
132 | if (StorageFactory.setupJDBC(args[0], args[1], args[2], args[3])) {
133 | System.out.println("Connect the database is ok");
134 | start("localhost", (short)4000);
135 | }
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/main/java/com/github/xlogger/server/codec/XLoggerDecoder.java:
--------------------------------------------------------------------------------
1 | package com.github.xlogger.server.codec;
2 |
3 | import org.jboss.netty.buffer.ChannelBuffer;
4 | import org.jboss.netty.channel.Channel;
5 | import org.jboss.netty.channel.ChannelHandlerContext;
6 | import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;
7 |
8 | import com.github.xlogger.common.XLoggerData;
9 |
10 | /**
11 | * 解析发送过来的消息
12 | * @author Steven
13 | *
14 | */
15 | public class XLoggerDecoder extends LengthFieldBasedFrameDecoder {
16 | public XLoggerDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) {
17 | super(maxFrameLength, lengthFieldOffset, lengthFieldLength, 0, 4);
18 | }
19 |
20 | public Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
21 | ChannelBuffer objBuffer = (ChannelBuffer) super.decode(ctx, channel, buffer);
22 | if (objBuffer != null) {
23 | XLoggerData data = new XLoggerData(objBuffer);
24 | return data;
25 | }
26 | return null;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/github/xlogger/server/store/Storage.java:
--------------------------------------------------------------------------------
1 | package com.github.xlogger.server.store;
2 |
3 | import com.github.xlogger.common.XLoggerData;
4 |
5 | public interface Storage {
6 | public void save(XLoggerData data) throws Exception;
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/github/xlogger/server/store/StorageFactory.java:
--------------------------------------------------------------------------------
1 | package com.github.xlogger.server.store;
2 |
3 | import java.sql.SQLException;
4 | import java.util.concurrent.atomic.AtomicInteger;
5 |
6 | import com.github.xlogger.common.XLoggerData;
7 | import com.github.xlogger.server.store.imp.JDBCStorage;
8 |
9 | public class StorageFactory {
10 |
11 | private static Storage[] storage = null;
12 |
13 | private static AtomicInteger workerId = new AtomicInteger();
14 |
15 | private static final int MAX_CPU = 15;
16 |
17 | synchronized public static boolean setupJDBC(String jdbcDriver, String url, String user, String passwd) {
18 | boolean initOk = false;
19 | if (storage == null) {
20 | storage = new JDBCStorage[MAX_CPU + 1];
21 | for (int i = 0; i <= MAX_CPU; i++) {
22 | try {
23 | storage[i] = new JDBCStorage(jdbcDriver, url, user, passwd);
24 | initOk = true;
25 | } catch (SQLException e) {
26 | e.printStackTrace();
27 | } catch (ClassNotFoundException e) {
28 | e.printStackTrace();
29 | }
30 | }
31 | }
32 | return initOk;
33 | }
34 |
35 | public static void saveLog(final XLoggerData data) throws Exception {
36 | storage[workerId.incrementAndGet() & MAX_CPU].save(data);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/github/xlogger/server/store/imp/JDBCStorage.java:
--------------------------------------------------------------------------------
1 | package com.github.xlogger.server.store.imp;
2 |
3 | import java.sql.Connection;
4 | import java.sql.Date;
5 | import java.sql.DriverManager;
6 | import java.sql.PreparedStatement;
7 | import java.sql.SQLException;
8 | import java.sql.Timestamp;
9 | import java.util.LinkedList;
10 | import java.util.List;
11 | import java.util.concurrent.Executors;
12 | import java.util.concurrent.ScheduledExecutorService;
13 | import java.util.concurrent.ThreadFactory;
14 | import java.util.concurrent.TimeUnit;
15 |
16 |
17 | import com.github.xlogger.common.XLoggerData;
18 | import com.github.xlogger.server.store.Storage;
19 |
20 | public class JDBCStorage implements Storage, Runnable {
21 |
22 | private Connection conn;
23 |
24 | private static ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
25 | @Override
26 | public Thread newThread(Runnable r) {
27 | Thread thread = new Thread(r);
28 | thread.setDaemon(true);
29 | return thread;
30 | }
31 | });
32 |
33 | private Object writeLock = new Object();
34 |
35 | private static final List myIdleList = new LinkedList();
36 |
37 | public JDBCStorage(String jdbcDriver, String url, String user, String password) throws SQLException, ClassNotFoundException {
38 | Class.forName(jdbcDriver);
39 | conn = DriverManager.getConnection(url, user, password);
40 | myIdleList.add(this);
41 | service.schedule(this, 3, TimeUnit.MINUTES);
42 | }
43 |
44 | private long lastWroteTime;
45 |
46 | @Override
47 | public void save(XLoggerData data) throws Exception {
48 | String sql = data.toSQL();
49 | PreparedStatement ps = conn.prepareStatement(sql);
50 | try {
51 | Object[] args = data.getArgs();
52 | int i = 1;
53 | for (Object obj: args) {
54 | if (obj.getClass() == Byte.class) {
55 | ps.setByte(i, (Byte) obj);
56 | } else if (obj.getClass() == Integer.class) {
57 | ps.setInt(i, (Integer) obj);
58 | } else if (obj.getClass() == Boolean.class) {
59 | ps.setBoolean(i, (Boolean) obj);
60 | } else if (obj.getClass() == String.class) {
61 | ps.setString(i, (String) obj);
62 | } else if (obj.getClass() == Long.class) {
63 | ps.setLong(i, (Long) obj);
64 | } else if (obj.getClass() == Double.class) {
65 | ps.setDouble(i, (Double) obj);
66 | } else if (obj.getClass() == Float.class) {
67 | ps.setFloat(i, (Float) obj);
68 | } else if (obj.getClass() == Timestamp.class) {
69 | ps.setTimestamp(i, (Timestamp) obj);
70 | } else if (obj.getClass() == Date.class) {
71 | ps.setDate(i, (Date) obj);
72 | }
73 | i++;
74 | }
75 |
76 | synchronized (writeLock) {
77 | if (ps.executeUpdate() == 0) {
78 | throw new Exception("no record inserted (`" + data.getTabName() + "`");
79 | }
80 | }
81 | } finally {
82 | ps.close();
83 | }
84 | lastWroteTime = System.currentTimeMillis();
85 | }
86 |
87 | private void sendPing() throws SQLException {
88 | PreparedStatement ps = conn.prepareStatement("SELECT CURRENT_TIME()");
89 | try {
90 | synchronized (writeLock) {
91 | ps.execute();
92 | }
93 | lastWroteTime = System.currentTimeMillis();
94 | } finally {
95 | ps.close();
96 | }
97 | }
98 |
99 | @Override
100 | public void run() {
101 | for (JDBCStorage storage: myIdleList) {
102 | if (System.currentTimeMillis() - storage.lastWroteTime >= 60000) {
103 | try {
104 | storage.sendPing();
105 | } catch (SQLException e) {
106 | }
107 | }
108 | }
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/src/test/java/com/github/xlogger/XLoggerServerTest.java:
--------------------------------------------------------------------------------
1 | package com.github.xlogger;
2 |
3 | import org.junit.Test;
4 |
5 | import com.github.xlogger.server.XLoggerServer;
6 | import com.github.xlogger.server.store.StorageFactory;
7 |
8 | public class XLoggerServerTest {
9 |
10 | @Test
11 | public void test() {
12 | StorageFactory.setupJDBC("com.mysql.jdbc.Driver", "jdbc:mysql://192.168.10.73/test?", "root", "123456");
13 | XLoggerServer.start("localhost", (short) 4000);
14 |
15 | while (true) {
16 | try {
17 | Thread.sleep(1000000);
18 | } catch (InterruptedException e) {
19 | e.printStackTrace();
20 | }
21 | }
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/test/java/com/github/xlogger/XLoggerTest.java:
--------------------------------------------------------------------------------
1 | package com.github.xlogger;
2 |
3 | import org.junit.Test;
4 |
5 | public class XLoggerTest {
6 |
7 | @Test
8 | public void test() {
9 | XLogger.initXLogger("localhost", (short) 4000, 30000);
10 |
11 | for (int j = 0; j < 10000; j++) {
12 | for (int i = 0; i < 10000; i++)
13 | XLogger.log("Test", "1111", i);
14 | try {
15 | Thread.sleep(5000);
16 | } catch (InterruptedException e) {
17 | e.printStackTrace();
18 | }
19 | }
20 | try {
21 | Thread.sleep(50000000);
22 | } catch (InterruptedException e) {
23 | e.printStackTrace();
24 | }
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------