blob: 0c5a6044489c7880b355978e2162c0a66b8f44ef [file] [log] [blame]
Nils Diewald50e90e92015-02-26 21:25:25 +00001package de.ids_mannheim.korap.response.collector;
Nils Diewaldbb33da22015-03-04 16:24:25 +00002
Nils Diewald40996d82015-02-26 22:23:52 +00003import de.ids_mannheim.korap.server.Node;
Nils Diewald392bcf32015-02-26 20:01:17 +00004import de.ids_mannheim.korap.response.Match;
Nils Diewald50e90e92015-02-26 21:25:25 +00005import de.ids_mannheim.korap.response.MatchCollector;
Nils Diewaldad3f3032014-09-24 01:42:47 +00006import com.fasterxml.jackson.annotation.*;
7import java.sql.Connection;
8import java.sql.PreparedStatement;
9import javax.sql.DataSource;
10import java.sql.SQLException;
Nils Diewald6aa929e2014-09-17 13:30:34 +000011import java.util.*;
12
Nils Diewaldf04e1002014-09-24 22:52:59 +000013import org.slf4j.Logger;
14import org.slf4j.LoggerFactory;
15
Akron98b78542015-08-06 21:43:08 +020016public final class MatchCollectorDB extends MatchCollector {
Nils Diewald6aa929e2014-09-17 13:30:34 +000017
Nils Diewaldf04e1002014-09-24 22:52:59 +000018 // Logger
Nils Diewald40996d82015-02-26 22:23:52 +000019 private final static Logger log = LoggerFactory.getLogger(Node.class);
Nils Diewaldf04e1002014-09-24 22:52:59 +000020
Nils Diewald6aa929e2014-09-17 13:30:34 +000021 /*
Nils Diewald8d8641b2014-09-28 17:37:53 +000022 * Todo: In case there are multiple threads searching,
23 * the list should be synchrinized Collections.synchronizedList()
Nils Diewald6aa929e2014-09-17 13:30:34 +000024 */
Nils Diewaldad3f3032014-09-24 01:42:47 +000025 private String databaseType;
Akron98b78542015-08-06 21:43:08 +020026 private final List matchCollector;
27 private final int bufferSize;
28 private int docCollect;
29 private final String resultID;
Nils Diewald6aa929e2014-09-17 13:30:34 +000030
Nils Diewald8d8641b2014-09-28 17:37:53 +000031 // private Connection connection;
Nils Diewaldf04e1002014-09-24 22:52:59 +000032 private DataSource pool;
Nils Diewaldad3f3032014-09-24 01:42:47 +000033 private Connection connection;
34 private PreparedStatement prepared;
Nils Diewald6aa929e2014-09-17 13:30:34 +000035
Nils Diewaldbb33da22015-03-04 16:24:25 +000036
Nils Diewald6aa929e2014-09-17 13:30:34 +000037 /*
38 * Create a new collector for database connections
39 */
Nils Diewaldad3f3032014-09-24 01:42:47 +000040 public MatchCollectorDB (int bufferSize, String resultID) {
Nils Diewald392bcf32015-02-26 20:01:17 +000041 this.bufferSize = bufferSize;
42 this.resultID = resultID;
43 this.matchCollector = new ArrayList<int[]>(bufferSize + 2);
Nils Diewald6aa929e2014-09-17 13:30:34 +000044 };
45
Nils Diewaldbb33da22015-03-04 16:24:25 +000046
Nils Diewald6aa929e2014-09-17 13:30:34 +000047 /*
48 * Add matches till the bufferSize exceeds - then commit to the database.
49 */
Nils Diewaldad3f3032014-09-24 01:42:47 +000050 public void add (int UID, int matchCount) {
Nils Diewald392bcf32015-02-26 20:01:17 +000051 if (this.docCollect == bufferSize)
52 this.commit();
Nils Diewaldf04e1002014-09-24 22:52:59 +000053
Nils Diewald392bcf32015-02-26 20:01:17 +000054 this.incrTotalResultDocs(1);
55 this.incrTotalResults(matchCount);
Nils Diewaldbb33da22015-03-04 16:24:25 +000056 this.matchCollector.add(new int[] { UID, matchCount });
Nils Diewald392bcf32015-02-26 20:01:17 +000057 this.docCollect++;
Nils Diewald6aa929e2014-09-17 13:30:34 +000058 };
59
Nils Diewaldbb33da22015-03-04 16:24:25 +000060
Nils Diewaldad3f3032014-09-24 01:42:47 +000061 @JsonIgnore
62 public void setDatabaseType (String type) {
Nils Diewald392bcf32015-02-26 20:01:17 +000063 this.databaseType = type;
Nils Diewaldad3f3032014-09-24 01:42:47 +000064 };
65
Nils Diewaldbb33da22015-03-04 16:24:25 +000066
Nils Diewaldad3f3032014-09-24 01:42:47 +000067 @JsonIgnore
68 public String getDatabaseType () {
Nils Diewald392bcf32015-02-26 20:01:17 +000069 return this.databaseType;
Nils Diewaldad3f3032014-09-24 01:42:47 +000070 };
71
Nils Diewaldbb33da22015-03-04 16:24:25 +000072
Nils Diewaldad3f3032014-09-24 01:42:47 +000073 @JsonIgnore
Nils Diewaldbb33da22015-03-04 16:24:25 +000074 public void setDBPool (String type, DataSource ds, Connection conn)
75 throws SQLException {
Nils Diewald392bcf32015-02-26 20:01:17 +000076 this.setDatabaseType(type);
77 this.connection = conn;
78 this.pool = ds;
Nils Diewald8d8641b2014-09-28 17:37:53 +000079 };
80
81
82 @JsonIgnore
Nils Diewaldf04e1002014-09-24 22:52:59 +000083 public void setDBPool (String type, DataSource ds) throws SQLException {
Nils Diewald392bcf32015-02-26 20:01:17 +000084 this.setDatabaseType(type);
85 this.pool = ds;
Nils Diewaldad3f3032014-09-24 01:42:47 +000086 };
Nils Diewaldbb33da22015-03-04 16:24:25 +000087
88
Nils Diewald8d8641b2014-09-28 17:37:53 +000089 /*
90 Create prepared statement for multiple requests
91 this.prepared = this.conn.prepareStatement(
92 "INSERT INTO people VALUES (?, ?);"
93 );
94 Only prepare if commit > buffersize!
95 Difference between mariadb and sqlite!
96 */
97
Nils Diewaldbb33da22015-03-04 16:24:25 +000098
Nils Diewaldf04e1002014-09-24 22:52:59 +000099 /* TODO: Ensure the commit was successful! */
Nils Diewaldbb33da22015-03-04 16:24:25 +0000100 public void commit () {
Nils Diewald392bcf32015-02-26 20:01:17 +0000101 if (this.pool == null)
102 return;
Nils Diewaldad3f3032014-09-24 01:42:47 +0000103
Nils Diewald392bcf32015-02-26 20:01:17 +0000104 try {
Nils Diewaldbb33da22015-03-04 16:24:25 +0000105 /*
106 * This should be heavily optimized! It's aweful!
107 * ARGHHHHHHH!
108 */
Nils Diewald392bcf32015-02-26 20:01:17 +0000109 if (this.connection.isClosed())
110 this.connection = this.pool.getConnection();
Nils Diewaldf04e1002014-09-24 22:52:59 +0000111
Nils Diewald392bcf32015-02-26 20:01:17 +0000112 StringBuilder sb = new StringBuilder();
Nils Diewaldbb33da22015-03-04 16:24:25 +0000113 sb.append("INSERT INTO ").append(this.resultID)
114 .append(" (text_id, match_count) ");
115
Nils Diewald392bcf32015-02-26 20:01:17 +0000116 // SQLite batch insertion idiom
117 if (this.getDatabaseType().equals("sqlite")) {
118 for (int i = 1; i < this.docCollect; i++) {
119 sb.append("SELECT ?, ? UNION ");
120 }
121 if (this.docCollect == 1)
122 sb.append("VALUES (?, ?)");
123 else
124 sb.append("SELECT ?, ?");
125 }
Nils Diewaldf04e1002014-09-24 22:52:59 +0000126
Nils Diewald392bcf32015-02-26 20:01:17 +0000127 // MySQL batch insertion idiom
128 else if (this.getDatabaseType().equals("mysql")) {
129 sb.append(" VALUES ");
130 for (int i = 1; i < this.docCollect; i++) {
131 sb.append("(?,?),");
132 };
133 sb.append("(?,?)");
134 }
Nils Diewaldbb33da22015-03-04 16:24:25 +0000135
Nils Diewald392bcf32015-02-26 20:01:17 +0000136 // Unknown idiom
137 else {
138 log.error("Unsupported Database type");
139 return;
140 };
Nils Diewaldf04e1002014-09-24 22:52:59 +0000141
Nils Diewald392bcf32015-02-26 20:01:17 +0000142 // Prepare statement based on the string
Nils Diewaldbb33da22015-03-04 16:24:25 +0000143 PreparedStatement prep = this.connection.prepareStatement(sb
144 .toString());
Nils Diewaldf04e1002014-09-24 22:52:59 +0000145
Nils Diewald392bcf32015-02-26 20:01:17 +0000146 int i = 1;
Nils Diewaldbb33da22015-03-04 16:24:25 +0000147 ListIterator li = this.matchCollector.listIterator();
Nils Diewald392bcf32015-02-26 20:01:17 +0000148 while (li.hasNext()) {
149 int[] v = (int[]) li.next();
150 prep.setInt(i++, v[0]);
151 prep.setInt(i++, v[1]);
152 };
Nils Diewald8d8641b2014-09-28 17:37:53 +0000153
Nils Diewald392bcf32015-02-26 20:01:17 +0000154 prep.addBatch();
155 prep.executeBatch();
156 this.connection.commit();
157 }
Nils Diewaldf04e1002014-09-24 22:52:59 +0000158
Nils Diewald392bcf32015-02-26 20:01:17 +0000159 // An SQL error occured ...
160 catch (SQLException e) {
161 log.error(e.getLocalizedMessage());
162 };
Nils Diewaldf04e1002014-09-24 22:52:59 +0000163
Nils Diewald392bcf32015-02-26 20:01:17 +0000164 this.matchCollector.clear();
165 this.docCollect = 0;
166 return;
Nils Diewaldad3f3032014-09-24 01:42:47 +0000167 };
168
Nils Diewaldbb33da22015-03-04 16:24:25 +0000169
Nils Diewald8d8641b2014-09-28 17:37:53 +0000170 /*
171 * Close collector and connection
172 */
Nils Diewaldad3f3032014-09-24 01:42:47 +0000173 public void close () {
Nils Diewald392bcf32015-02-26 20:01:17 +0000174 this.commit();
175 try {
176 this.connection.close();
177 }
Nils Diewaldbb33da22015-03-04 16:24:25 +0000178 catch (SQLException e) {
Nils Diewald392bcf32015-02-26 20:01:17 +0000179 log.warn(e.getLocalizedMessage());
180 }
Nils Diewald8d8641b2014-09-28 17:37:53 +0000181 };
182
Nils Diewaldbb33da22015-03-04 16:24:25 +0000183
Nils Diewald8d8641b2014-09-28 17:37:53 +0000184 /*
185 * Close collector and probably connection
186 */
187 public void close (boolean close) {
Nils Diewald392bcf32015-02-26 20:01:17 +0000188 if (close)
189 this.close();
Akron98b78542015-08-06 21:43:08 +0200190
191 this.commit();
Nils Diewald6aa929e2014-09-17 13:30:34 +0000192 };
193};