view src/luan/modules/lucene/PostgresBackup.java @ 1391:94f48cc76de8

add lucene check
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 05 Sep 2019 01:29:57 -0600
parents 2024d23ddd64
children 002152af497a
line wrap: on
line source

package luan.modules.lucene;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.util.Properties;
import java.util.List;
import java.util.ArrayList;
import luan.Luan;
import luan.LuanTable;
import luan.LuanFunction;
import luan.LuanException;
import luan.modules.parsers.LuanToString;
import luan.lib.logging.Logger;
import luan.lib.logging.LoggerFactory;


final class PostgresBackup {
	private static final Logger logger = LoggerFactory.getLogger(PostgresBackup.class);

	static PostgresBackup newInstance() {
		try {
			return new PostgresBackup();
		} catch(ClassNotFoundException e) {
			logger.error("creation failed",e);
			return null;
		} catch(SQLException e) {
			logger.error("creation failed",e);
			return null;
		}
	}

	final boolean wasCreated;
	private final String url;
	private final Properties props = new Properties();
	private final Connection con;
	private final PreparedStatement insertStmt;
	private final PreparedStatement updateStmt;
	private final PreparedStatement deleteStmt;
	private int trans = 0;
	private final LuanToString luanToString = new LuanToString();

	private PostgresBackup()
		throws ClassNotFoundException, SQLException
	{
		Class.forName("org.postgresql.Driver");

		url = "jdbc:postgresql://localhost:5432/luan";
		props.setProperty("user","postgres");
		props.setProperty("password","");

		con = newConnection();

		Statement stmt = con.createStatement();
		boolean hasTable = stmt.executeQuery(
			"select * from information_schema.tables where table_name='lucene'"
		).next();
		if( !hasTable ) {
			stmt.executeUpdate(
				"create table lucene ("
				+"	id integer not null primary key,"
				+"	data text not null"
				+")"
			);
		}
		stmt.close();
		wasCreated = !hasTable;

		insertStmt = con.prepareStatement(
			"insert into lucene (id,data) values (?,?)"
		);
		updateStmt = con.prepareStatement(
			"update lucene set data=? where id=?"
		);
		deleteStmt = con.prepareStatement(
			"delete from lucene where id=?"
		);

		luanToString.strict = true;
		luanToString.numberTypes = true;
	}

	Connection newConnection() throws SQLException {
		return DriverManager.getConnection(url,props);
	}

	void close() {
		try {
			insertStmt.close();
			updateStmt.close();
			deleteStmt.close();
			con.close();
		} catch(SQLException e) {
			logger.error("close failed",e);
		}
	}

	protected void finalize() throws Throwable {
		super.finalize();
		if( !con.isClosed() ) {
			logger.error("con not closed");
			con.close();
		}
	}

	void add(LuanTable doc) throws LuanException {
		try {
			Long id = (Long)doc.get("id");
			String data = luanToString.toString(doc);
			insertStmt.setLong(1,id);
			insertStmt.setString(2,data);
			insertStmt.executeUpdate();
		} catch(SQLException e) {
			logger.error("add failed",e);
		}
	}

	void update(LuanTable doc) throws LuanException {
		try {
			Long id = (Long)doc.get("id");
			String data = luanToString.toString(doc);
			updateStmt.setString(1,data);
			updateStmt.setLong(2,id);
			int n = updateStmt.executeUpdate();
			if( n==0 ) {
				logger.error("update not found for id="+id+", trying add");
				add(doc);
			} else if( n!=1 )
				throw new RuntimeException();
		} catch(SQLException e) {
			logger.error("update failed",e);
		}
	}

	void deleteAll() {
		try {
			Statement stmt = con.createStatement();
			stmt.executeUpdate("delete from lucene");
			stmt.close();
		} catch(SQLException e) {
			logger.error("update failed",e);
		}
	}

	void delete(long id) {
		try {
			deleteStmt.setLong(1,id);
			int n = deleteStmt.executeUpdate();
			if( n==0 ) {
				logger.error("delete not found for id="+id);
			}
		} catch(SQLException e) {
			logger.error("update failed",e);
		}
	}

	void begin() {
		try {
			if( trans++ == 0 )
				con.setAutoCommit(false);
		} catch(SQLException e) {
			logger.error("begin failed",e);
		}
	}

	void commit() {
		try {
			if( trans <= 0 ) {
				logger.error("commit not in transaction");
				return;
			}
			if( --trans == 0 )
				con.setAutoCommit(true);
		} catch(SQLException e) {
			logger.error("begin failed",e);
		}
	}

	void rollback() {
		try {
			if( --trans != 0 ) {
				logger.error("rollback failed trans="+trans);
				return;
			}
			con.rollback();
			con.setAutoCommit(true);
		} catch(SQLException e) {
			logger.error("begin failed",e);
		}
	}

	private static LuanTable newEnv() {
		LuanTable env = new LuanTable(new Luan());
		LuanToString.addNumberTypes(env);
		return env;
	}

	private static Object eval(String s,LuanTable env) throws LuanException {
		LuanFunction fn = env.luan().load( "return "+s, "PostgresBackup", env );
		return fn.call();
	}

	void restoreLucene(LuceneIndex li)
		throws LuanException, IOException
	{
		try {
			LuanTable env = newEnv();
			Statement stmt = con.createStatement();
			ResultSet rs = stmt.executeQuery("select data from lucene");
			while( rs.next() ) {
				String data = rs.getString("data");
				LuanTable doc = (LuanTable)eval(data,env);
				li.restore(doc);
			}
			stmt.close();
		} catch(SQLException e) {
			logger.error("restoreLucene failed",e);
			throw new RuntimeException(e);
		}
	}

	long maxId()
		throws LuanException, IOException
	{
		try {
			Statement stmt = con.createStatement();
			ResultSet rs = stmt.executeQuery("select max(id) as m from lucene");
			rs.next();
			long m = rs.getLong("m");
			stmt.close();
			return m;
		} catch(SQLException e) {
			logger.error("maxId failed",e);
			throw new RuntimeException(e);
		}
	}

	final class Checker {
		private final Connection con;
		private final PreparedStatement pstmt;
		private final LuanTable env = newEnv();

		Checker() throws SQLException {
			con = newConnection();
			con.setAutoCommit(false);
			pstmt = con.prepareStatement(
				"select data from lucene where id=?"
			);
		}

		void close() throws SQLException {
			pstmt.close();
			con.close();
		}

		List<Long> getIds() throws SQLException {
			List<Long> ids = new ArrayList<Long>();
			Statement stmt = con.createStatement();
			ResultSet rs = stmt.executeQuery("select id from lucene order by id");
			while( rs.next() ) {
				long id = rs.getLong("id");
				ids.add(id);
			}
			stmt.close();
			return ids;
		}

		LuanTable getDoc(long id) throws SQLException, LuanException {
			pstmt.setLong(1,id);
			ResultSet rs = pstmt.executeQuery();
			rs.next();
			String data = rs.getString("data");
			LuanTable doc = (LuanTable)eval(data,env);
			return doc;
		}
	}

	Checker newChecker() throws SQLException {
		return new Checker();
	}

}