blob: 2cfa252cdde510145bcd3e4c2ae37090dc572d4a [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
Nils Diewaldd723d812014-09-23 18:50:52 +000016public 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;
Nils Diewald6aa929e2014-09-17 13:30:34 +000026 private List matchCollector;
Nils Diewaldf04e1002014-09-24 22:52:59 +000027 private int bufferSize, docCollect;
Nils Diewaldad3f3032014-09-24 01:42:47 +000028 private String resultID;
Nils Diewald6aa929e2014-09-17 13:30:34 +000029
Nils Diewald8d8641b2014-09-28 17:37:53 +000030 // private Connection connection;
Nils Diewaldf04e1002014-09-24 22:52:59 +000031 private DataSource pool;
Nils Diewaldad3f3032014-09-24 01:42:47 +000032 private Connection connection;
33 private PreparedStatement prepared;
Nils Diewald6aa929e2014-09-17 13:30:34 +000034
Nils Diewaldbb33da22015-03-04 16:24:25 +000035
Nils Diewald6aa929e2014-09-17 13:30:34 +000036 /*
37 * Create a new collector for database connections
38 */
Nils Diewaldad3f3032014-09-24 01:42:47 +000039 public MatchCollectorDB (int bufferSize, String resultID) {
Nils Diewald392bcf32015-02-26 20:01:17 +000040 this.bufferSize = bufferSize;
41 this.resultID = resultID;
42 this.matchCollector = new ArrayList<int[]>(bufferSize + 2);
Nils Diewald6aa929e2014-09-17 13:30:34 +000043 };
44
Nils Diewaldbb33da22015-03-04 16:24:25 +000045
Nils Diewald6aa929e2014-09-17 13:30:34 +000046 /*
47 * Add matches till the bufferSize exceeds - then commit to the database.
48 */
Nils Diewaldad3f3032014-09-24 01:42:47 +000049 public void add (int UID, int matchCount) {
Nils Diewald392bcf32015-02-26 20:01:17 +000050 if (this.docCollect == bufferSize)
51 this.commit();
Nils Diewaldf04e1002014-09-24 22:52:59 +000052
Nils Diewald392bcf32015-02-26 20:01:17 +000053 this.incrTotalResultDocs(1);
54 this.incrTotalResults(matchCount);
Nils Diewaldbb33da22015-03-04 16:24:25 +000055 this.matchCollector.add(new int[] { UID, matchCount });
Nils Diewald392bcf32015-02-26 20:01:17 +000056 this.docCollect++;
Nils Diewald6aa929e2014-09-17 13:30:34 +000057 };
58
Nils Diewaldbb33da22015-03-04 16:24:25 +000059
Nils Diewaldad3f3032014-09-24 01:42:47 +000060 @JsonIgnore
61 public void setDatabaseType (String type) {
Nils Diewald392bcf32015-02-26 20:01:17 +000062 this.databaseType = type;
Nils Diewaldad3f3032014-09-24 01:42:47 +000063 };
64
Nils Diewaldbb33da22015-03-04 16:24:25 +000065
Nils Diewaldad3f3032014-09-24 01:42:47 +000066 @JsonIgnore
67 public String getDatabaseType () {
Nils Diewald392bcf32015-02-26 20:01:17 +000068 return this.databaseType;
Nils Diewaldad3f3032014-09-24 01:42:47 +000069 };
70
Nils Diewaldbb33da22015-03-04 16:24:25 +000071
Nils Diewaldad3f3032014-09-24 01:42:47 +000072 @JsonIgnore
Nils Diewaldbb33da22015-03-04 16:24:25 +000073 public void setDBPool (String type, DataSource ds, Connection conn)
74 throws SQLException {
Nils Diewald392bcf32015-02-26 20:01:17 +000075 this.setDatabaseType(type);
76 this.connection = conn;
77 this.pool = ds;
Nils Diewald8d8641b2014-09-28 17:37:53 +000078 };
79
80
81 @JsonIgnore
Nils Diewaldf04e1002014-09-24 22:52:59 +000082 public void setDBPool (String type, DataSource ds) throws SQLException {
Nils Diewald392bcf32015-02-26 20:01:17 +000083 this.setDatabaseType(type);
84 this.pool = ds;
Nils Diewaldad3f3032014-09-24 01:42:47 +000085 };
Nils Diewaldbb33da22015-03-04 16:24:25 +000086
87
Nils Diewald8d8641b2014-09-28 17:37:53 +000088 /*
89 Create prepared statement for multiple requests
90 this.prepared = this.conn.prepareStatement(
91 "INSERT INTO people VALUES (?, ?);"
92 );
93 Only prepare if commit > buffersize!
94 Difference between mariadb and sqlite!
95 */
96
Nils Diewaldbb33da22015-03-04 16:24:25 +000097
Nils Diewaldf04e1002014-09-24 22:52:59 +000098 /* TODO: Ensure the commit was successful! */
Nils Diewaldbb33da22015-03-04 16:24:25 +000099 public void commit () {
Nils Diewald392bcf32015-02-26 20:01:17 +0000100 if (this.pool == null)
101 return;
Nils Diewaldad3f3032014-09-24 01:42:47 +0000102
Nils Diewald392bcf32015-02-26 20:01:17 +0000103 try {
Nils Diewaldbb33da22015-03-04 16:24:25 +0000104 /*
105 * This should be heavily optimized! It's aweful!
106 * ARGHHHHHHH!
107 */
Nils Diewald392bcf32015-02-26 20:01:17 +0000108 if (this.connection.isClosed())
109 this.connection = this.pool.getConnection();
Nils Diewaldf04e1002014-09-24 22:52:59 +0000110
Nils Diewald392bcf32015-02-26 20:01:17 +0000111 StringBuilder sb = new StringBuilder();
Nils Diewaldbb33da22015-03-04 16:24:25 +0000112 sb.append("INSERT INTO ").append(this.resultID)
113 .append(" (text_id, match_count) ");
114
Nils Diewald392bcf32015-02-26 20:01:17 +0000115 // SQLite batch insertion idiom
116 if (this.getDatabaseType().equals("sqlite")) {
117 for (int i = 1; i < this.docCollect; i++) {
118 sb.append("SELECT ?, ? UNION ");
119 }
120 if (this.docCollect == 1)
121 sb.append("VALUES (?, ?)");
122 else
123 sb.append("SELECT ?, ?");
124 }
Nils Diewaldf04e1002014-09-24 22:52:59 +0000125
Nils Diewald392bcf32015-02-26 20:01:17 +0000126 // MySQL batch insertion idiom
127 else if (this.getDatabaseType().equals("mysql")) {
128 sb.append(" VALUES ");
129 for (int i = 1; i < this.docCollect; i++) {
130 sb.append("(?,?),");
131 };
132 sb.append("(?,?)");
133 }
Nils Diewaldbb33da22015-03-04 16:24:25 +0000134
Nils Diewald392bcf32015-02-26 20:01:17 +0000135 // Unknown idiom
136 else {
137 log.error("Unsupported Database type");
138 return;
139 };
Nils Diewaldf04e1002014-09-24 22:52:59 +0000140
Nils Diewald392bcf32015-02-26 20:01:17 +0000141 // Prepare statement based on the string
Nils Diewaldbb33da22015-03-04 16:24:25 +0000142 PreparedStatement prep = this.connection.prepareStatement(sb
143 .toString());
Nils Diewaldf04e1002014-09-24 22:52:59 +0000144
Nils Diewald392bcf32015-02-26 20:01:17 +0000145 int i = 1;
Nils Diewaldbb33da22015-03-04 16:24:25 +0000146 ListIterator li = this.matchCollector.listIterator();
Nils Diewald392bcf32015-02-26 20:01:17 +0000147 while (li.hasNext()) {
148 int[] v = (int[]) li.next();
149 prep.setInt(i++, v[0]);
150 prep.setInt(i++, v[1]);
151 };
Nils Diewald8d8641b2014-09-28 17:37:53 +0000152
Nils Diewald392bcf32015-02-26 20:01:17 +0000153 prep.addBatch();
154 prep.executeBatch();
155 this.connection.commit();
156 }
Nils Diewaldf04e1002014-09-24 22:52:59 +0000157
Nils Diewald392bcf32015-02-26 20:01:17 +0000158 // An SQL error occured ...
159 catch (SQLException e) {
160 log.error(e.getLocalizedMessage());
161 };
Nils Diewaldf04e1002014-09-24 22:52:59 +0000162
Nils Diewald392bcf32015-02-26 20:01:17 +0000163 this.matchCollector.clear();
164 this.docCollect = 0;
165 return;
Nils Diewaldad3f3032014-09-24 01:42:47 +0000166 };
167
Nils Diewaldbb33da22015-03-04 16:24:25 +0000168
Nils Diewald8d8641b2014-09-28 17:37:53 +0000169 /*
170 * Close collector and connection
171 */
Nils Diewaldad3f3032014-09-24 01:42:47 +0000172 public void close () {
Nils Diewald392bcf32015-02-26 20:01:17 +0000173 this.commit();
174 try {
175 this.connection.close();
176 }
Nils Diewaldbb33da22015-03-04 16:24:25 +0000177 catch (SQLException e) {
Nils Diewald392bcf32015-02-26 20:01:17 +0000178 log.warn(e.getLocalizedMessage());
179 }
Nils Diewald8d8641b2014-09-28 17:37:53 +0000180 };
181
Nils Diewaldbb33da22015-03-04 16:24:25 +0000182
Nils Diewald8d8641b2014-09-28 17:37:53 +0000183 /*
184 * Close collector and probably connection
185 */
186 public void close (boolean close) {
Nils Diewald392bcf32015-02-26 20:01:17 +0000187 if (close)
188 this.close();
189 else
190 this.commit();
Nils Diewald6aa929e2014-09-17 13:30:34 +0000191 };
192};