# HG changeset patch # User cli # Date 1315671485 -7200 # Node ID 7e24949b87b0f8159b8efd2a509fed8ccc0ae1e4 # Parent 5d7d1adf387f39bbd3f489e80383614936630d4f HSQLDB backend support completed, but untested. diff -r 5d7d1adf387f -r 7e24949b87b0 README --- a/README Tue Jun 07 11:55:22 2011 +0200 +++ b/README Sat Sep 10 18:18:05 2011 +0200 @@ -1,6 +1,9 @@ sonews README ============= +sonews is an Usenet News Server written in Java. It uses a relation database as +backend, currently supported is MySQL, PostgreSQL and HSQLDB. + Prerequisites: -------------- @@ -23,5 +26,5 @@ Bugs and other Issues: ---------------------- -Please mail them to christian.lins@fh-osnabrueck.de or better issue them -into the bugtracker at http://bugs.xerxys.info/ . \ No newline at end of file +Please mail them to mail(at)sonews.org or better issue them +into the bugtracker at https://bitbucket.org/cli/sonews/ . diff -r 5d7d1adf387f -r 7e24949b87b0 helpers/database_hsqldb_tmpl.sql --- a/helpers/database_hsqldb_tmpl.sql Tue Jun 07 11:55:22 2011 +0200 +++ b/helpers/database_hsqldb_tmpl.sql Sat Sep 10 18:18:05 2011 +0200 @@ -140,3 +140,4 @@ ); COMMIT; +SHUTDOWN; diff -r 5d7d1adf387f -r 7e24949b87b0 helpers/sonews.conf.sample --- a/helpers/sonews.conf.sample Tue Jun 07 11:55:22 2011 +0200 +++ b/helpers/sonews.conf.sample Sat Sep 10 18:18:05 2011 +0200 @@ -2,3 +2,4 @@ sonews.storage.user=SA sonews.storage.dbmsdriver=org.hsqldb.jdbcDriver sonews.storage.password= +sonews.storage.provider=org.sonews.storage.impl.HSQLDBProvider diff -r 5d7d1adf387f -r 7e24949b87b0 src/org/sonews/Main.java --- a/src/org/sonews/Main.java Tue Jun 07 11:55:22 2011 +0200 +++ b/src/org/sonews/Main.java Sat Sep 10 18:18:05 2011 +0200 @@ -102,8 +102,9 @@ // Do NOT USE BackendConfig or Log classes before this point because they require // a working JDBCDatabase connection. try { - StorageProvider sprov = - StorageManager.loadProvider("org.sonews.storage.impl.JDBCDatabaseProvider"); + String provName = Config.inst().get(Config.LEVEL_FILE, + Config.STORAGE_PROVIDER, "org.sonews.storage.impl.JDBCDatabaseProvider"); + StorageProvider sprov = StorageManager.loadProvider(provName); StorageManager.enableProvider(sprov); // Make sure some elementary groups are existing diff -r 5d7d1adf387f -r 7e24949b87b0 src/org/sonews/config/Config.java --- a/src/org/sonews/config/Config.java Tue Jun 07 11:55:22 2011 +0200 +++ b/src/org/sonews/config/Config.java Sat Sep 10 18:18:05 2011 +0200 @@ -52,8 +52,7 @@ public static final String MLSEND_PORT = "sonews.mlsend.port"; public static final String MLSEND_USER = "sonews.mlsend.user"; /** Key constant. If value is "true" every I/O is written to logfile - * (which is a lot!) - */ + * (which is a lot!) */ public static final String DEBUG = "sonews.debug"; /** Key constant. Value is classname of the JDBC driver */ public static final String STORAGE_DBMSDRIVER = "sonews.storage.dbmsdriver"; @@ -63,6 +62,7 @@ public static final String STORAGE_USER = "sonews.storage.user"; /** Key constant. Value is the password for the DBMS. */ public static final String STORAGE_PASSWORD = "sonews.storage.password"; + public static final String STORAGE_PROVIDER = "sonews.storage.provider"; /** Key constant. Value is the name of the host which is allowed to use the * XDAEMON command; default: "localhost" */ public static final String XDAEMON_HOST = "sonews.xdaemon.host"; diff -r 5d7d1adf387f -r 7e24949b87b0 src/org/sonews/storage/StorageManager.java --- a/src/org/sonews/storage/StorageManager.java Tue Jun 07 11:55:22 2011 +0200 +++ b/src/org/sonews/storage/StorageManager.java Sat Sep 10 18:18:05 2011 +0200 @@ -26,8 +26,7 @@ private static StorageProvider provider; - public static Storage current() - throws StorageBackendException { + public static Storage current() throws StorageBackendException { synchronized (StorageManager.class) { if (provider == null) { return null; @@ -41,7 +40,7 @@ try { Class clazz = Class.forName(pluginClassName); Object inst = clazz.newInstance(); - return (StorageProvider) inst; + return (StorageProvider)inst; } catch (Exception ex) { System.err.println(ex); return null; diff -r 5d7d1adf387f -r 7e24949b87b0 src/org/sonews/storage/impl/HSQLDB.java --- a/src/org/sonews/storage/impl/HSQLDB.java Tue Jun 07 11:55:22 2011 +0200 +++ b/src/org/sonews/storage/impl/HSQLDB.java Sat Sep 10 18:18:05 2011 +0200 @@ -17,7 +17,10 @@ */ package org.sonews.storage.impl; +import java.sql.SQLException; +import org.sonews.storage.Channel; import org.sonews.storage.Storage; +import org.sonews.storage.StorageBackendException; /** * A specialized JDBCDatabase supporting HSQLDB. @@ -26,5 +29,31 @@ */ public class HSQLDB extends JDBCDatabase implements Storage { + @Override + protected void prepareAddGroupStatement() throws SQLException { + this.pstmtAddGroup0 = conn.prepareStatement( + "INSERT INTO groups (name, flags, group_id) VALUES (?, ?, IDENTITY())"); + } + @Override + protected void prepareCountGroupsStatement() throws SQLException { + this.pstmtCountGroups = conn.prepareStatement( + "SELECT Count(group_id) FROM groups WHERE " + + "BITAND(flags, " + Channel.DELETED + ") = 0"); + } + + @Override + protected void prepareGetPostingsCountStatement() throws SQLException { + this.pstmtGetPostingsCount = conn.prepareStatement( + "SELECT Count(*) FROM postings JOIN groups " + + "ON groups.name = ? GROUP BY groups.name"); + } + + @Override + protected void prepareGetSubscriptionsStatement() throws SQLException { + this.pstmtGetSubscriptions = conn.prepareStatement( + "SELECT * FROM (SELECT feedtype, host, port, peer_id FROM peers JOIN " + + "peer_subscriptions ON peers.peer_id = peer_subscriptions.peer_id) " + + "JOIN groups ON group_id = groups.group_id WHERE feedtype = ?"); + } } diff -r 5d7d1adf387f -r 7e24949b87b0 src/org/sonews/storage/impl/HSQLDBProvider.java --- a/src/org/sonews/storage/impl/HSQLDBProvider.java Tue Jun 07 11:55:22 2011 +0200 +++ b/src/org/sonews/storage/impl/HSQLDBProvider.java Sat Sep 10 18:18:05 2011 +0200 @@ -17,6 +17,9 @@ */ package org.sonews.storage.impl; +import java.sql.SQLException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.sonews.storage.Storage; import org.sonews.storage.StorageBackendException; import org.sonews.storage.StorageProvider; @@ -27,13 +30,28 @@ * @since sonews/1.1 */ public class HSQLDBProvider implements StorageProvider { + protected static final Map instances = + new ConcurrentHashMap(); + @Override public boolean isSupported(String uri) { return uri.startsWith("jdbc:hsqldb"); } + @Override public Storage storage(Thread thread) throws StorageBackendException { - throw new UnsupportedOperationException("Not supported yet."); + try { + if (!instances.containsKey(Thread.currentThread())) { + HSQLDB db = new HSQLDB(); + db.arise(); + instances.put(Thread.currentThread(), db); + return db; + } else { + return instances.get(Thread.currentThread()); + } + } catch (SQLException ex) { + throw new StorageBackendException(ex); + } } } diff -r 5d7d1adf387f -r 7e24949b87b0 src/org/sonews/storage/impl/JDBCDatabase.java --- a/src/org/sonews/storage/impl/JDBCDatabase.java Tue Jun 07 11:55:22 2011 +0200 +++ b/src/org/sonews/storage/impl/JDBCDatabase.java Sat Sep 10 18:18:05 2011 +0200 @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.List; +import java.util.logging.Level; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -97,6 +98,29 @@ /** How many times the database connection was reinitialized */ protected int restarts = 0; + protected void prepareAddGroupStatement() throws SQLException { + this.pstmtAddGroup0 = conn.prepareStatement( + "INSERT INTO groups (name, flags) VALUES (?, ?)"); + } + + protected void prepareCountGroupsStatement() throws SQLException { + this.pstmtCountGroups = conn.prepareStatement( + "SELECT Count(group_id) FROM groups WHERE " + + "flags & " + Channel.DELETED + " = 0"); + } + + protected void prepareGetPostingsCountStatement() throws SQLException { + this.pstmtGetPostingsCount = conn.prepareStatement( + "SELECT Count(*) FROM postings NATURAL JOIN groups " + + "WHERE groups.name = ?"); + } + + protected void prepareGetSubscriptionsStatement() throws SQLException { + this.pstmtGetSubscriptions = conn.prepareStatement( + "SELECT host, port, name FROM peers NATURAL JOIN " + + "peer_subscriptions NATURAL JOIN groups WHERE feedtype = ?"); + } + /** * Rises the database: reconnect and recreate all prepared statements. * @throws java.lang.SQLException @@ -137,17 +161,14 @@ "INSERT INTO events VALUES (?, ?, ?)"); // Prepare statement for method addGroup() - this.pstmtAddGroup0 = conn.prepareStatement( - "INSERT INTO groups (name, flags) VALUES (?, ?)"); + prepareAddGroupStatement(); // Prepare statement for method countArticles() this.pstmtCountArticles = conn.prepareStatement( "SELECT Count(article_id) FROM article_ids"); // Prepare statement for method countGroups() - this.pstmtCountGroups = conn.prepareStatement( - "SELECT Count(group_id) FROM groups WHERE " - + "flags & " + Channel.DELETED + " = 0"); + prepareCountGroupsStatement(); // Prepare statements for method delete(article) this.pstmtDeleteArticle0 = conn.prepareStatement( @@ -254,14 +275,10 @@ "SELECT Min(article_index) FROM postings WHERE group_id = ?"); // Prepare statement for method getPostingsCount() - this.pstmtGetPostingsCount = conn.prepareStatement( - "SELECT Count(*) FROM postings NATURAL JOIN groups " - + "WHERE groups.name = ?"); + prepareGetPostingsCountStatement(); // Prepare statement for method getSubscriptions() - this.pstmtGetSubscriptions = conn.prepareStatement( - "SELECT host, port, name FROM peers NATURAL JOIN " - + "peer_subscriptions NATURAL JOIN groups WHERE feedtype = ?"); + prepareGetSubscriptionsStatement(); // Prepare statement for method isArticleExisting() this.pstmtIsArticleExisting = conn.prepareStatement( @@ -1364,12 +1381,12 @@ } } - private void restartConnection(SQLException cause) + protected void restartConnection(SQLException cause) throws StorageBackendException { restarts++; - Log.get().severe(Thread.currentThread() - + ": Database connection was closed (restart " + restarts + ")."); + Log.get().log(Level.SEVERE, Thread.currentThread() + + ": Database connection was closed (restart " + restarts + ").", cause); if (restarts >= MAX_RESTARTS) { // Delete the current, probably broken JDBCDatabase instance. diff -r 5d7d1adf387f -r 7e24949b87b0 src/org/sonews/storage/impl/JDBCDatabaseProvider.java --- a/src/org/sonews/storage/impl/JDBCDatabaseProvider.java Tue Jun 07 11:55:22 2011 +0200 +++ b/src/org/sonews/storage/impl/JDBCDatabaseProvider.java Sat Sep 10 18:18:05 2011 +0200 @@ -31,7 +31,8 @@ */ public class JDBCDatabaseProvider implements StorageProvider { - protected static final Map instances = new ConcurrentHashMap(); + protected static final Map instances = + new ConcurrentHashMap(); @Override public boolean isSupported(String uri) {