├── .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 | --------------------------------------------------------------------------------