001: /*
002: * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005:
006: package com.sun.portal.search.db;
007:
008: import com.sun.portal.search.soif.*;
009: import com.sun.portal.search.util.*;
010: import com.sun.portal.search.rdm.*;
011: import com.sun.portal.log.common.PortalLogger;
012:
013: import java.util.*;
014: import java.util.logging.Logger;
015: import java.util.logging.Level;
016:
017: /**
018: * SOIF Database API implementation.
019: *
020: * <p>- handles SOIF db i/o
021: * <p>- provides a template for similar, non-SOIF layers, eg, XML, etc.
022: * <p>- hides db implementation details (eg, db might not contain SOIF)
023: * <p>- hides the mechanics of P/NP data
024: */
025: public class SOIFDb extends PartitionedDb implements RDMDb {
026:
027: public static final String ENCODING = "UTF-8"; // XXX not being used consistently
028:
029: /**
030: * Added as an attribute to an input RD by dbs without their own
031: * index to indicate that the RD does not need reindexing. Ie, that
032: * the RD has not changed according to the definition of that db.
033: */
034: public static final String NOREINDEX = "__noreindex__";
035:
036: RDLastChangedList rdlist = new RDLastChangedList();
037:
038: /**
039: * retrieve RD from database, store into s, filtered by view
040: */
041: public SOIF fetch(SToken st, String url, Set view, int flags,
042: RDMTransaction t) throws RDMException {
043: return _fetch(st, url, view, flags, t);
044: }
045:
046: public SOIF fetch(SToken st, String url, int flags, RDMTransaction t)
047: throws RDMException {
048: // Do a fetch with a null view
049: return _fetch(st, url, null, flags, t); // fetch with a null view XXX virtual
050: }
051:
052: /**
053: * retrieve RD from database, store into s, filtered by view
054: */
055: private SOIF _fetch(SToken st, String url, Set view, int flags,
056: RDMTransaction t) throws RDMException {
057:
058: SOIF ons = null, ops = null;
059: SOIF result = null;
060: int rcode = 0;
061: Datum key;
062: Datum data;
063: boolean vdbViewAdded = false;
064:
065: if (view != null && !view.contains(st.getVirtualDBTagName())) {
066: view.add(st.getVirtualDBTagName());
067: vdbViewAdded = true;
068: }
069:
070: try {
071:
072: /**
073: * The RDMDb SOIF flags are not undserstood by the PartitionedDb api.
074: * This sets the SOIF flags locally and strips them out of the PartitionedDb flags.
075: */
076: int pflags = flags & 0xFF000000;
077: flags &= 0x00FFFFFF;
078:
079: if ((pflags & PONLY) != 0 && (pflags & NPONLY) != 0)
080: throw new RDMException("invalid flags");
081:
082: if ((pflags & PONLY) == 0) {
083: key = DbUtil.key_create(url);
084: data = new Datum();
085: rcode = fetch(st, key, data, flags, t);
086: if (rcode == 0)
087: ons = new SOIF(data.get_data(), ENCODING, view);
088: else if (rcode != RDMDb.DB_NOTFOUND)
089: throw new Exception(
090: "error when reading non-persistent RD ("
091: + rcode + ")");
092: }
093:
094: if ((pflags & NPONLY) == 0) {
095: key = DbUtil.persist_key_create(url);
096: data = new Datum();
097: rcode = fetch(st, key, data, flags, t);
098: if (rcode == 0)
099: ops = new SOIF(data.get_data(), ENCODING, view);
100: else if (rcode != RDMDb.DB_NOTFOUND)
101: throw new Exception(
102: "error when reading non-persistent RD ("
103: + rcode + ")");
104: }
105:
106: // do the persistent merge
107: if (ons != null) {
108: if (ops != null) {
109: ons.merge(ops);
110: }
111: result = ons;
112: } else
113: result = ops;
114: result = RDMSecurityManager.getInstance()
115: .filter(st, result);
116: if (result != null && vdbViewAdded) {
117: result.remove(st.getVirtualDBTagName());
118: }
119: return result;
120: } catch (Exception e) {
121: throw new RDMException(e);
122: }
123:
124: }
125:
126: /**
127: * insert/replace RD in database, filtered by view
128: */
129: public void store(SToken st, SOIF insoif, Set view, int flags,
130: RDMTransaction t) throws RDMException {
131: _store(st, insoif, view, flags, t);
132: }
133:
134: public void store(SToken st, SOIF insoif, int flags,
135: RDMTransaction t) throws RDMException {
136: // Do a store with a null view
137: _store(st, insoif, null, flags, t);
138: }
139:
140: /**
141: * insert/replace RD in database, filtered by view (XXX view is ignored on insert at the moment)
142: */
143: private void _store(SToken st, SOIF insoif, Set view, int flags,
144: RDMTransaction t) throws RDMException {
145: int rcode = 0;
146: boolean is_persistent = false;
147: Datum key = null;
148: Datum data = null;
149: SOIF ops = null, ons = null, nps = null, nns = null;
150: RDLastChanged rdlc = new RDLastChanged();
151: String url = insoif.getURL();
152:
153: try {
154:
155: int pflags = flags & 0xFF000000;
156: flags &= 0x00FFFFFF;
157:
158: if ((pflags & PONLY) != 0 && (pflags & NPONLY) != 0)
159: throw new Exception("invalid flags");
160:
161: /*// must set exactly one of P and NP for store
162: // XXX we probably don't need the NPONLY flag
163: if ((pflags & PONLY) != 0) {
164: is_persistent = true;
165: } else if ((pflags & NPONLY) != 0) {
166: is_persistent = false;
167: } else
168: throw new Exception("invalid flags");
169: */
170:
171: is_persistent = ((pflags & PONLY) != 0); // XXX agrees with rdsubmit semantics?
172:
173: // fetch old P and NP data
174: ops = fetch(st, url, flags | PONLY, t);
175: ons = fetch(st, url, flags | NPONLY, t);
176:
177: // set new P and NP data
178: if (is_persistent) {
179: nps = insoif;
180: nns = ons;
181: } else {
182: nps = ops;
183: nns = insoif;
184: }
185:
186: if (nps == null)
187: nps = new SOIF(insoif.getSchemaName(), url);
188:
189: // Call plugins here (may not need P and NP in general
190: // - that will be fixed with a better all-in-one representation)
191: if ((pflags & NOSTATS) == 0) {
192: // calculate rd-last-changed
193: RDLastChangedPlugin.stamp_rd(rdlc, rdlist, ops, ons,
194: nps, nns, is_persistent);
195: // if NP was modified, update P (rd-last-modified) to the db
196: // XXX this should all be done inside the rd-last-changed plugin
197: if (!is_persistent && rdlc.update_flag) {
198: key = DbUtil.persist_key_create(url);
199: data = new Datum(nps.toByteArray(ENCODING));
200: store(st, key, data, 0, t);
201: }
202: }
203:
204: // store the RD
205: key = is_persistent ? DbUtil.persist_key_create(url)
206: : DbUtil.key_create(url);
207: //data = new Datum(insoif.toByteArray(ENCODING, view)); XXX view will clobber rating, etc, attrs - need to augment
208: data = new Datum(insoif.toByteArray(ENCODING));
209: store(st, key, data, 0, t);
210:
211: // merge insoif for reindexing
212: if ((pflags & NOMERGE) == 0) {
213: if (!is_persistent)
214: // NP only store - always reindex
215: insoif.merge(nps);
216: else {
217: // P only store
218: if (nns != null) {
219: // we have NP data - need to reindex
220: insoif.absorb(nns);
221: } else {
222: // no NP data - don't reindex
223: // XXX we should index P only and we should check for any changes and update rd-last-modified
224: insoif.insert(NOREINDEX, "true");
225: }
226: }
227: }
228:
229: } catch (Exception e) {
230: throw new RDMException(e);
231: }
232:
233: }
234:
235: /** delete RD from database */
236: // XXX delete with View???
237: public void delete(SToken st, SOIF s, int flags, RDMTransaction t)
238: throws RDMException {
239: int rcode = 0;
240: Datum key = null;
241: SOIF ops = null, ons = null, nps = null, nns = null;
242: String url = s.getURL();
243:
244: try {
245:
246: int pflags = flags & 0xFF000000;
247: flags &= 0x00FFFFFF;
248:
249: /**
250: * flags
251: * none - delete P and NP
252: * PONLY - delete only P
253: * NPONLY - delete only NP
254: */
255: if ((pflags & PONLY) != 0 && (pflags & NPONLY) != 0)
256: throw new Exception("invalid flags");
257:
258: // fetch old P and NP data
259: ops = fetch(st, url, flags | PONLY, t);
260: ons = fetch(st, url, flags | NPONLY, t);
261:
262: // Delete db entries
263: if ((pflags & NPONLY) != 0)
264: nps = ops;
265: else {
266: nps = null;
267: key = DbUtil.persist_key_create(url);
268: delete(st, key, 0, t);
269: }
270:
271: if ((pflags & PONLY) != 0)
272: nns = ons;
273: else {
274: nns = null;
275: key = DbUtil.key_create(url);
276: delete(st, key, 0, t);
277: }
278:
279: // setup for reindexing
280: if ((pflags & PONLY) != 0) {
281: if (ons != null) {
282: // need to reindex - remove any P attrs and replace with NP attrs
283: s.clear();
284: s.merge(ons);
285: } else
286: s.insert(NOREINDEX, "true");
287: }
288:
289: } catch (Exception e) {
290: throw new RDMException(e);
291: }
292:
293: }
294:
295: /**
296: * update an RD based on fields from insoif and/or view
297: */
298: public void update(SToken st, SOIF insoif, Set view, int flags,
299: RDMTransaction t) throws RDMException {
300:
301: int i, j, k;
302: AVPair avp;
303: SOIF oldsoif = null;
304:
305: // retrieve existing RD
306: oldsoif = fetch(st, insoif.getURL(), flags, t);
307: if (oldsoif == null)
308: oldsoif = new SOIF(insoif.getSchemaName(), insoif.getURL());
309:
310: if (view != null) {
311: // If there is a view, remove all non-view attrs from insoif
312: for (Iterator it = insoif.getAttributes().iterator(); it
313: .hasNext();) {
314: String at = (String) it.next();
315: if (!view.contains(at))
316: it.remove();
317: }
318: }
319:
320: // add to insoif all non-view attrs from oldsoif
321: insoif.absorb(oldsoif);
322:
323: // XXX Handle comment/rating - should be in discussion code, not here
324: //if (is_persistent) {
325: // handle_rating(cdbm, newsoif);
326: //}
327:
328: // Finally, store newsoif
329: // XXX logic has changed - could be called with both P and NP set
330: // - need to check behaviour of cdbm.sore in this case
331: /* if (is_persistent)
332: flags = RDMDb.PONLY;
333: else
334: flags = RDMDb.NPONLY;*/
335:
336: // disallow store here so that update semantics can be used for index only
337: if ((flags & NOSTORE) == 0)
338: _store(st, insoif, null, flags, t);
339:
340: // insoif will have been set up for reindexing by store()
341:
342: }
343:
344: /** check if RD is in database (slow) */
345: public boolean check(SToken st, String url, int flags,
346: RDMTransaction t) throws RDMException {
347: throw new RDMException("not implemented");
348: }
349:
350: /** Stats node */
351: class ClassStats {
352: String n_name;
353: int n_doc_count;
354: String n_idx_batch_list;
355: }
356:
357: void init(String rootdir, int flags) throws RDMException {
358: super .init(rootdir, flags);
359: try {
360: RDLastChangedPlugin.load_alert_config(rdlist, SearchConfig
361: .getValue(SearchConfig.SERVER_ROOT));
362: } catch (Exception e) {
363: SearchLogger.getLogger().log(Level.WARNING,
364: "PSSH_CSPSB0065", e);
365: }
366: }
367:
368: public RDMResultSet search(SToken st, String qry, int numHits,
369: Set view, String sortOrder, RDMTransaction t)
370: throws RDMException {
371: throw new RDMException("not implemented");
372: }
373:
374: public void delete(SToken st, SOIF s, Set view, int flags,
375: RDMTransaction t) throws RDMException {
376: throw new RDMException("not implemented");
377: }
378:
379: public void open(SToken st, String rootdir, String dbname, int rw,
380: int mode, RDMTransaction t) throws RDMException {
381: throw new RDMException("not implemented");
382: }
383:
384: public void close(SToken st, RDMTransaction t) throws RDMException {
385: }
386:
387: // inherited public int count(SToken st, RDMTransaction t) throws RDMException { throw new RDMException("not implemented"); }
388: // inherited public void optimize(SToken st) throws RDMException { throw new RDMException("not implemented"); }
389: public void recover(SToken st, String dbhome, boolean fatal)
390: throws RDMException {
391: throw new RDMException("not implemented");
392: }
393:
394: public void indexBatch(SToken st) throws RDMException {
395: throw new RDMException("not implemented");
396: }
397:
398: //public int purge(SToken st, RDMTransaction t) throws RDMException { throw new RDMException("not implemented"); }
399:
400: }
|