1 |
| package org.jboss.cache.loader; |
2 |
| |
3 |
| import net.jcip.annotations.ThreadSafe; |
4 |
| import org.apache.commons.logging.Log; |
5 |
| import org.apache.commons.logging.LogFactory; |
6 |
| import org.jboss.cache.Fqn; |
7 |
| import org.jboss.cache.config.CacheLoaderConfig; |
8 |
| import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig; |
9 |
| import org.jboss.cache.marshall.NodeData; |
10 |
| |
11 |
| import java.io.InputStream; |
12 |
| import java.io.ObjectInputStream; |
13 |
| import java.sql.Connection; |
14 |
| import java.sql.PreparedStatement; |
15 |
| import java.sql.ResultSet; |
16 |
| import java.sql.SQLException; |
17 |
| import java.util.HashMap; |
18 |
| import java.util.List; |
19 |
| import java.util.Map; |
20 |
| |
21 |
| |
22 |
| |
23 |
| |
24 |
| |
25 |
| |
26 |
| |
27 |
| |
28 |
| |
29 |
| |
30 |
| |
31 |
| |
32 |
| |
33 |
| |
34 |
| |
35 |
| |
36 |
| |
37 |
| @ThreadSafe |
38 |
| public class JDBCCacheLoader extends AdjListJDBCCacheLoader |
39 |
| { |
40 |
| |
41 |
| private static final Log log = LogFactory.getLog(JDBCCacheLoader.class); |
42 |
| |
43 |
| private JDBCCacheLoaderConfig config; |
44 |
| |
45 |
| |
46 |
| |
47 |
| |
48 |
253
| protected AdjListJDBCCacheLoaderConfig processConfig(CacheLoaderConfig.IndividualCacheLoaderConfig base)
|
49 |
| { |
50 |
253
| if (base instanceof JDBCCacheLoaderConfig)
|
51 |
| { |
52 |
0
| config = (JDBCCacheLoaderConfig) base;
|
53 |
| } |
54 |
| else |
55 |
| { |
56 |
253
| config = new JDBCCacheLoaderConfig(base);
|
57 |
| } |
58 |
253
| return config;
|
59 |
| } |
60 |
| |
61 |
| |
62 |
| |
63 |
| |
64 |
| |
65 |
6539
| public Object put(Fqn name, Object key, Object value) throws Exception
|
66 |
| { |
67 |
6539
| Map toAdd = new HashMap();
|
68 |
6539
| toAdd.put(key, value);
|
69 |
6539
| Map existing = _put(name, toAdd);
|
70 |
6539
| return existing == null ? null : existing.get(key);
|
71 |
| } |
72 |
| |
73 |
| |
74 |
| |
75 |
| |
76 |
| |
77 |
6383
| public void put(Fqn name, Map attributes) throws Exception
|
78 |
| { |
79 |
6383
| _put(name, attributes);
|
80 |
| } |
81 |
| |
82 |
| |
83 |
| |
84 |
| |
85 |
| |
86 |
6636
| public void remove(Fqn fqn) throws Exception
|
87 |
| { |
88 |
6636
| Connection conn = null;
|
89 |
6636
| PreparedStatement ps = null;
|
90 |
6636
| try
|
91 |
| { |
92 |
6636
| conn = cf.getConnection();
|
93 |
6636
| ps = conn.prepareStatement(config.getDeleteNodeSql());
|
94 |
| |
95 |
6636
| ps.setString(1, fqn.isRoot() ? fqn.toString() : fqn + Fqn.SEPARATOR);
|
96 |
6636
| lock.acquireLock(fqn, true);
|
97 |
6636
| ps.executeUpdate();
|
98 |
| } |
99 |
| catch (SQLException e) |
100 |
| { |
101 |
0
| log.error("Failed to remove the node : " + fqn, e);
|
102 |
0
| throw new IllegalStateException("Failure while removing sub-tree (" + fqn + ")" + e.getMessage());
|
103 |
| } |
104 |
| finally |
105 |
| { |
106 |
6636
| safeClose(ps);
|
107 |
6636
| cf.close(conn);
|
108 |
6636
| lock.releaseLock(fqn);
|
109 |
| } |
110 |
| } |
111 |
| |
112 |
| |
113 |
| |
114 |
| |
115 |
| |
116 |
| |
117 |
26
| protected void getNodeDataList(Fqn fqn, List<NodeData> list) throws Exception
|
118 |
| { |
119 |
26
| Map nodeAttributes = loadNode(fqn);
|
120 |
26
| if (nodeAttributes == null)
|
121 |
| { |
122 |
10
| return;
|
123 |
| } |
124 |
16
| Connection connection = null;
|
125 |
16
| PreparedStatement ps = null;
|
126 |
16
| ResultSet rs = null;
|
127 |
16
| try
|
128 |
| { |
129 |
16
| connection = cf.getConnection();
|
130 |
16
| ps = connection.prepareStatement(config.getRecursiveChildrenSql());
|
131 |
16
| ps.setString(1, fqn.isRoot() ? fqn.toString() : fqn.toString() + Fqn.SEPARATOR);
|
132 |
16
| rs = ps.executeQuery();
|
133 |
16
| while (rs.next())
|
134 |
| { |
135 |
49
| Map<Object, Object> attributes = readAttributes(rs, 2);
|
136 |
49
| Fqn path = Fqn.fromString(rs.getString(1));
|
137 |
49
| NodeData nodeData = (attributes == null || attributes.isEmpty()) ? new NodeData(path) : new NodeData(path, attributes);
|
138 |
49
| list.add(nodeData);
|
139 |
| } |
140 |
| } |
141 |
| catch (SQLException e) |
142 |
| { |
143 |
0
| log.error("Failed to load state for node(" + fqn + ") :" + e.getMessage(), e);
|
144 |
0
| throw new IllegalStateException("Failed to load state for node(" + fqn + ") :" + e.getMessage());
|
145 |
| } |
146 |
| finally |
147 |
| { |
148 |
16
| safeClose(rs);
|
149 |
16
| safeClose(ps);
|
150 |
16
| cf.close(connection);
|
151 |
| } |
152 |
| } |
153 |
| |
154 |
49
| private Map<Object, Object> readAttributes(ResultSet rs, int index) throws SQLException
|
155 |
| { |
156 |
49
| Map<Object, Object> result;
|
157 |
49
| InputStream is = rs.getBinaryStream(index);
|
158 |
49
| if (is != null && !rs.wasNull())
|
159 |
| { |
160 |
32
| ObjectInputStream ois;
|
161 |
32
| try
|
162 |
| { |
163 |
32
| Object marshalledNode = unmarshall(is);
|
164 |
32
| result = (Map<Object, Object>) marshalledNode;
|
165 |
| } |
166 |
| catch (Exception e) |
167 |
| { |
168 |
0
| log.error("Failure while reading attribute set from db", e);
|
169 |
0
| throw new SQLException("Failure while reading attribute set from db " + e);
|
170 |
| } |
171 |
| } |
172 |
| else |
173 |
| { |
174 |
17
| result = null;
|
175 |
| } |
176 |
49
| return result;
|
177 |
| } |
178 |
| |
179 |
12922
| private Map _put(Fqn name, Map attributes) throws Exception
|
180 |
| { |
181 |
12922
| lock.acquireLock(name, true);
|
182 |
12922
| try
|
183 |
| { |
184 |
12922
| Map result = null;
|
185 |
12922
| Map treeNode = loadNode(name);
|
186 |
12922
| if (treeNode == null)
|
187 |
| { |
188 |
4731
| addNewSubtree(name, attributes);
|
189 |
| } |
190 |
8191
| else if (treeNode == NULL_NODE_IN_ROW)
|
191 |
| { |
192 |
19
| updateNode(name, attributes);
|
193 |
| } |
194 |
| else |
195 |
| { |
196 |
8172
| Map<Object, Object> newAttributes = new HashMap<Object, Object>(treeNode);
|
197 |
8172
| newAttributes.putAll(attributes);
|
198 |
8172
| updateNode(name, newAttributes);
|
199 |
8172
| result = treeNode;
|
200 |
| } |
201 |
12922
| return result;
|
202 |
| } |
203 |
| finally |
204 |
| { |
205 |
12922
| lock.releaseLock(name);
|
206 |
| } |
207 |
| } |
208 |
| |
209 |
4731
| private void addNewSubtree(Fqn name, Map attributes) throws Exception
|
210 |
| { |
211 |
4731
| Fqn currentNode = name;
|
212 |
4731
| do
|
213 |
| { |
214 |
5260
| if (currentNode.equals(name))
|
215 |
| { |
216 |
4731
| insertNode(currentNode, attributes);
|
217 |
| } |
218 |
| else |
219 |
| { |
220 |
529
| insertNode(currentNode, null);
|
221 |
| } |
222 |
5260
| if (currentNode.isRoot())
|
223 |
| { |
224 |
228
| break;
|
225 |
| } |
226 |
5032
| currentNode = currentNode.getParent();
|
227 |
| } |
228 |
5032
| while (!exists(currentNode));
|
229 |
| } |
230 |
| |
231 |
| |
232 |
55550
| protected Log getLogger()
|
233 |
| { |
234 |
55550
| return log;
|
235 |
| } |
236 |
| |
237 |
| |
238 |
| |
239 |
| |
240 |
| |
241 |
| |
242 |
| |
243 |
| |
244 |
| |
245 |
| |
246 |
247
| public void start() throws Exception
|
247 |
| { |
248 |
247
| super.start();
|
249 |
247
| if (!exists(Fqn.ROOT) && getNodeCount() > 0)
|
250 |
| { |
251 |
2
| put(Fqn.ROOT, null);
|
252 |
| } |
253 |
| } |
254 |
| |
255 |
| |
256 |
| |
257 |
| |
258 |
246
| public int getNodeCount() throws Exception
|
259 |
| { |
260 |
246
| Connection conn = null;
|
261 |
246
| PreparedStatement ps = null;
|
262 |
246
| ResultSet rs = null;
|
263 |
246
| try
|
264 |
| { |
265 |
246
| conn = cf.getConnection();
|
266 |
246
| ps = conn.prepareStatement(config.getNodeCountSql());
|
267 |
246
| rs = ps.executeQuery();
|
268 |
246
| rs.next();
|
269 |
246
| return rs.getInt(1);
|
270 |
| } |
271 |
| catch (Exception e) |
272 |
| { |
273 |
0
| log.error("Failure while trying to get the count of persisted nodes: " + e.getMessage(), e);
|
274 |
0
| throw new IllegalStateException("Failure while trying to get the count of persisted nodes: " + e.getMessage());
|
275 |
| } |
276 |
| finally |
277 |
| { |
278 |
246
| safeClose(rs);
|
279 |
246
| safeClose(ps);
|
280 |
246
| cf.close(conn);
|
281 |
| } |
282 |
| } |
283 |
| |
284 |
247
| public IndividualCacheLoaderConfig getConfig()
|
285 |
| { |
286 |
247
| return config;
|
287 |
| } |
288 |
| } |