Mercurial Hosting > nabble
comparison src/fschmidt/util/servlet/DbCache.java @ 68:00520880ad02
add fschmidt source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 05 Oct 2025 17:24:15 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
67:9d0fefce6985 | 68:00520880ad02 |
---|---|
1 /* | |
2 Copyright (c) 2008 Franklin Schmidt <fschmidt@gmail.com> | |
3 | |
4 Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 of this software and associated documentation files (the "Software"), to deal | |
6 in the Software without restriction, including without limitation the rights | |
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 copies of the Software, and to permit persons to whom the Software is | |
9 furnished to do so, subject to the following conditions: | |
10 | |
11 The above copyright notice and this permission notice shall be included in | |
12 all copies or substantial portions of the Software. | |
13 | |
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 THE SOFTWARE. | |
21 */ | |
22 | |
23 package fschmidt.util.servlet; | |
24 | |
25 import java.sql.Connection; | |
26 import java.sql.PreparedStatement; | |
27 import java.sql.ResultSet; | |
28 import java.sql.SQLException; | |
29 import java.sql.Statement; | |
30 import java.util.Date; | |
31 import java.util.Map; | |
32 import java.util.HashMap; | |
33 import fschmidt.db.DbDatabase; | |
34 import fschmidt.db.postgres.DbDatabaseImpl; | |
35 | |
36 | |
37 public final class DbCache implements HttpCache { | |
38 private final DbDatabase db; | |
39 private long lastClear; | |
40 private static final String LAST_CLEAR = "_last_clear"; | |
41 | |
42 public DbCache(DbDatabase db) { | |
43 this.db = db; | |
44 setLastClear(); | |
45 } | |
46 | |
47 private void setLastClear() { | |
48 try { | |
49 Connection con = db.getConnection(); | |
50 try { | |
51 PreparedStatement stmt = con.prepareStatement( | |
52 "select last_modified from http_cache where event=?" | |
53 ); | |
54 stmt.setString(1,LAST_CLEAR); | |
55 ResultSet rs = stmt.executeQuery(); | |
56 if( !rs.next() ) { | |
57 modified(LAST_CLEAR); | |
58 stmt.setString(1,LAST_CLEAR); | |
59 rs = stmt.executeQuery(); | |
60 rs.next(); | |
61 } | |
62 lastClear = getLastModified(rs); | |
63 stmt.close(); | |
64 } finally { | |
65 con.close(); | |
66 } | |
67 } catch(SQLException e) { | |
68 throw new RuntimeException(e); | |
69 } | |
70 } | |
71 | |
72 private static long getLastModified(ResultSet rs) throws SQLException { | |
73 return rs.getTimestamp("last_modified").getTime()/1000*1000; | |
74 } | |
75 | |
76 public long[] lastModifieds(final String[] modifyingEvents) { | |
77 switch( modifyingEvents.length ) { | |
78 case 0: | |
79 return new long[0]; | |
80 case 1: | |
81 try { | |
82 Connection con = db.getConnection(); | |
83 PreparedStatement stmt = con.prepareStatement( | |
84 "select last_modified from http_cache where event=?" | |
85 ); | |
86 try { | |
87 stmt.setString(1,modifyingEvents[0].toString()); | |
88 ResultSet rs = stmt.executeQuery(); | |
89 return new long[]{ rs.next() ? getLastModified(rs) : lastClear }; | |
90 } finally { | |
91 stmt.close(); | |
92 con.close(); | |
93 } | |
94 } catch(SQLException e) { | |
95 throw new RuntimeException(e); | |
96 } | |
97 default: | |
98 StringBuilder select = new StringBuilder(); | |
99 try { | |
100 final String[] events = new String[modifyingEvents.length]; | |
101 final long[] rtn = new long[modifyingEvents.length]; | |
102 for( int i=0; i<modifyingEvents.length; i++ ) { | |
103 events[i] = modifyingEvents[i].toString(); | |
104 rtn[i] = lastClear; | |
105 } | |
106 Map<String,Long> map = new HashMap<String,Long>(); | |
107 select.append( | |
108 "select event,last_modified from http_cache where event in (" | |
109 ).append( db.arcana().quote(events[0]) ); | |
110 for( int i=1; i<events.length; i++ ) { | |
111 select.append( ',' ).append( db.arcana().quote(events[i]) ); | |
112 } | |
113 select.append( ")" ); | |
114 Connection con = db.getConnection(); | |
115 try { | |
116 Statement stmt = con.createStatement(); | |
117 ResultSet rs = stmt.executeQuery( select.toString() ); | |
118 while( rs.next() ) { | |
119 map.put( rs.getString("event"), getLastModified(rs) ); | |
120 } | |
121 stmt.close(); | |
122 } finally { | |
123 con.close(); | |
124 } | |
125 for( int i=0; !map.isEmpty(); i++ ) { | |
126 Long lm = map.remove(events[i]); | |
127 if( lm != null ) | |
128 rtn[i] = lm; | |
129 } | |
130 return rtn; | |
131 } catch(SQLException e) { | |
132 throw new RuntimeException(select.toString(),e); | |
133 } | |
134 } | |
135 } | |
136 | |
137 public void modified(final String event) { | |
138 db.runAfterCommit(new Runnable(){public void run(){ | |
139 try { | |
140 Connection con = db.getConnection(); | |
141 try { | |
142 boolean didUpdate; | |
143 { | |
144 PreparedStatement stmt = con.prepareStatement( | |
145 "update http_cache set last_modified=now() where event = ?" | |
146 ); | |
147 stmt.setString(1,event); | |
148 didUpdate = stmt.executeUpdate() > 0; | |
149 stmt.close(); | |
150 } | |
151 if( !didUpdate ) { | |
152 PreparedStatement stmt = con.prepareStatement( | |
153 "insert into http_cache (event) values (?)" | |
154 ); | |
155 stmt.setString(1,event); | |
156 DbDatabaseImpl.executeUpdateIgnoringDuplicateKeys(stmt); | |
157 stmt.close(); | |
158 } | |
159 } finally { | |
160 con.close(); | |
161 } | |
162 } catch(SQLException e) { | |
163 throw new RuntimeException("event = "+event,e); | |
164 } | |
165 }}); | |
166 } | |
167 | |
168 public void clear() { | |
169 try { | |
170 Connection con = db.getConnection(); | |
171 try { | |
172 Statement stmt = con.createStatement(); | |
173 stmt.executeUpdate( | |
174 "delete from http_cache" | |
175 ); | |
176 stmt.close(); | |
177 } finally { | |
178 con.close(); | |
179 } | |
180 } catch(SQLException e) { | |
181 throw new RuntimeException(e); | |
182 } | |
183 setLastClear(); | |
184 } | |
185 | |
186 /* | |
187 assumes: | |
188 | |
189 create table http_cache ( | |
190 event varchar not null primary key, | |
191 last_modified timestamp with time zone NOT NULL DEFAULT now() | |
192 ); | |
193 */ | |
194 } |