diff src/luan/modules/lucene/LuceneIndex.java @ 1387:bc40bc9aab3a

start postgres backup
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 02 Sep 2019 22:23:12 -0600
parents 87a3738d7cc5
children 2024d23ddd64
line wrap: on
line diff
--- a/src/luan/modules/lucene/LuceneIndex.java	Thu Aug 22 12:32:20 2019 -0600
+++ b/src/luan/modules/lucene/LuceneIndex.java	Mon Sep 02 22:23:12 2019 -0600
@@ -45,6 +45,7 @@
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.NumericUtils;
 import org.apache.lucene.search.Query;
+import org.apache.lucene.search.PrefixQuery;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.search.Sort;
@@ -110,14 +111,14 @@
 
 	private static Map<String,LuceneIndex> indexes = new HashMap<String,LuceneIndex>();
 
-	public static Object[] getLuceneIndex(Luan luan,File indexDir,FieldParser defaultFieldParser,String[] defaultFields)
+	public static Object[] getLuceneIndex(Luan luan,File indexDir,FieldParser defaultFieldParser,String[] defaultFields,LuanFunction completer)
 		throws LuanException, IOException
 	{
 		String key = indexDir.getCanonicalPath();
 		synchronized(indexes) {
 			LuceneIndex li = indexes.get(key);
 			if( li == null ) {
-				li = new LuceneIndex(indexDir,defaultFieldParser,defaultFields,key);
+				li = new LuceneIndex(indexDir,defaultFieldParser,defaultFields,key,completer);
 				li.openCount = 1;
 				indexes.put(key,li);
 			} else {
@@ -157,7 +158,9 @@
 	private final FieldParser defaultFieldParser;
 	private final String[] defaultFields;
 
-	private LuceneIndex(File indexDir,FieldParser defaultFieldParser,String[] defaultFields,String key)
+	private final PostgresBackup postgresBackup;
+
+	private LuceneIndex(File indexDir,FieldParser defaultFieldParser,String[] defaultFields,String key,LuanFunction completer)
 		throws LuanException, IOException
 	{
 		this.key = key;
@@ -174,6 +177,9 @@
 		}
 		this.analyzer = analyzer;
 		reopen();
+		postgresBackup = completer!=null ? PostgresBackup.newInstance() : null;
+		if( postgresBackup != null && postgresBackup.wasCreated )
+			rebuild_postgres_backup(completer);
 	}
 
 	public void reopen() throws LuanException, IOException {
@@ -199,6 +205,8 @@
 		try {
 			writer.deleteAll();
 			id = idLim = 0;
+			if( postgresBackup != null )
+				postgresBackup.deleteAll();
 			if(commit) writer.commit();
 		} finally {
 			wrote();
@@ -212,6 +220,28 @@
 		return new Term(key,br);
 	}
 
+	private void backupDelete(Query query)
+		throws IOException
+	{
+		if( postgresBackup != null ) {
+			final List<Long> ids = new ArrayList<Long>();
+			IndexSearcher searcher = openSearcher();
+			MyCollector col = new MyCollector() {
+				@Override public void collect(int iDoc) throws IOException {
+					Document doc = searcher.doc( docBase + iDoc );
+					Long id = (Long)doc.getField("id").numericValue();
+					ids.add(id);
+				}
+			};
+			searcher.search(query,col);
+			postgresBackup.begin();
+			for( Long id : ids ) {
+				postgresBackup.delete(id);
+			}
+			postgresBackup.commit();
+		}
+	}
+
 	public void delete(String queryStr)
 		throws IOException, ParseException
 	{
@@ -220,6 +250,7 @@
 		boolean commit = !writeLock.isHeldByCurrentThread();
 		writeLock.lock();
 		try {
+			backupDelete(query);
 			writer.deleteDocuments(query);
 			if(commit) writer.commit();
 		} finally {
@@ -235,6 +266,9 @@
 	public void save(LuanTable doc,LuanTable boosts)
 		throws LuanException, IOException
 	{
+		if( boosts!=null && postgresBackup!=null )
+			logger.error("boosts are not saved to postgres backup");
+
 		Object obj = doc.get("id");
 		Long id;
 		try {
@@ -250,8 +284,12 @@
 				id = nextId();
 				doc.put("id",id);
 				writer.addDocument(toLucene(doc,boosts));
+				if( postgresBackup != null )
+					postgresBackup.add(id,doc);
 			} else {
 				writer.updateDocument( term("id",id), toLucene(doc,boosts) );
+				if( postgresBackup != null )
+					postgresBackup.update(id,doc);
 			}
 			if(commit) writer.commit();
 		} finally {
@@ -263,16 +301,31 @@
 	public Object run_in_transaction(LuanFunction fn) throws IOException, LuanException {
 		boolean commit = !writeLock.isHeldByCurrentThread();
 		writeLock.lock();
+		boolean ok = false;
 		try {
+			if( commit && postgresBackup != null )
+				postgresBackup.begin();
 			Object rtn = fn.call();
-			if(commit) writer.commit();
+			ok = true;
+			if(commit) {
+				if( postgresBackup != null )
+					postgresBackup.commit();
+				writer.commit();
+			}
 			return rtn;
 		} finally {
+			if( !ok && commit ) {
+				if( postgresBackup != null )
+					postgresBackup.rollback();
+				writer.rollback();
+				reopen();
+			}
 			wrote();
 			writeLock.unlock();
 		}
 	}
 
+	// ???
 	public Object run_in_lock(LuanFunction fn) throws IOException, LuanException {
 		if( writeLock.isHeldByCurrentThread() )
 			throw new RuntimeException();
@@ -373,6 +426,8 @@
 	}
 
 	public void doClose() throws IOException {
+		if( postgresBackup != null )
+			postgresBackup.close();
 		writer.close();
 		reader.close();
 	}
@@ -725,4 +780,48 @@
 		return n;
 	}
 
+
+
+	public boolean hasPostgresBackup() {
+		return postgresBackup != null;
+	}
+
+	public void rebuild_postgres_backup(LuanFunction completer)
+		throws IOException, LuanException
+	{
+		writeLock.lock();
+		boolean ok = false;
+		try {
+			postgresBackup.begin();
+			postgresBackup.deleteAll();
+			Query query = new PrefixQuery(new Term("id"));
+			IndexSearcher searcher = openSearcher();
+			MyCollector col = new MyCollector() {
+				@Override public void collect(int iDoc) throws IOException {
+					try {
+						Document doc = searcher.doc( docBase + iDoc );
+						LuanTable tbl = toTable(completer.luan(),doc);
+						tbl = (LuanTable)completer.call(tbl);
+						Long id = (Long)tbl.get("id");
+						//logger.info("id = "+id);
+						postgresBackup.add(id,tbl);
+					} catch(LuanException e) {
+						throw new LuanRuntimeException(e);
+					}
+				}
+			};
+			try {
+				searcher.search(query,col);
+			} catch(LuanRuntimeException e) {
+				throw (LuanException)e.getCause();
+			}
+			ok = true;
+			postgresBackup.commit();
+		} finally {
+			if( !ok )
+				postgresBackup.rollback();
+			writeLock.unlock();
+		}
+	}
+
 }