1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| |
16 |
| |
17 |
| |
18 |
| |
19 |
| |
20 |
| package org.apache.xindice.core; |
21 |
| |
22 |
| import org.apache.commons.logging.Log; |
23 |
| import org.apache.commons.logging.LogFactory; |
24 |
| import org.apache.xindice.core.cache.DocumentCache; |
25 |
| import org.apache.xindice.core.data.DocumentSet; |
26 |
| import org.apache.xindice.core.data.EmptyDocumentSet; |
27 |
| import org.apache.xindice.core.data.EmptyNodeSet; |
28 |
| import org.apache.xindice.core.data.Entry; |
29 |
| import org.apache.xindice.core.data.Key; |
30 |
| import org.apache.xindice.core.data.NodeSet; |
31 |
| import org.apache.xindice.core.data.Record; |
32 |
| import org.apache.xindice.core.data.RecordSet; |
33 |
| import org.apache.xindice.core.data.Value; |
34 |
| import org.apache.xindice.core.filer.Filer; |
35 |
| import org.apache.xindice.core.indexer.IndexManager; |
36 |
| import org.apache.xindice.core.indexer.Indexer; |
37 |
| import org.apache.xindice.core.meta.MetaData; |
38 |
| import org.apache.xindice.core.meta.inline.InlineMetaMap; |
39 |
| import org.apache.xindice.core.meta.inline.InlineMetaService; |
40 |
| import org.apache.xindice.core.meta.inline.ResourceTypeReader; |
41 |
| import org.apache.xindice.core.query.QueryEngine; |
42 |
| import org.apache.xindice.util.Configurable; |
43 |
| import org.apache.xindice.util.Configuration; |
44 |
| import org.apache.xindice.util.Named; |
45 |
| import org.apache.xindice.util.XindiceException; |
46 |
| import org.apache.xindice.xml.NamespaceMap; |
47 |
| import org.apache.xindice.xml.NodeSource; |
48 |
| import org.apache.xindice.xml.SymbolTable; |
49 |
| import org.apache.xindice.xml.TextWriter; |
50 |
| import org.apache.xindice.xml.XMLSerializable; |
51 |
| import org.apache.xindice.xml.dom.DBDocument; |
52 |
| import org.apache.xindice.xml.dom.DOMCompressor; |
53 |
| import org.apache.xindice.xml.dom.DOMParser; |
54 |
| import org.apache.xindice.xml.dom.DocumentImpl; |
55 |
| |
56 |
| import org.w3c.dom.Document; |
57 |
| import org.w3c.dom.Element; |
58 |
| import org.w3c.dom.Node; |
59 |
| import org.w3c.dom.NodeList; |
60 |
| import org.w3c.dom.ProcessingInstruction; |
61 |
| |
62 |
| import java.io.File; |
63 |
| import java.io.UnsupportedEncodingException; |
64 |
| import java.lang.ref.WeakReference; |
65 |
| import java.net.InetAddress; |
66 |
| import java.util.ArrayList; |
67 |
| import java.util.Map; |
68 |
| import java.util.WeakHashMap; |
69 |
| |
70 |
| |
71 |
| |
72 |
| |
73 |
| |
74 |
| |
75 |
| |
76 |
| |
77 |
| public class Collection extends CollectionManager |
78 |
| implements Named, DBObject, Configurable { |
79 |
| |
80 |
| private static final Log log = LogFactory.getLog(Collection.class); |
81 |
| |
82 |
| private static final String CACHE = "cache"; |
83 |
| private static final String CLASS = "class"; |
84 |
| private static final String CLASSNAME = "xindice-class"; |
85 |
| private static final String COMPRESSED = "compressed"; |
86 |
| private static final String FILER = "filer"; |
87 |
| private static final String INDEXES = "indexes"; |
88 |
| private static final String INLINE_METADATA = "inline-metadata"; |
89 |
| private static final String NAME = "name"; |
90 |
| private static final String SYMBOLS = "symbols"; |
91 |
| |
92 |
| private static final byte ACTION_INSERT = 1; |
93 |
| private static final byte ACTION_UPDATE = 2; |
94 |
| private static final byte ACTION_STORE = 3; |
95 |
| |
96 |
| private static final DocumentSet EMPTY_DOCUMENTSET = new EmptyDocumentSet(); |
97 |
| private static final NodeSet EMPTY_NODESET = new EmptyNodeSet(); |
98 |
| private static final String[] EMPTY_STRING_ARRAY = {}; |
99 |
| |
100 |
| private static int host_id; |
101 |
| static { |
102 |
19
| try {
|
103 |
19
| InetAddress a = InetAddress.getLocalHost();
|
104 |
19
| byte[] b = a.getAddress();
|
105 |
19
| host_id = 0;
|
106 |
19
| host_id += b[0];
|
107 |
19
| host_id += (b[1] << 8);
|
108 |
19
| host_id += (b[2] << 16);
|
109 |
19
| host_id += (b[3] << 24);
|
110 |
19
| host_id = Math.abs(host_id);
|
111 |
| } catch (Exception e) { |
112 |
0
| if (log.isWarnEnabled()) {
|
113 |
0
| log.warn("ignored exception", e);
|
114 |
| } |
115 |
| } |
116 |
| } |
117 |
| |
118 |
| |
119 |
| |
120 |
| |
121 |
| private class ColContainer implements Container { |
122 |
| private Document document; |
123 |
| private Key key; |
124 |
| |
125 |
0
| public ColContainer(Key key, Document document) {
|
126 |
0
| this.key = key;
|
127 |
0
| this.document = document;
|
128 |
| } |
129 |
| |
130 |
0
| public void commit() throws DBException {
|
131 |
0
| putDocument(this.key, this.document, ACTION_STORE);
|
132 |
| } |
133 |
| |
134 |
0
| public void commit(Document doc) throws DBException {
|
135 |
0
| this.document = doc;
|
136 |
0
| commit();
|
137 |
| } |
138 |
| |
139 |
0
| public String getCanonicalName() throws DBException {
|
140 |
0
| return Collection.this.getCanonicalDocumentName(key);
|
141 |
| } |
142 |
| |
143 |
0
| public Collection getCollection() {
|
144 |
0
| return Collection.this;
|
145 |
| } |
146 |
| |
147 |
0
| public Document getDocument() {
|
148 |
0
| return this.document;
|
149 |
| } |
150 |
| |
151 |
0
| public Key getKey() {
|
152 |
0
| return this.key;
|
153 |
| } |
154 |
| |
155 |
0
| public void remove() throws DBException {
|
156 |
0
| Collection.this.remove(key);
|
157 |
| } |
158 |
| |
159 |
0
| public Document rollback() throws DBException {
|
160 |
0
| this.document = Collection.this.getDocument(key);
|
161 |
0
| return this.document;
|
162 |
| } |
163 |
| } |
164 |
| |
165 |
| |
166 |
| |
167 |
| |
168 |
| private class ColDocumentSet implements DocumentSet { |
169 |
| private RecordSet set; |
170 |
| |
171 |
0
| public ColDocumentSet(RecordSet set) {
|
172 |
0
| this.set = set;
|
173 |
| } |
174 |
| |
175 |
0
| public Container getNextContainer() throws DBException {
|
176 |
0
| if (set.hasMoreRecords()) {
|
177 |
0
| Record rec = set.getNextRecord();
|
178 |
0
| Key key = rec.getKey();
|
179 |
0
| Value val = rec.getValue();
|
180 |
0
| if (val.getLength() > 0) {
|
181 |
0
| try {
|
182 |
0
| if (compressed) {
|
183 |
0
| Document doc = new DocumentImpl(val.getData(), symbols, new NodeSource(Collection.this, key));
|
184 |
0
| return new ColContainer(key, doc);
|
185 |
| } else { |
186 |
0
| return new ColContainer(key, DOMParser.toDocument(val));
|
187 |
| } |
188 |
| } catch (Exception e) { |
189 |
0
| if (log.isWarnEnabled()) {
|
190 |
0
| log.warn("ignored exception", e);
|
191 |
| } |
192 |
| } |
193 |
| } |
194 |
| } |
195 |
0
| return null;
|
196 |
| } |
197 |
| |
198 |
0
| public Document getNextDocument() throws DBException {
|
199 |
0
| Container c = getNextContainer();
|
200 |
0
| if (c != null) {
|
201 |
0
| return c.getDocument();
|
202 |
| } else { |
203 |
0
| return null;
|
204 |
| } |
205 |
| } |
206 |
| |
207 |
0
| public boolean hasMoreDocuments() throws DBException {
|
208 |
0
| return set.hasMoreRecords();
|
209 |
| } |
210 |
| } |
211 |
| |
212 |
| |
213 |
| private String name; |
214 |
| private String canonicalName; |
215 |
| private Collection parent; |
216 |
| |
217 |
| |
218 |
| private final Object oidMutex = new Object(); |
219 |
| private String oidTemplate; |
220 |
| private long documentId; |
221 |
| |
222 |
| private SymbolTable symbols; |
223 |
| |
224 |
| private File collectionRoot; |
225 |
| private boolean compressed; |
226 |
| private Filer filer; |
227 |
| private InlineMetaService inlineMetaService; |
228 |
| private DocumentCache cache; |
229 |
| private IndexManager indexManager; |
230 |
| |
231 |
| |
232 |
| private final Map identityMap = new WeakHashMap(); |
233 |
| |
234 |
| |
235 |
123
| protected Collection() {
|
236 |
123
| documentId = System.currentTimeMillis();
|
237 |
| } |
238 |
| |
239 |
| |
240 |
| |
241 |
| |
242 |
1661
| public Collection(Collection parent) {
|
243 |
1661
| this.parent = parent;
|
244 |
| } |
245 |
| |
246 |
18087
| public boolean isCompressed() {
|
247 |
18087
| return compressed;
|
248 |
| } |
249 |
| |
250 |
| |
251 |
| |
252 |
76356
| private void checkFiler(int faultCode) throws DBException {
|
253 |
76356
| if (filer == null) {
|
254 |
0
| throw new DBException(faultCode,
|
255 |
| "Collection '" + name + "' cannot store resources (no filer)"); |
256 |
| } |
257 |
76356
| if (!filer.isOpened()) {
|
258 |
0
| throw new DBException(FaultCodes.COL_COLLECTION_CLOSED,
|
259 |
| "Collection '" + name + "' is closed."); |
260 |
| } |
261 |
| } |
262 |
| |
263 |
74621
| private Key getIdentityKey(Key key) {
|
264 |
74621
| synchronized (identityMap) {
|
265 |
74621
| Key id = null;
|
266 |
74621
| WeakReference ref = (WeakReference) identityMap.get(key);
|
267 |
74621
| if (ref != null) {
|
268 |
69512
| id = (Key) ref.get();
|
269 |
| } |
270 |
74621
| if (id == null) {
|
271 |
5109
| id = key;
|
272 |
5109
| identityMap.put(id, new WeakReference(id));
|
273 |
| } |
274 |
| |
275 |
74621
| return id;
|
276 |
| } |
277 |
| } |
278 |
| |
279 |
14978
| private String debugHeader() {
|
280 |
14978
| return "["
|
281 |
| + Thread.currentThread().getName() |
282 |
| + "] '" |
283 |
14978
| + (parent != null ? parent.getCanonicalName() : "")
|
284 |
| + "/" |
285 |
| + name |
286 |
| + "' "; |
287 |
| } |
288 |
| |
289 |
| |
290 |
| |
291 |
| |
292 |
45437
| private void flushSymbolTable() throws DBException {
|
293 |
45437
| if (symbols.isDirty()) {
|
294 |
941
| getSystemCollection().saveSymbols(this, symbols);
|
295 |
| } |
296 |
| } |
297 |
| |
298 |
| |
299 |
| |
300 |
| |
301 |
0
| protected void setName(String name) {
|
302 |
0
| this.name = name;
|
303 |
| } |
304 |
| |
305 |
1771
| protected final void setCanonicalName(String canonicalName) {
|
306 |
1771
| this.canonicalName = canonicalName;
|
307 |
| |
308 |
| |
309 |
1771
| StringBuffer sb = new StringBuffer("00000000000000000000000000000000");
|
310 |
1771
| String host = Integer.toString(host_id, 16);
|
311 |
1771
| sb.insert(8 - host.length(), host);
|
312 |
| |
313 |
1771
| String collection = Integer.toString(Math.abs(canonicalName.hashCode()), 16);
|
314 |
1771
| sb.insert(16 - collection.length(), collection);
|
315 |
| |
316 |
1771
| sb.setLength(32);
|
317 |
1771
| oidTemplate = sb.toString();
|
318 |
| } |
319 |
| |
320 |
1771
| protected final void setCollectionRoot(File collectionRoot) {
|
321 |
1771
| this.collectionRoot = collectionRoot;
|
322 |
1771
| if (!collectionRoot.exists()) {
|
323 |
1059
| if (log.isTraceEnabled()) {
|
324 |
0
| log.trace("Creating directories: " + collectionRoot);
|
325 |
| } |
326 |
1059
| collectionRoot.mkdirs();
|
327 |
| } |
328 |
| } |
329 |
| |
330 |
| |
331 |
| |
332 |
| |
333 |
| |
334 |
| |
335 |
| |
336 |
| |
337 |
| |
338 |
74627
| protected final Key createNewKey(Object key) {
|
339 |
74627
| if (key == null) {
|
340 |
1
| return createNewOID();
|
341 |
74626
| } else if (key instanceof Key) {
|
342 |
55197
| return (Key) key;
|
343 |
| } else { |
344 |
19429
| return new Key(key.toString());
|
345 |
| } |
346 |
| } |
347 |
| |
348 |
| |
349 |
| |
350 |
| |
351 |
| |
352 |
| |
353 |
| |
354 |
| |
355 |
| |
356 |
| |
357 |
16773
| private Document parseDocument(Key key, String xml) throws DBException {
|
358 |
16773
| try {
|
359 |
16773
| Document doc = DOMParser.toDocument(xml);
|
360 |
16773
| ((DBDocument) doc).setSource(new NodeSource(this, key));
|
361 |
| |
362 |
| |
363 |
| |
364 |
16773
| DOMCompressor.compress(doc, symbols);
|
365 |
| |
366 |
16773
| return doc;
|
367 |
| } catch (Exception e) { |
368 |
0
| throw new DBException(FaultCodes.COL_DOCUMENT_MALFORMED,
|
369 |
| "Unable to parse document '" + key + "' in '" + getCanonicalName() + "'", e); |
370 |
| } |
371 |
| } |
372 |
| |
373 |
| |
374 |
| |
375 |
| |
376 |
0
| public boolean isOpened() {
|
377 |
| |
378 |
| |
379 |
0
| if (filer == null) {
|
380 |
0
| return true;
|
381 |
| } |
382 |
| |
383 |
0
| return filer.isOpened();
|
384 |
| } |
385 |
| |
386 |
| |
387 |
| |
388 |
| |
389 |
0
| public boolean exists() throws DBException {
|
390 |
0
| return true;
|
391 |
| } |
392 |
| |
393 |
| |
394 |
| |
395 |
| |
396 |
1033
| public boolean create() throws DBException {
|
397 |
| |
398 |
1033
| updateCollectionMeta();
|
399 |
| |
400 |
1033
| DBObserver.getInstance().createCollection(this);
|
401 |
1033
| return true;
|
402 |
| } |
403 |
| |
404 |
0
| public final boolean open() throws DBException {
|
405 |
0
| return true;
|
406 |
| } |
407 |
| |
408 |
| |
409 |
| |
410 |
| |
411 |
1036
| public boolean drop() throws DBException {
|
412 |
1036
| DBObserver.getInstance().dropCollection(this);
|
413 |
| |
414 |
| |
415 |
1036
| if (isMetaEnabled()) {
|
416 |
1035
| getMetaSystemCollection().dropCollectionMeta(this);
|
417 |
| } |
418 |
| |
419 |
| |
420 |
1036
| String[] cols = listCollections();
|
421 |
1036
| for (int i = 0; i < cols.length; i++) {
|
422 |
42
| dropCollection(getCollection(cols[i]));
|
423 |
| } |
424 |
| |
425 |
1036
| if (filer != null) {
|
426 |
| |
427 |
1036
| indexManager.drop();
|
428 |
1036
| filer.drop();
|
429 |
| } |
430 |
| |
431 |
1036
| getCollectionRoot().delete();
|
432 |
| |
433 |
| |
434 |
1036
| if (!symbols.isReadOnly()) {
|
435 |
1036
| getSystemCollection().dropSymbols(this);
|
436 |
| } |
437 |
| |
438 |
1036
| getDatabase().flushConfig();
|
439 |
1036
| return true;
|
440 |
| } |
441 |
| |
442 |
| |
443 |
| |
444 |
| |
445 |
736
| public boolean close() throws DBException {
|
446 |
| |
447 |
736
| super.close();
|
448 |
| |
449 |
| |
450 |
736
| if (filer != null) {
|
451 |
246
| indexManager.close();
|
452 |
246
| filer.close();
|
453 |
| } |
454 |
| |
455 |
736
| return true;
|
456 |
| } |
457 |
| |
458 |
| |
459 |
| |
460 |
| |
461 |
1894
| public void setConfig(Configuration config) throws XindiceException {
|
462 |
1894
| name = config.getAttribute(NAME);
|
463 |
1894
| compressed = config.getBooleanAttribute(COMPRESSED, true);
|
464 |
| |
465 |
| |
466 |
| |
467 |
| |
468 |
1894
| if (config.getBooleanAttribute(INLINE_METADATA, false)) {
|
469 |
513
| inlineMetaService = new InlineMetaService();
|
470 |
| } |
471 |
| |
472 |
| |
473 |
| |
474 |
| |
475 |
| |
476 |
1894
| final String localDebugHeader = debugHeader() + "setConfig: ";
|
477 |
| |
478 |
| |
479 |
1894
| if (parent != null) {
|
480 |
1648
| setCanonicalName(parent.getCanonicalName() + '/' + name);
|
481 |
1648
| setCollectionRoot(new File(parent.getCollectionRoot(), name));
|
482 |
1648
| if (log.isDebugEnabled()) {
|
483 |
0
| log.debug(localDebugHeader + "Root=<" + getCollectionRoot() + ">");
|
484 |
| } |
485 |
| } |
486 |
| |
487 |
1894
| if (log.isDebugEnabled()) {
|
488 |
0
| log.debug(localDebugHeader
|
489 |
0
| + (compressed ? "Compressed" : "NOT Compressed")
|
490 |
| + ", " |
491 |
0
| + (inlineMetaService == null ? "Inline metadata DISABLED" : "Inline metadata ENABLED")
|
492 |
| ); |
493 |
| } |
494 |
| |
495 |
1894
| if (config.getBooleanAttribute(CACHE, true)) {
|
496 |
1894
| cache = getDatabase().getDocumentCache();
|
497 |
| } |
498 |
| |
499 |
| |
500 |
1894
| Configuration filerConfig = config.getChild(FILER);
|
501 |
1894
| if (filerConfig != null) {
|
502 |
1281
| if (log.isTraceEnabled()) {
|
503 |
0
| log.trace(localDebugHeader + "Have filer config...");
|
504 |
| } |
505 |
| |
506 |
| |
507 |
1281
| Configuration symConfig = config.getChild(SYMBOLS);
|
508 |
1281
| if (symConfig != null) {
|
509 |
123
| if (log.isTraceEnabled()) {
|
510 |
0
| log.trace(localDebugHeader +
|
511 |
| "Internal symbols=<" + TextWriter.toString(symConfig.getElement()) + ">"); |
512 |
| } |
513 |
| |
514 |
123
| try {
|
515 |
123
| symbols = new SymbolTable(symConfig.getElement(), true);
|
516 |
| } catch (Exception e) { |
517 |
0
| if (log.isWarnEnabled()) {
|
518 |
0
| log.warn(localDebugHeader + "Error building symbol table from internal symbols", e);
|
519 |
| } |
520 |
| } |
521 |
| } else { |
522 |
1158
| if (log.isTraceEnabled()) {
|
523 |
0
| log.trace(localDebugHeader + "No internal symbols...");
|
524 |
| } |
525 |
| |
526 |
1158
| try {
|
527 |
1158
| symbols = getSystemCollection().loadSymbols(this);
|
528 |
1158
| if (log.isDebugEnabled()) {
|
529 |
0
| log.debug(localDebugHeader + "Loaded symbols=<" +
|
530 |
| TextWriter.toString(symbols.streamToXML(new DocumentImpl())) + ">"); |
531 |
| } |
532 |
| } catch (Exception e) { |
533 |
0
| if (log.isWarnEnabled()) {
|
534 |
0
| log.warn(localDebugHeader + "Error loading symbol table from system collection", e);
|
535 |
| } |
536 |
| } |
537 |
| } |
538 |
| |
539 |
1281
| String className = filerConfig.getAttribute(CLASS);
|
540 |
1281
| if (log.isDebugEnabled()) {
|
541 |
0
| log.debug(localDebugHeader + "Filer class=<" + className + ">");
|
542 |
| } |
543 |
1281
| try {
|
544 |
1281
| filer = (Filer) Class.forName(className).newInstance();
|
545 |
1281
| filer.setLocation(getCollectionRoot(), getName());
|
546 |
1281
| filer.setConfig(filerConfig);
|
547 |
1281
| if (!filer.exists()) {
|
548 |
1043
| filer.create();
|
549 |
| } |
550 |
1281
| filer.open();
|
551 |
| } catch (Exception e) { |
552 |
0
| if (log.isWarnEnabled()) {
|
553 |
0
| log.warn("Filer '" + className + "' is not available", e);
|
554 |
| } |
555 |
| } |
556 |
| |
557 |
| |
558 |
1281
| try {
|
559 |
1281
| indexManager = new IndexManager(this, getDatabase().getTimer());
|
560 |
1281
| Configuration idxConfig = config.getChild(INDEXES, true);
|
561 |
1281
| indexManager.setConfig(idxConfig);
|
562 |
| } catch (Exception e) { |
563 |
0
| if (log.isWarnEnabled()) {
|
564 |
0
| log.warn("Failed to initialize indexer", e);
|
565 |
| } |
566 |
| } |
567 |
| } |
568 |
| |
569 |
| |
570 |
1894
| super.setConfig(config);
|
571 |
| |
572 |
| |
573 |
1894
| DBObserver.getInstance().setCollectionConfig(this, config);
|
574 |
| } |
575 |
| |
576 |
| |
577 |
| |
578 |
| |
579 |
1062
| public final Collection createCollection(String path, Configuration config) throws DBException {
|
580 |
1062
| Collection col = super.createCollection(path, config);
|
581 |
1036
| getDatabase().flushConfig();
|
582 |
1036
| return col;
|
583 |
| } |
584 |
| |
585 |
| |
586 |
| |
587 |
| |
588 |
1558
| public final boolean dropCollection(Collection collection) throws DBException {
|
589 |
1558
| boolean success = super.dropCollection(collection);
|
590 |
1533
| getDatabase().flushConfig();
|
591 |
1533
| return success;
|
592 |
| } |
593 |
| |
594 |
| |
595 |
| |
596 |
| |
597 |
| |
598 |
| |
599 |
| |
600 |
| |
601 |
119863
| public Database getDatabase() {
|
602 |
119863
| return parent.getDatabase();
|
603 |
| } |
604 |
| |
605 |
| |
606 |
| |
607 |
| |
608 |
| |
609 |
| |
610 |
| |
611 |
| |
612 |
1533
| public final Collection getParentCollection() throws DBException {
|
613 |
1533
| return parent;
|
614 |
| } |
615 |
| |
616 |
| |
617 |
| |
618 |
| |
619 |
| |
620 |
| |
621 |
| |
622 |
3135
| public SystemCollection getSystemCollection() {
|
623 |
3135
| return getDatabase().getSystemCollection();
|
624 |
| } |
625 |
| |
626 |
| |
627 |
| |
628 |
| |
629 |
| |
630 |
| |
631 |
| |
632 |
17768
| private MetaSystemCollection getMetaSystemCollection() {
|
633 |
17768
| return getDatabase().getMetaSystemCollection();
|
634 |
| } |
635 |
| |
636 |
6293
| public final String getName() {
|
637 |
6294
| return name;
|
638 |
| } |
639 |
| |
640 |
| |
641 |
| |
642 |
| |
643 |
| |
644 |
| |
645 |
| |
646 |
| |
647 |
92771
| public final String getCanonicalName() {
|
648 |
92771
| return canonicalName;
|
649 |
| } |
650 |
| |
651 |
| |
652 |
| |
653 |
| |
654 |
| |
655 |
| |
656 |
| |
657 |
| |
658 |
| |
659 |
| |
660 |
109797
| public final String getCanonicalDocumentName(Key key) {
|
661 |
109797
| return getCanonicalDocumentName(key.toString());
|
662 |
| } |
663 |
| |
664 |
| |
665 |
| |
666 |
| |
667 |
| |
668 |
| |
669 |
| |
670 |
| |
671 |
120031
| public final String getCanonicalDocumentName(String key) {
|
672 |
120031
| return canonicalName + '/' + key;
|
673 |
| } |
674 |
| |
675 |
| |
676 |
| |
677 |
| |
678 |
4335
| public final File getCollectionRoot() {
|
679 |
4335
| return collectionRoot;
|
680 |
| } |
681 |
| |
682 |
| |
683 |
| |
684 |
| |
685 |
| |
686 |
| |
687 |
| |
688 |
17015
| public final SymbolTable getSymbols() {
|
689 |
17015
| return symbols;
|
690 |
| } |
691 |
| |
692 |
| |
693 |
| |
694 |
| |
695 |
| |
696 |
| |
697 |
| |
698 |
910
| public final Filer getFiler() {
|
699 |
910
| return filer;
|
700 |
| } |
701 |
| |
702 |
| |
703 |
| |
704 |
| |
705 |
| |
706 |
| |
707 |
| |
708 |
372
| public QueryEngine getQueryEngine() throws DBException {
|
709 |
372
| return getDatabase().getQueryEngine();
|
710 |
| } |
711 |
| |
712 |
| |
713 |
| |
714 |
| |
715 |
| |
716 |
| |
717 |
| |
718 |
| |
719 |
| |
720 |
| |
721 |
1497
| public final IndexManager getIndexManager() throws DBException {
|
722 |
1497
| checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
|
723 |
1497
| return indexManager;
|
724 |
| } |
725 |
| |
726 |
| |
727 |
| |
728 |
| |
729 |
| |
730 |
| |
731 |
| |
732 |
| |
733 |
66
| public final Indexer getIndexer(String name) throws DBException {
|
734 |
66
| checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
|
735 |
66
| return indexManager.get(name);
|
736 |
| } |
737 |
| |
738 |
| |
739 |
| |
740 |
| |
741 |
| |
742 |
| |
743 |
| |
744 |
| |
745 |
15
| public final String[] listIndexers() throws DBException {
|
746 |
15
| checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
|
747 |
15
| return indexManager.list();
|
748 |
| } |
749 |
| |
750 |
| |
751 |
| |
752 |
| |
753 |
| |
754 |
| |
755 |
| |
756 |
| |
757 |
| |
758 |
154
| public final Indexer createIndexer(Configuration config) throws DBException {
|
759 |
154
| checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
|
760 |
154
| Indexer idx = indexManager.create(config);
|
761 |
144
| getDatabase().flushConfig();
|
762 |
144
| return idx;
|
763 |
| } |
764 |
| |
765 |
| |
766 |
| |
767 |
| |
768 |
| |
769 |
| |
770 |
| |
771 |
| |
772 |
| |
773 |
66
| public final boolean dropIndexer(Indexer index) throws DBException {
|
774 |
66
| checkFiler(FaultCodes.COL_NO_INDEXMANAGER);
|
775 |
| |
776 |
66
| if (index == null) {
|
777 |
8
| throw new DBException(FaultCodes.IDX_INDEX_NOT_FOUND,
|
778 |
| "Index value is null"); |
779 |
| } |
780 |
| |
781 |
58
| boolean success = indexManager.drop(index.getName());
|
782 |
58
| getDatabase().flushConfig();
|
783 |
58
| return success;
|
784 |
| } |
785 |
| |
786 |
| |
787 |
| |
788 |
| |
789 |
10216
| private Record writeRecord(Key key, boolean isDocument, byte[] bytes) throws DBException {
|
790 |
| |
791 |
10216
| Value value;
|
792 |
10216
| if (inlineMetaService == null) {
|
793 |
8233
| value = new Value(bytes);
|
794 |
| } else { |
795 |
1983
| InlineMetaMap map = inlineMetaService.getEmptyMap();
|
796 |
1983
| if (isDocument) {
|
797 |
1963
| map.put("type", ResourceTypeReader.XML);
|
798 |
| } else { |
799 |
20
| map.put("type", ResourceTypeReader.BINARY);
|
800 |
| } |
801 |
1983
| value = inlineMetaService.createValue(map, bytes, 0, bytes.length);
|
802 |
| } |
803 |
| |
804 |
10216
| return filer.writeRecord(key, value);
|
805 |
| } |
806 |
| |
807 |
| |
808 |
| |
809 |
| |
810 |
| |
811 |
| |
812 |
| |
813 |
13
| public final Key createNewOID() {
|
814 |
13
| long ct = System.currentTimeMillis();
|
815 |
13
| synchronized (oidMutex) {
|
816 |
13
| if (ct <= documentId) {
|
817 |
0
| ct = documentId + 1;
|
818 |
| } |
819 |
13
| documentId = ct;
|
820 |
| } |
821 |
| |
822 |
13
| StringBuffer sb = new StringBuffer(oidTemplate);
|
823 |
13
| String document = Long.toString(documentId, 16);
|
824 |
13
| sb.insert(32 - document.length(), document);
|
825 |
13
| sb.setLength(32);
|
826 |
13
| return new Key(sb.toString());
|
827 |
| } |
828 |
| |
829 |
| |
830 |
| |
831 |
| |
832 |
| |
833 |
| |
834 |
| |
835 |
| |
836 |
| |
837 |
| |
838 |
| |
839 |
| |
840 |
| |
841 |
| |
842 |
62344
| public final Entry getEntry(Object id) throws DBException {
|
843 |
| |
844 |
| |
845 |
62344
| if (id == null || filer == null) {
|
846 |
4
| return null;
|
847 |
| } |
848 |
| |
849 |
62340
| String localDebugHeader = null;
|
850 |
62340
| if (log.isTraceEnabled()) {
|
851 |
0
| localDebugHeader = debugHeader() + "getEntry: id=<" + id + ">: ";
|
852 |
0
| log.trace(localDebugHeader);
|
853 |
| } |
854 |
| |
855 |
62340
| checkFiler(FaultCodes.COL_NO_FILER);
|
856 |
| |
857 |
62340
| Key key = getIdentityKey(createNewKey(id));
|
858 |
62340
| synchronized (key) {
|
859 |
| |
860 |
| |
861 |
| |
862 |
| |
863 |
62340
| if (cache != null) {
|
864 |
62340
| Entry entry = cache.getEntry(this, key);
|
865 |
62340
| if (entry != null) {
|
866 |
18109
| if (log.isTraceEnabled()) {
|
867 |
0
| log.trace(localDebugHeader + "Returning cached: " + entry.getValue());
|
868 |
| } |
869 |
| |
870 |
18109
| return entry;
|
871 |
| } |
872 |
| } |
873 |
| |
874 |
44231
| Record record = filer.readRecord(key);
|
875 |
44231
| if (record == null) {
|
876 |
8998
| return null;
|
877 |
| } |
878 |
| |
879 |
35233
| Value value;
|
880 |
35233
| boolean isDocument;
|
881 |
35233
| if (inlineMetaService == null) {
|
882 |
781
| value = record.getValue();
|
883 |
781
| isDocument = true;
|
884 |
| |
885 |
781
| if (log.isTraceEnabled()) {
|
886 |
0
| log.trace(localDebugHeader + "Type is not available, Length=" + value.getLength());
|
887 |
| } |
888 |
| } else { |
889 |
34452
| InlineMetaService.DatabaseEntry databaseEntry = inlineMetaService.readDatabaseEntry(record.getValue());
|
890 |
34452
| Object type = databaseEntry.map.get("type");
|
891 |
34452
| value = databaseEntry.value;
|
892 |
34452
| isDocument = type.equals(ResourceTypeReader.XML);
|
893 |
| |
894 |
34452
| if (log.isTraceEnabled()) {
|
895 |
0
| log.trace(localDebugHeader + "Type=" + type + ", Length=" + value.getLength());
|
896 |
| } |
897 |
| } |
898 |
| |
899 |
35233
| Map entryMeta = Entry.createMetaMap(record);
|
900 |
35233
| if (isDocument) {
|
901 |
35233
| Document document;
|
902 |
35233
| if (compressed) {
|
903 |
21240
| document = new DocumentImpl(value.getData(), symbols, new NodeSource(this, key));
|
904 |
21240
| if (log.isTraceEnabled()) {
|
905 |
0
| log.trace(localDebugHeader +
|
906 |
| "Compressed XML document=<" + TextWriter.toString(document) + ">"); |
907 |
| } |
908 |
| } else { |
909 |
| |
910 |
13993
| document = parseDocument(key, value.toString());
|
911 |
13993
| if (log.isTraceEnabled()) {
|
912 |
0
| log.trace(localDebugHeader +
|
913 |
| "Uncompressed XML document=<" + TextWriter.toString(document) + ">"); |
914 |
| } |
915 |
| } |
916 |
| |
917 |
| |
918 |
35233
| flushSymbolTable();
|
919 |
| |
920 |
35233
| if (cache != null) {
|
921 |
35233
| cache.putEntry(this, key, Entry.DOCUMENT, value, entryMeta);
|
922 |
| } |
923 |
| |
924 |
35233
| DBObserver.getInstance().loadDocument(this, record, document);
|
925 |
35233
| return new Entry(key, document, entryMeta);
|
926 |
| } else { |
927 |
0
| if (log.isTraceEnabled()) {
|
928 |
0
| log.trace(localDebugHeader + "Binary document");
|
929 |
| } |
930 |
| |
931 |
0
| if (cache != null) {
|
932 |
0
| cache.putEntry(this, key, Entry.BINARY, value, entryMeta);
|
933 |
| } |
934 |
| |
935 |
0
| return new Entry(key, value.getData(), entryMeta);
|
936 |
| } |
937 |
| } |
938 |
| } |
939 |
| |
940 |
| |
941 |
| |
942 |
| |
943 |
| |
944 |
| |
945 |
| |
946 |
| |
947 |
6429
| public final Document getDocument(Object key) throws DBException {
|
948 |
6429
| if (log.isDebugEnabled()) {
|
949 |
0
| log.debug(debugHeader() + "Get document: " + key);
|
950 |
| } |
951 |
| |
952 |
6429
| Entry entry = getEntry(key);
|
953 |
6429
| if (entry == null) {
|
954 |
3515
| return null;
|
955 |
| } |
956 |
| |
957 |
2914
| if (entry.getEntryType() != Entry.DOCUMENT) {
|
958 |
0
| throw new DBException(FaultCodes.COL_INVALID_RESULT,
|
959 |
| "Resource '" + key + "' in collection '" + |
960 |
| getCanonicalName() + "' is not a document"); |
961 |
| } |
962 |
| |
963 |
2914
| return (Document) entry.getValue();
|
964 |
| } |
965 |
| |
966 |
| |
967 |
| |
968 |
| |
969 |
| |
970 |
| |
971 |
| |
972 |
| |
973 |
| |
974 |
| |
975 |
6162
| public final XMLSerializable getObject(Object key) throws DBException {
|
976 |
6162
| if (log.isDebugEnabled()) {
|
977 |
0
| log.debug(debugHeader() + "Get object: " + key);
|
978 |
| } |
979 |
| |
980 |
6162
| Document doc = getDocument(key);
|
981 |
6162
| if (doc != null) {
|
982 |
2658
| String className = null;
|
983 |
2658
| NodeList childNodes = doc.getChildNodes();
|
984 |
2658
| int size = childNodes.getLength();
|
985 |
2658
| for (int i = 0; i < size; i++) {
|
986 |
2658
| Node n = childNodes.item(i);
|
987 |
2658
| if (n.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE && n.getNodeName().equals(CLASSNAME)) {
|
988 |
2658
| className = n.getNodeValue().trim();
|
989 |
2658
| break;
|
990 |
| } |
991 |
| } |
992 |
| |
993 |
2658
| if (className != null) {
|
994 |
2658
| try {
|
995 |
2658
| XMLSerializable obj = (XMLSerializable) Class.forName(className).newInstance();
|
996 |
2658
| obj.streamFromXML(doc.getDocumentElement());
|
997 |
2658
| return obj;
|
998 |
| } catch (Exception e) { |
999 |
0
| if (log.isWarnEnabled()) {
|
1000 |
0
| log.warn("ignored exception", e);
|
1001 |
| } |
1002 |
| } |
1003 |
| } |
1004 |
| } |
1005 |
| |
1006 |
3504
| return null;
|
1007 |
| } |
1008 |
| |
1009 |
| |
1010 |
| |
1011 |
| |
1012 |
| |
1013 |
| |
1014 |
| |
1015 |
| |
1016 |
| |
1017 |
| |
1018 |
| |
1019 |
| |
1020 |
| |
1021 |
4
| public final byte[] getBinary(Object key) throws DBException {
|
1022 |
4
| if (log.isTraceEnabled()) {
|
1023 |
0
| log.trace(debugHeader() + "Get binary: " + key);
|
1024 |
| } |
1025 |
| |
1026 |
4
| if (inlineMetaService == null) {
|
1027 |
0
| throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
|
1028 |
| "Collection '" + getCanonicalName() + |
1029 |
| "' has no binary resources (inline metadata is not enabled)"); |
1030 |
| } |
1031 |
| |
1032 |
4
| Entry entry = getEntry(key);
|
1033 |
4
| if (entry == null) {
|
1034 |
1
| return null;
|
1035 |
| } |
1036 |
| |
1037 |
3
| if (entry.getEntryType() != Entry.BINARY) {
|
1038 |
0
| throw new DBException(FaultCodes.COL_INVALID_RESULT,
|
1039 |
| "Resource '" + key + "' in collection '" + |
1040 |
| getCanonicalName() + "' is not a binary resource"); |
1041 |
| } |
1042 |
| |
1043 |
3
| return (byte[]) entry.getValue();
|
1044 |
| } |
1045 |
| |
1046 |
| |
1047 |
| |
1048 |
| |
1049 |
| |
1050 |
| |
1051 |
| |
1052 |
| |
1053 |
1
| public final Key insertDocument(Document document) throws DBException {
|
1054 |
1
| return insertDocument(null, document);
|
1055 |
| } |
1056 |
| |
1057 |
| |
1058 |
| |
1059 |
| |
1060 |
| |
1061 |
| |
1062 |
| |
1063 |
| |
1064 |
| |
1065 |
309
| public final Key insertDocument(Object docKey, Document document) throws DBException {
|
1066 |
309
| Key key = createNewKey(docKey);
|
1067 |
309
| if (log.isInfoEnabled()) {
|
1068 |
2
| log.info(debugHeader() + "Insert document: " + key);
|
1069 |
| } |
1070 |
309
| putDocument(key, document, ACTION_INSERT);
|
1071 |
| |
1072 |
| |
1073 |
304
| updateCollectionMeta();
|
1074 |
304
| return key;
|
1075 |
| } |
1076 |
| |
1077 |
| |
1078 |
| |
1079 |
| |
1080 |
| |
1081 |
| |
1082 |
| |
1083 |
| |
1084 |
| |
1085 |
| |
1086 |
0
| public final Key insertObject(XMLSerializable obj) throws DBException {
|
1087 |
0
| return insertObject(null, obj);
|
1088 |
| } |
1089 |
| |
1090 |
| |
1091 |
| |
1092 |
| |
1093 |
| |
1094 |
| |
1095 |
| |
1096 |
| |
1097 |
| |
1098 |
| |
1099 |
| |
1100 |
0
| public final Key insertObject(String objKey, XMLSerializable obj) throws DBException {
|
1101 |
0
| Key key = createNewKey(objKey);
|
1102 |
0
| if (log.isInfoEnabled()) {
|
1103 |
0
| log.info(debugHeader() + "Insert object: " + key);
|
1104 |
| } |
1105 |
0
| putObject(key, obj, ACTION_INSERT);
|
1106 |
| |
1107 |
| |
1108 |
0
| updateCollectionMeta();
|
1109 |
0
| return key;
|
1110 |
| } |
1111 |
| |
1112 |
| |
1113 |
| |
1114 |
| |
1115 |
| |
1116 |
| |
1117 |
| |
1118 |
| |
1119 |
| |
1120 |
| |
1121 |
| |
1122 |
| |
1123 |
| |
1124 |
0
| public Key insertBinary(byte[] bytes) throws DBException {
|
1125 |
0
| return insertBinary(null, bytes);
|
1126 |
| } |
1127 |
| |
1128 |
| |
1129 |
| |
1130 |
| |
1131 |
| |
1132 |
| |
1133 |
| |
1134 |
| |
1135 |
| |
1136 |
| |
1137 |
4
| public Key insertBinary(Object docKey, byte[] bytes) throws DBException {
|
1138 |
4
| if (inlineMetaService == null) {
|
1139 |
0
| throw new DBException(FaultCodes.COL_CANNOT_STORE,
|
1140 |
| "Cannot insert a binary resource in '" + getCanonicalName() + |
1141 |
| "' (inline-metadata is not enabled)"); |
1142 |
| } |
1143 |
| |
1144 |
4
| Key key = createNewKey(docKey);
|
1145 |
4
| if (log.isInfoEnabled()) {
|
1146 |
0
| log.info(debugHeader() + "Insert binary: " + key);
|
1147 |
| } |
1148 |
4
| putBinary(key, bytes, ACTION_INSERT);
|
1149 |
| |
1150 |
| |
1151 |
4
| updateCollectionMeta();
|
1152 |
4
| return key;
|
1153 |
| } |
1154 |
| |
1155 |
| |
1156 |
| |
1157 |
| |
1158 |
| |
1159 |
| |
1160 |
| |
1161 |
| |
1162 |
| |
1163 |
| |
1164 |
4020
| public final boolean setDocument(Object docKey, Document document) throws DBException {
|
1165 |
4020
| if (log.isInfoEnabled()) {
|
1166 |
971
| log.info(debugHeader() + "Set document " + docKey);
|
1167 |
| } |
1168 |
| |
1169 |
4020
| boolean res = putDocument(createNewKey(docKey), document, ACTION_STORE);
|
1170 |
4020
| if (res) {
|
1171 |
1636
| updateCollectionMeta();
|
1172 |
| } |
1173 |
| |
1174 |
4020
| return res;
|
1175 |
| } |
1176 |
| |
1177 |
| |
1178 |
| |
1179 |
| |
1180 |
| |
1181 |
| |
1182 |
| |
1183 |
| |
1184 |
| |
1185 |
| |
1186 |
5869
| public final void setObject(Object key, XMLSerializable obj) throws DBException {
|
1187 |
5869
| if (log.isInfoEnabled()) {
|
1188 |
1339
| log.info(debugHeader() + "Set object " + key);
|
1189 |
| } |
1190 |
5869
| putObject(createNewKey(key), obj, ACTION_STORE);
|
1191 |
| } |
1192 |
| |
1193 |
| |
1194 |
| |
1195 |
| |
1196 |
| |
1197 |
| |
1198 |
| |
1199 |
| |
1200 |
| |
1201 |
| |
1202 |
16
| public boolean setBinary(Object docKey, byte[] bytes) throws DBException {
|
1203 |
16
| if (inlineMetaService == null) {
|
1204 |
0
| throw new DBException(FaultCodes.COL_CANNOT_STORE,
|
1205 |
| "Cannot insert a binary resource in '" + getCanonicalName() + |
1206 |
| "' (inline-metadata is not enabled)"); |
1207 |
| } |
1208 |
| |
1209 |
16
| if (log.isInfoEnabled()) {
|
1210 |
4
| log.info(debugHeader() + "Set binary " + docKey);
|
1211 |
| } |
1212 |
| |
1213 |
16
| boolean res = putBinary(createNewKey(docKey), bytes, ACTION_STORE);
|
1214 |
16
| if (res) {
|
1215 |
13
| updateCollectionMeta();
|
1216 |
| } |
1217 |
| |
1218 |
16
| return res;
|
1219 |
| } |
1220 |
| |
1221 |
| |
1222 |
| |
1223 |
| |
1224 |
| |
1225 |
| |
1226 |
| |
1227 |
| |
1228 |
| |
1229 |
6
| public void updateDocument(Object docKey, Document document) throws DBException {
|
1230 |
6
| if (log.isInfoEnabled()) {
|
1231 |
2
| log.info(debugHeader() + "Update document: " + docKey);
|
1232 |
| } |
1233 |
6
| putDocument(createNewKey(docKey), document, ACTION_UPDATE);
|
1234 |
| |
1235 |
| |
1236 |
3
| updateCollectionMeta();
|
1237 |
| } |
1238 |
| |
1239 |
| |
1240 |
| |
1241 |
| |
1242 |
| |
1243 |
| |
1244 |
| |
1245 |
| |
1246 |
| |
1247 |
0
| public void updateBinary(Object docKey, byte[] bytes) throws DBException {
|
1248 |
0
| if (inlineMetaService == null) {
|
1249 |
0
| throw new DBException(FaultCodes.COL_CANNOT_STORE,
|
1250 |
| "Cannot insert a binary resource in '" + getCanonicalName() + |
1251 |
| "' (inline-metadata is not enabled)"); |
1252 |
| } |
1253 |
| |
1254 |
0
| if (log.isInfoEnabled()) {
|
1255 |
0
| log.info(debugHeader() + "Set binary " + docKey);
|
1256 |
| } |
1257 |
| |
1258 |
0
| putBinary(createNewKey(docKey), bytes, ACTION_UPDATE);
|
1259 |
0
| updateCollectionMeta();
|
1260 |
| } |
1261 |
| |
1262 |
| |
1263 |
| |
1264 |
| |
1265 |
| |
1266 |
| |
1267 |
| |
1268 |
| |
1269 |
| |
1270 |
| |
1271 |
| |
1272 |
| |
1273 |
| |
1274 |
| |
1275 |
| |
1276 |
| |
1277 |
| |
1278 |
| |
1279 |
| |
1280 |
10204
| private boolean putDocument(Key key, Document document, byte action) throws DBException {
|
1281 |
10204
| final String localDebugHeader = debugHeader() + "putDocument: docKey=<" + key + ">: ";
|
1282 |
10204
| if (log.isTraceEnabled()) {
|
1283 |
0
| log.trace(localDebugHeader + "document=<" + TextWriter.toString(document) + ">");
|
1284 |
| } |
1285 |
| |
1286 |
10204
| checkFiler(FaultCodes.COL_NO_FILER);
|
1287 |
| |
1288 |
10204
| if (document instanceof DBDocument) {
|
1289 |
| |
1290 |
9286
| DBDocument dbDoc = (DBDocument) document;
|
1291 |
9286
| if (dbDoc.getSource() == null) {
|
1292 |
7621
| dbDoc.setSource(new NodeSource(this, key));
|
1293 |
| } |
1294 |
| } |
1295 |
| |
1296 |
| |
1297 |
| |
1298 |
| |
1299 |
| |
1300 |
| |
1301 |
| |
1302 |
| |
1303 |
| |
1304 |
| |
1305 |
| |
1306 |
| |
1307 |
| |
1308 |
| |
1309 |
| |
1310 |
10204
| byte[] documentBytes;
|
1311 |
| |
1312 |
10204
| if (compressed) {
|
1313 |
| |
1314 |
7424
| documentBytes = DOMCompressor.compress(document, symbols);
|
1315 |
7424
| if (log.isTraceEnabled()) {
|
1316 |
0
| log.trace(localDebugHeader + "length=" + documentBytes.length);
|
1317 |
| } |
1318 |
| |
1319 |
| |
1320 |
| |
1321 |
| |
1322 |
7424
| document = new DocumentImpl(documentBytes, symbols, new NodeSource(this, key));
|
1323 |
| |
1324 |
7424
| if (log.isTraceEnabled()) {
|
1325 |
0
| log.trace(localDebugHeader + "packedDocument: length=" + documentBytes.length +
|
1326 |
| " document=<" + TextWriter.toString(document) + ">"); |
1327 |
| } |
1328 |
| } else { |
1329 |
| |
1330 |
2780
| String documentChars = TextWriter.toString(document);
|
1331 |
2780
| try {
|
1332 |
2780
| documentBytes = documentChars.getBytes("utf-8");
|
1333 |
| } catch (UnsupportedEncodingException e) { |
1334 |
| |
1335 |
0
| throw new DBException(FaultCodes.GEN_FATAL_ERROR,
|
1336 |
| "utf-8 encoding not supported", e); |
1337 |
| } |
1338 |
| |
1339 |
| |
1340 |
| |
1341 |
| |
1342 |
| |
1343 |
2780
| document = parseDocument(key, documentChars);
|
1344 |
| |
1345 |
2780
| if (log.isTraceEnabled()) {
|
1346 |
0
| log.trace(localDebugHeader + "utf8Document: length=" + documentBytes.length +
|
1347 |
| " document=<" + documentChars + ">"); |
1348 |
| } |
1349 |
| } |
1350 |
| |
1351 |
| |
1352 |
10204
| flushSymbolTable();
|
1353 |
| |
1354 |
10204
| key = getIdentityKey(key);
|
1355 |
10204
| Entry entry;
|
1356 |
10204
| synchronized (key) {
|
1357 |
| |
1358 |
10204
| entry = getEntry(key);
|
1359 |
| |
1360 |
10204
| if (action == ACTION_INSERT && entry != null) {
|
1361 |
5
| throw new DBException(FaultCodes.COL_DUPLICATE_RESOURCE);
|
1362 |
10199
| } else if (action == ACTION_UPDATE && entry == null) {
|
1363 |
3
| throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND);
|
1364 |
| } |
1365 |
| |
1366 |
10196
| if (entry != null && entry.getEntryType() == Entry.DOCUMENT) {
|
1367 |
4980
| indexManager.removeDocument(key, (Document) entry.getValue());
|
1368 |
| } |
1369 |
10196
| indexManager.addDocument(key, document);
|
1370 |
| |
1371 |
| |
1372 |
10196
| Record record = writeRecord(key, true, documentBytes);
|
1373 |
| |
1374 |
| |
1375 |
10196
| if (cache != null) {
|
1376 |
10196
| cache.putEntry(this, key, Entry.DOCUMENT,
|
1377 |
| new Value(documentBytes), Entry.createMetaMap(record)); |
1378 |
| } |
1379 |
| |
1380 |
| |
1381 |
10196
| updateDocumentMeta(record);
|
1382 |
| } |
1383 |
| |
1384 |
10196
| DBObserver.getInstance().putDocument(this, key, document, entry == null);
|
1385 |
10196
| return entry == null;
|
1386 |
| } |
1387 |
| |
1388 |
5869
| private boolean putObject(Key key, XMLSerializable obj, byte action) throws DBException {
|
1389 |
5869
| if (log.isTraceEnabled()) {
|
1390 |
0
| log.trace(debugHeader() + "putObject: key=<" + key + "> class=<" + obj.getClass().getName() + ">");
|
1391 |
| } |
1392 |
| |
1393 |
5869
| Document doc = new DocumentImpl();
|
1394 |
5869
| ProcessingInstruction pi = doc.createProcessingInstruction(CLASSNAME, obj.getClass().getName());
|
1395 |
5869
| doc.appendChild(pi);
|
1396 |
5869
| Element elem = obj.streamToXML(doc);
|
1397 |
5869
| doc.appendChild(elem);
|
1398 |
5869
| return putDocument(key, doc, action);
|
1399 |
| } |
1400 |
| |
1401 |
| |
1402 |
| |
1403 |
| |
1404 |
| |
1405 |
| |
1406 |
| |
1407 |
| |
1408 |
| |
1409 |
| |
1410 |
| |
1411 |
| |
1412 |
| |
1413 |
| |
1414 |
| |
1415 |
| |
1416 |
| |
1417 |
| |
1418 |
| |
1419 |
| |
1420 |
20
| private boolean putBinary(Key key, byte[] bytes, byte action) throws DBException {
|
1421 |
20
| Entry entry;
|
1422 |
| |
1423 |
20
| synchronized (getIdentityKey(key)) {
|
1424 |
20
| entry = getEntry(key);
|
1425 |
20
| if (action == ACTION_INSERT && entry != null) {
|
1426 |
0
| throw new DBException(FaultCodes.COL_DUPLICATE_RESOURCE,
|
1427 |
| "Error inserting binary resource '" + key + "' in '" + getCanonicalName() + |
1428 |
| "': key is already in database"); |
1429 |
20
| } else if (action == ACTION_UPDATE && entry == null) {
|
1430 |
0
| throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
|
1431 |
| "Error updating binary resource '" + key + "' in '" + getCanonicalName() + |
1432 |
| "': key does not exist in database"); |
1433 |
| } |
1434 |
| |
1435 |
20
| if (entry != null && entry.getEntryType() == Entry.DOCUMENT) {
|
1436 |
| |
1437 |
2
| indexManager.removeDocument(key, (Document) entry.getValue());
|
1438 |
| } |
1439 |
| |
1440 |
| |
1441 |
20
| Record record = writeRecord(key, false, bytes);
|
1442 |
| |
1443 |
20
| if (cache != null) {
|
1444 |
20
| cache.putEntry(this, key, Entry.BINARY, new Value(bytes), Entry.createMetaMap(record));
|
1445 |
| } |
1446 |
| |
1447 |
| |
1448 |
20
| updateDocumentMeta(record);
|
1449 |
| } |
1450 |
| |
1451 |
20
| return entry == null;
|
1452 |
| } |
1453 |
| |
1454 |
| |
1455 |
| |
1456 |
| |
1457 |
| |
1458 |
| |
1459 |
| |
1460 |
| |
1461 |
1959
| public final void remove(Object id) throws DBException {
|
1462 |
1959
| if (log.isInfoEnabled()) {
|
1463 |
556
| log.info(debugHeader() + "Remove " + id);
|
1464 |
| } |
1465 |
| |
1466 |
1959
| checkFiler(FaultCodes.COL_NO_FILER);
|
1467 |
| |
1468 |
1959
| Key objKey = getIdentityKey(createNewKey(id));
|
1469 |
1959
| synchronized (objKey) {
|
1470 |
1959
| Entry entry = getEntry(objKey);
|
1471 |
1959
| if (entry != null && entry.getEntryType() == Entry.DOCUMENT) {
|
1472 |
1718
| indexManager.removeDocument(objKey, (Document) entry.getValue());
|
1473 |
| } |
1474 |
| |
1475 |
1959
| if (cache != null) {
|
1476 |
1959
| cache.removeEntry(this, objKey);
|
1477 |
| } |
1478 |
| |
1479 |
1959
| if (!filer.deleteRecord(objKey)) {
|
1480 |
234
| throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
|
1481 |
| "Resource '" + objKey + "' does not exist in '" + getCanonicalName() + "'"); |
1482 |
| } |
1483 |
| |
1484 |
| |
1485 |
1725
| if (isMetaEnabled()) {
|
1486 |
1724
| getMetaSystemCollection().dropDocumentMeta(this, objKey.toString());
|
1487 |
| } |
1488 |
| } |
1489 |
| |
1490 |
| |
1491 |
1725
| updateCollectionMeta();
|
1492 |
| |
1493 |
1725
| DBObserver.getInstance().dropDocument(this, objKey);
|
1494 |
| } |
1495 |
| |
1496 |
| |
1497 |
| |
1498 |
| |
1499 |
| |
1500 |
| |
1501 |
| |
1502 |
| |
1503 |
| |
1504 |
17813
| public boolean isMetaEnabled() {
|
1505 |
17813
| return getDatabase().isMetaEnabled();
|
1506 |
| } |
1507 |
| |
1508 |
| |
1509 |
| |
1510 |
| |
1511 |
| |
1512 |
| |
1513 |
| |
1514 |
| |
1515 |
| |
1516 |
| |
1517 |
39
| public MetaData getCollectionMeta() throws DBException {
|
1518 |
39
| if (!isMetaEnabled()) {
|
1519 |
0
| if (log.isWarnEnabled()) {
|
1520 |
0
| log.warn("Meta information requested but not enabled in config!");
|
1521 |
| } |
1522 |
0
| return null;
|
1523 |
| } |
1524 |
| |
1525 |
39
| MetaSystemCollection metacol = getMetaSystemCollection();
|
1526 |
39
| MetaData meta = metacol.getCollectionMeta(this);
|
1527 |
39
| if (null == meta) {
|
1528 |
0
| long now = System.currentTimeMillis();
|
1529 |
0
| meta = new MetaData(MetaData.COLLECTION, getCanonicalName(), now, now);
|
1530 |
0
| metacol.setCollectionMeta(this, meta);
|
1531 |
| } |
1532 |
| |
1533 |
39
| return meta;
|
1534 |
| } |
1535 |
| |
1536 |
| |
1537 |
| |
1538 |
| |
1539 |
| |
1540 |
| |
1541 |
| |
1542 |
6
| public void setCollectionMeta(MetaData meta) throws DBException {
|
1543 |
6
| if (!isMetaEnabled()) {
|
1544 |
0
| if (log.isWarnEnabled()) {
|
1545 |
0
| log.warn("Meta information requested but not enabled in config!");
|
1546 |
| } |
1547 |
0
| return;
|
1548 |
| } |
1549 |
| |
1550 |
6
| if (null != meta) {
|
1551 |
6
| if (meta.getType() != MetaData.COLLECTION) {
|
1552 |
0
| throw new DBException(FaultCodes.GEN_UNKNOWN,
|
1553 |
| "Mismatch type of meta data for collection " + getCanonicalName()); |
1554 |
| } |
1555 |
| |
1556 |
6
| MetaSystemCollection metacol = getMetaSystemCollection();
|
1557 |
6
| MetaData current = metacol.getCollectionMeta(this);
|
1558 |
6
| current.copyDataFrom(meta);
|
1559 |
6
| metacol.setCollectionMeta(this, current);
|
1560 |
| } |
1561 |
| } |
1562 |
| |
1563 |
| |
1564 |
| |
1565 |
| |
1566 |
| |
1567 |
| |
1568 |
| |
1569 |
| |
1570 |
| |
1571 |
| |
1572 |
| |
1573 |
| |
1574 |
| |
1575 |
49
| public final Entry getEntryMeta(Object id) throws DBException {
|
1576 |
49
| if (id == null) {
|
1577 |
0
| return null;
|
1578 |
| } |
1579 |
| |
1580 |
49
| checkFiler(FaultCodes.COL_NO_FILER);
|
1581 |
| |
1582 |
49
| Key key = getIdentityKey(createNewKey(id));
|
1583 |
49
| synchronized (key) {
|
1584 |
| |
1585 |
| |
1586 |
| |
1587 |
| |
1588 |
49
| if (cache != null) {
|
1589 |
49
| Entry entry = cache.getEntryMeta(this, key);
|
1590 |
49
| if (entry != null) {
|
1591 |
49
| return entry;
|
1592 |
| } |
1593 |
| } |
1594 |
| |
1595 |
0
| Record record = filer.readRecord(key, true);
|
1596 |
0
| if (record == null) {
|
1597 |
0
| return null;
|
1598 |
| } |
1599 |
| |
1600 |
0
| Map entryMeta = Entry.createMetaMap(record);
|
1601 |
0
| return new Entry(key, entryMeta);
|
1602 |
| } |
1603 |
| } |
1604 |
| |
1605 |
| |
1606 |
| |
1607 |
| |
1608 |
| |
1609 |
| |
1610 |
| |
1611 |
| |
1612 |
| |
1613 |
37
| public MetaData getDocumentMeta(String id) throws DBException {
|
1614 |
37
| if (!isMetaEnabled()) {
|
1615 |
0
| if (log.isWarnEnabled()) {
|
1616 |
0
| log.warn("Meta information requested but not enabled in config!");
|
1617 |
| } |
1618 |
0
| return null;
|
1619 |
| } |
1620 |
| |
1621 |
37
| Key key = getIdentityKey(createNewKey(id));
|
1622 |
37
| synchronized (key) {
|
1623 |
37
| if (getEntryMeta(id) == null) {
|
1624 |
0
| throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
|
1625 |
| "Resource '" + id + "' does not exist in '" + getCanonicalName() + "'"); |
1626 |
| } |
1627 |
| |
1628 |
37
| MetaSystemCollection metacol = getMetaSystemCollection();
|
1629 |
37
| MetaData meta = metacol.getDocumentMeta(this, id);
|
1630 |
| |
1631 |
| |
1632 |
| |
1633 |
| |
1634 |
| |
1635 |
| |
1636 |
| |
1637 |
| |
1638 |
| |
1639 |
| |
1640 |
| |
1641 |
| |
1642 |
| |
1643 |
| |
1644 |
| |
1645 |
| |
1646 |
| |
1647 |
37
| long now = System.currentTimeMillis();
|
1648 |
37
| if (meta == null) {
|
1649 |
0
| meta = new MetaData(MetaData.DOCUMENT, getCanonicalDocumentName(id), now, now);
|
1650 |
0
| metacol.setDocumentMeta(this, id, meta);
|
1651 |
37
| } else if (!meta.hasContext()) {
|
1652 |
0
| meta.setContext(now, now);
|
1653 |
| } |
1654 |
| |
1655 |
37
| return meta;
|
1656 |
| } |
1657 |
| } |
1658 |
| |
1659 |
| |
1660 |
| |
1661 |
| |
1662 |
| |
1663 |
| |
1664 |
| |
1665 |
| |
1666 |
12
| public void setDocumentMeta(String id, MetaData meta) throws DBException {
|
1667 |
12
| if (!isMetaEnabled()) {
|
1668 |
0
| if (log.isWarnEnabled()) {
|
1669 |
0
| log.warn("Meta information requested but not enabled in config!");
|
1670 |
| } |
1671 |
0
| return;
|
1672 |
| } |
1673 |
| |
1674 |
12
| Key key = getIdentityKey(createNewKey(id));
|
1675 |
12
| synchronized (key) {
|
1676 |
12
| if (getEntryMeta(id) == null) {
|
1677 |
0
| throw new DBException(FaultCodes.COL_DOCUMENT_NOT_FOUND,
|
1678 |
| "Resource '" + id + "' does not exist in '" + getCanonicalName() + "'"); |
1679 |
| } |
1680 |
| |
1681 |
12
| if (meta != null) {
|
1682 |
12
| if (meta.getType() == MetaData.UNKNOWN || meta.getType() == MetaData.COLLECTION) {
|
1683 |
0
| throw new DBException(FaultCodes.GEN_UNKNOWN,
|
1684 |
| "Mismatch type of meta data for document " + getCanonicalDocumentName(id)); |
1685 |
| } |
1686 |
| |
1687 |
12
| if (log.isInfoEnabled()) {
|
1688 |
4
| log.info(debugHeader() + "Set document meta " + id);
|
1689 |
| } |
1690 |
12
| MetaSystemCollection metacol = getMetaSystemCollection();
|
1691 |
12
| MetaData current = metacol.getDocumentMeta(this, id);
|
1692 |
12
| current.copyDataFrom(meta);
|
1693 |
12
| metacol.setDocumentMeta(this, id, current);
|
1694 |
| } |
1695 |
| } |
1696 |
| } |
1697 |
| |
1698 |
| |
1699 |
| |
1700 |
| |
1701 |
4718
| protected void updateCollectionMeta() {
|
1702 |
| |
1703 |
4718
| if (isMetaEnabled()) {
|
1704 |
4711
| MetaSystemCollection metacol = getMetaSystemCollection();
|
1705 |
4711
| MetaData meta;
|
1706 |
4711
| try {
|
1707 |
4711
| meta = metacol.getCollectionMeta(this);
|
1708 |
| } catch (DBException e) { |
1709 |
| |
1710 |
| |
1711 |
0
| if (log.isWarnEnabled()) {
|
1712 |
0
| log.warn("Error fetching meta for collection '" + getCanonicalName() + "'", e);
|
1713 |
| } |
1714 |
0
| return;
|
1715 |
| } |
1716 |
| |
1717 |
4711
| if (log.isTraceEnabled()) {
|
1718 |
0
| log.trace(debugHeader() + "Updating modified time for collection");
|
1719 |
| } |
1720 |
4711
| long now = System.currentTimeMillis();
|
1721 |
4711
| if (null == meta) {
|
1722 |
1784
| meta = new MetaData(MetaData.COLLECTION, getCanonicalName(), now, now);
|
1723 |
2927
| } else if (!meta.hasContext()) {
|
1724 |
| |
1725 |
517
| meta.setContext(now, now);
|
1726 |
| } else { |
1727 |
| |
1728 |
2410
| meta.setContext(0, now);
|
1729 |
| } |
1730 |
| |
1731 |
4711
| try {
|
1732 |
4711
| metacol.setCollectionMeta(this, meta);
|
1733 |
| } catch (DBException e) { |
1734 |
0
| if (log.isWarnEnabled()) {
|
1735 |
0
| log.warn("Error setting meta for collection '" + getCanonicalName() + "'", e);
|
1736 |
| } |
1737 |
| } |
1738 |
| } |
1739 |
| } |
1740 |
| |
1741 |
| |
1742 |
| |
1743 |
| |
1744 |
| |
1745 |
| |
1746 |
| |
1747 |
10216
| protected void updateDocumentMeta(Record record) throws DBException {
|
1748 |
| |
1749 |
10216
| if (!isMetaEnabled()) {
|
1750 |
12
| return;
|
1751 |
| } |
1752 |
| |
1753 |
10204
| MetaSystemCollection metacol = getMetaSystemCollection();
|
1754 |
10204
| String id = record.getKey().toString();
|
1755 |
10204
| MetaData meta = metacol.getDocumentMeta(this, id);
|
1756 |
10204
| String path = getCanonicalDocumentName(id);
|
1757 |
| |
1758 |
10204
| if (log.isTraceEnabled()) {
|
1759 |
0
| log.trace(debugHeader() + "Updating modified time for document '" + id + "'");
|
1760 |
| } |
1761 |
| |
1762 |
10204
| long now = System.currentTimeMillis();
|
1763 |
| |
1764 |
| |
1765 |
10204
| Long time = (Long) record.getMetaData(Record.CREATED);
|
1766 |
10204
| long created = time != null ? time.longValue() : now;
|
1767 |
| |
1768 |
10204
| time = (Long) record.getMetaData(Record.MODIFIED);
|
1769 |
10204
| long modified = time != null ? time.longValue() : now;
|
1770 |
| |
1771 |
10204
| if (null == meta) {
|
1772 |
8221
| meta = new MetaData(MetaData.DOCUMENT, path, created, modified);
|
1773 |
1983
| } else if (!meta.hasContext()) {
|
1774 |
1948
| meta.setContext(created, modified);
|
1775 |
| } else { |
1776 |
35
| meta.setContext(0, modified);
|
1777 |
| } |
1778 |
| |
1779 |
10204
| metacol.setDocumentMeta(this, id, meta);
|
1780 |
| } |
1781 |
| |
1782 |
| |
1783 |
| |
1784 |
| |
1785 |
| |
1786 |
| |
1787 |
| |
1788 |
| |
1789 |
| |
1790 |
| |
1791 |
| |
1792 |
| |
1793 |
| |
1794 |
0
| public final Container getContainer(Object docKey) throws DBException {
|
1795 |
0
| Key key = createNewKey(docKey);
|
1796 |
0
| Document doc = getDocument(key);
|
1797 |
0
| return doc != null ? new ColContainer(key, doc) : null;
|
1798 |
| } |
1799 |
| |
1800 |
| |
1801 |
| |
1802 |
| |
1803 |
| |
1804 |
| |
1805 |
| |
1806 |
| |
1807 |
68
| public final long getDocumentCount() throws DBException {
|
1808 |
| |
1809 |
| |
1810 |
| |
1811 |
68
| return null == filer ? 0 : filer.getRecordCount();
|
1812 |
| } |
1813 |
| |
1814 |
| |
1815 |
| |
1816 |
| |
1817 |
| |
1818 |
| |
1819 |
| |
1820 |
| |
1821 |
0
| public final DocumentSet getDocumentSet() throws DBException {
|
1822 |
| |
1823 |
| |
1824 |
| |
1825 |
0
| return null == filer ? EMPTY_DOCUMENTSET : new ColDocumentSet(filer.getRecordSet());
|
1826 |
| } |
1827 |
| |
1828 |
| |
1829 |
| |
1830 |
| |
1831 |
| |
1832 |
| |
1833 |
| |
1834 |
| |
1835 |
30
| public final String[] listDocuments() throws DBException {
|
1836 |
| |
1837 |
| |
1838 |
| |
1839 |
30
| if (null == filer) {
|
1840 |
0
| return EMPTY_STRING_ARRAY;
|
1841 |
| } else { |
1842 |
| |
1843 |
| |
1844 |
| |
1845 |
30
| ArrayList temp = new ArrayList((int) filer.getRecordCount());
|
1846 |
| |
1847 |
30
| RecordSet set = filer.getRecordSet();
|
1848 |
30
| while (set.hasMoreRecords()) {
|
1849 |
220
| Key key = set.getNextKey();
|
1850 |
220
| temp.add(key.toString());
|
1851 |
| } |
1852 |
| |
1853 |
30
| return (String[]) temp.toArray(new String[temp.size()]);
|
1854 |
| } |
1855 |
| } |
1856 |
| |
1857 |
| |
1858 |
| |
1859 |
| |
1860 |
| |
1861 |
| |
1862 |
| |
1863 |
| |
1864 |
| |
1865 |
| |
1866 |
| |
1867 |
366
| public final NodeSet queryCollection(String style, String query, NamespaceMap nsMap) throws DBException {
|
1868 |
366
| if (log.isDebugEnabled()) {
|
1869 |
0
| log.debug(debugHeader() + "Query collection, query " + query);
|
1870 |
| } |
1871 |
| |
1872 |
| |
1873 |
| |
1874 |
| |
1875 |
366
| return null == filer ? EMPTY_NODESET : getQueryEngine().query(this, style, query, nsMap, null);
|
1876 |
| } |
1877 |
| |
1878 |
| |
1879 |
| |
1880 |
| |
1881 |
| |
1882 |
| |
1883 |
| |
1884 |
| |
1885 |
| |
1886 |
| |
1887 |
| |
1888 |
| |
1889 |
6
| public final NodeSet queryDocument(String style, String query, NamespaceMap nsMap, Object key) throws DBException {
|
1890 |
6
| if (log.isInfoEnabled()) {
|
1891 |
2
| log.info(debugHeader() + "Query document " + key + ", query: " + query);
|
1892 |
| } |
1893 |
| |
1894 |
6
| checkFiler(FaultCodes.QRY_STYLE_NOT_FOUND);
|
1895 |
6
| Key[] k;
|
1896 |
6
| if (key instanceof Key[]) {
|
1897 |
0
| k = (Key[]) key;
|
1898 |
| } else { |
1899 |
6
| k = new Key[]{createNewKey(key)};
|
1900 |
| } |
1901 |
6
| return getQueryEngine().query(this, style, query, nsMap, k);
|
1902 |
| } |
1903 |
| } |