Revision 471
Added by bojilova about 24 years ago
src/edu/ucsb/nceas/metacat/DBSAXHandler.java | ||
---|---|---|
16 | 16 |
|
17 | 17 |
import java.sql.*; |
18 | 18 |
import java.util.Stack; |
19 |
import java.util.Vector; |
|
20 |
import java.util.Enumeration; |
|
19 | 21 |
import java.util.EmptyStackException; |
20 | 22 |
|
21 | 23 |
import org.xml.sax.Attributes; |
... | ... | |
30 | 32 |
* call when processing the XML stream and generating events |
31 | 33 |
*/ |
32 | 34 |
public class DBSAXHandler extends DefaultHandler |
33 |
implements LexicalHandler, DeclHandler { |
|
35 |
implements LexicalHandler, DeclHandler, Runnable {
|
|
34 | 36 |
|
35 | 37 |
private boolean atFirstElement; |
36 | 38 |
private boolean processingDTD; |
... | ... | |
38 | 40 |
private String doctype; |
39 | 41 |
private String systemid; |
40 | 42 |
private boolean stackCreated = false; |
41 |
private Stack nodeStack; |
|
42 |
private Connection conn = null; |
|
43 |
private Stack nodeStack; |
|
44 |
private Vector nodeIndex; |
|
45 |
private Connection conn = null; |
|
43 | 46 |
private DocumentImpl currentDocument; |
44 | 47 |
private DBSAXNode rootNode; |
45 |
private String action = null; |
|
46 |
private String docid = null; |
|
47 |
private String user = null; |
|
48 |
private String action = null; |
|
49 |
private String docid = null; |
|
50 |
private String user = null; |
|
51 |
private Thread xmlIndex; |
|
52 |
private boolean endDocument = false; |
|
48 | 53 |
|
49 | 54 |
private static final int MAXDATACHARS = 4000; |
50 | 55 |
private static final int MAXTITLELEN = 1000; |
... | ... | |
62 | 67 |
// if it doesn't already exist |
63 | 68 |
if (!stackCreated) { |
64 | 69 |
nodeStack = new Stack(); |
70 |
nodeIndex = new Vector(); |
|
65 | 71 |
stackCreated = true; |
66 | 72 |
} |
67 | 73 |
} |
... | ... | |
79 | 85 |
this.action = action; |
80 | 86 |
this.docid = docid; |
81 | 87 |
this.user = user; |
88 |
this.xmlIndex = new Thread(this); |
|
89 |
//this.xmlIndex.setPriority(Thread.MIN_PRIORITY); |
|
82 | 90 |
} |
83 | 91 |
|
84 | 92 |
/** SAX Handler that receives notification of beginning of the document */ |
... | ... | |
94 | 102 |
|
95 | 103 |
/** SAX Handler that receives notification of end of the document */ |
96 | 104 |
public void endDocument() throws SAXException { |
97 |
// NOT NEEDED ANY MORE - use currentDocument.setTitle() from characters(cbuf,start,end) |
|
98 |
// currentDocument.setTitleFromChildElement(); |
|
99 | 105 |
MetaCatUtil.debugMessage("end Document"); |
100 |
// NOT NEEDED ANY MORE - Accession# is generated at the very beginning before the parsing |
|
101 |
// if ((docid != null) && (!docid.equals(currentDocument.getDocID()))) { |
|
102 |
// throw (new SAXException("New document ID generated:", |
|
103 |
// new AccessionNumberGeneratedException(currentDocument.getDocID()))); |
|
104 |
// } else { |
|
105 |
// throw (new SAXException("New document ID generated:", |
|
106 |
// new AccessionNumberGeneratedException(currentDocument.getDocID()))); |
|
107 |
// } |
|
106 |
// Starting new thread for writing XML Index. |
|
107 |
// It calls the run method of the thread. |
|
108 |
try { |
|
109 |
xmlIndex.start(); |
|
110 |
} catch (NullPointerException e) { |
|
111 |
xmlIndex = null; |
|
112 |
throw new |
|
113 |
SAXException("Problem with starting thread for writing XML Index. " + |
|
114 |
e.getMessage()); |
|
115 |
} |
|
108 | 116 |
} |
109 | 117 |
|
110 | 118 |
/** SAX Handler that is called at the start of each XML element */ |
... | ... | |
151 | 159 |
currentNode = new DBSAXNode(conn, localName, parentNode, |
152 | 160 |
currentDocument.getRootNodeID(),docid, |
153 | 161 |
currentDocument.getDoctype()); |
154 |
|
|
162 |
|
|
155 | 163 |
// Add all of the attributes |
156 | 164 |
for (int i=0; i<atts.getLength(); i++) { |
157 | 165 |
currentNode.setAttribute(atts.getLocalName(i), atts.getValue(i), docid); |
... | ... | |
160 | 168 |
// Add the node to the stack, so that any text data can be |
161 | 169 |
// added as it is encountered |
162 | 170 |
nodeStack.push(currentNode); |
171 |
// Add the node to the vector used by thread for writing XML Index |
|
172 |
nodeIndex.addElement(currentNode); |
|
173 |
|
|
163 | 174 |
} |
175 |
|
|
176 |
// The run method of xmlIndex thread. It writes XML Index for the document. |
|
177 |
public void run () { |
|
178 |
DBSAXNode currNode = null; |
|
179 |
DBSAXNode prevNode = null; |
|
180 |
int step = 0; |
|
181 |
int counter = 0; |
|
164 | 182 |
|
183 |
try { |
|
184 |
// Opening separate db connection for writing XML Index |
|
185 |
MetaCatUtil util = new MetaCatUtil(); |
|
186 |
Connection conn = util.getConnection(); |
|
187 |
conn.setAutoCommit(false); |
|
188 |
|
|
189 |
// Going through the elements of the document and writing its Index |
|
190 |
Enumeration nodes = nodeIndex.elements(); |
|
191 |
while ( nodes.hasMoreElements() ) { |
|
192 |
currNode = (DBSAXNode)nodes.nextElement(); |
|
193 |
currNode.updateNodeIndex(conn, docid, currentDocument.getDoctype()); |
|
194 |
} |
|
195 |
|
|
196 |
conn.commit(); |
|
197 |
conn.close(); |
|
198 |
|
|
199 |
} catch (Exception e) { |
|
200 |
try { |
|
201 |
conn.rollback(); |
|
202 |
conn.close(); |
|
203 |
} catch (SQLException sqle) {} |
|
204 |
System.out.println("Error writing XML Index. " + e.getMessage()); |
|
205 |
} |
|
206 |
} |
|
207 |
|
|
165 | 208 |
/** SAX Handler that is called for each XML text node */ |
166 | 209 |
public void characters(char[] cbuf, int start, int len) throws SAXException { |
167 | 210 |
MetaCatUtil.debugMessage("CHARACTERS"); |
src/edu/ucsb/nceas/metacat/DBSAXNode.java | ||
---|---|---|
60 | 60 |
this.conn = conn; |
61 | 61 |
this.parentNode = parentNode; |
62 | 62 |
writeChildNodeToDB("ELEMENT", getTagName(), null, docid); |
63 |
updateNodeIndex(docid, doctype); |
|
63 |
//No writing XML Index from here. New Thread used instead. |
|
64 |
//updateNodeIndex(docid, doctype); |
|
64 | 65 |
} |
65 | 66 |
|
66 | 67 |
/** creates SQL code and inserts new node into DB connection */ |
... | ... | |
159 | 160 |
} |
160 | 161 |
} |
161 | 162 |
|
162 |
/** |
|
163 |
* creates SQL code to put doc ID for the document node and for |
|
164 |
* comment/PI nodes under document node into DB connection |
|
165 |
*/ |
|
166 |
/* |
|
167 |
public void writeDocID(String doc_id) { |
|
168 |
try { |
|
169 |
PreparedStatement pstmt; |
|
170 |
pstmt = conn.prepareStatement( |
|
171 |
"UPDATE xml_nodes set docid = ? " + |
|
172 |
"WHERE nodeid = ?"); |
|
173 |
|
|
174 |
// Bind the values to the query |
|
175 |
pstmt.setString(1, doc_id); |
|
176 |
pstmt.setLong(2, getNodeID()); |
|
177 |
// Do the insertion |
|
178 |
pstmt.execute(); |
|
179 |
pstmt.close(); |
|
180 |
|
|
181 |
// for comments and PI on the top |
|
182 |
pstmt = conn.prepareStatement( |
|
183 |
"UPDATE xml_nodes set docid = ? " + |
|
184 |
"WHERE parentnodeid = ?"); |
|
185 |
// Bind the values to the query |
|
186 |
pstmt.setString(1, doc_id); |
|
187 |
pstmt.setLong(2, getNodeID()); |
|
188 |
// Do the insertion |
|
189 |
pstmt.execute(); |
|
190 |
pstmt.close(); |
|
191 |
} catch (SQLException e) { |
|
192 |
System.out.println(e.getMessage()); |
|
193 |
} |
|
194 |
} |
|
195 |
*/ |
|
196 | 163 |
/** get next node id from DB connection */ |
197 | 164 |
private long generateNodeID() throws SAXException { |
198 | 165 |
long nid=0; |
... | ... | |
230 | 197 |
} |
231 | 198 |
|
232 | 199 |
/** |
200 |
* NOT USED |
|
233 | 201 |
* Update the node index (xml_index) for this node by generating |
234 | 202 |
* test strings that represent all of the relative and absolute |
235 | 203 |
* paths through the XML tree from document root to this node |
... | ... | |
285 | 253 |
pstmt.setLong(5, getParentID()); |
286 | 254 |
|
287 | 255 |
// Step through the hashtable and insert each of the path values |
256 |
Enumeration en = pathlist.keys(); |
|
257 |
while (en.hasMoreElements()) { |
|
258 |
String path = (String)en.nextElement(); |
|
259 |
Long nodeid = (Long)pathlist.get(path); |
|
260 |
pstmt.setLong(1, nodeid.longValue()); |
|
261 |
pstmt.setString(2, path); |
|
262 |
pstmt.executeUpdate(); |
|
263 |
|
|
264 |
//System.out.println(nodeid + " ==> " + path); |
|
265 |
} |
|
266 |
|
|
267 |
// Close the database statement |
|
268 |
pstmt.close(); |
|
269 |
} catch (SQLException sqe) { |
|
270 |
System.err.println("SQL Exception while inserting path to index."); |
|
271 |
System.err.println(sqe.getMessage()); |
|
272 |
throw new SAXException(sqe.getMessage()); |
|
273 |
} |
|
274 |
} |
|
275 |
|
|
276 |
/** |
|
277 |
* USED FROM SEPARATE THREAD RUNNED from DBSAXHandler on endDocument() |
|
278 |
* Update the node index (xml_index) for this node by generating |
|
279 |
* test strings that represent all of the relative and absolute |
|
280 |
* paths through the XML tree from document root to this node |
|
281 |
*/ |
|
282 |
public void updateNodeIndex(Connection conn, String docid, String doctype) |
|
283 |
throws SAXException |
|
284 |
{ |
|
285 |
Hashtable pathlist = new Hashtable(); |
|
286 |
boolean atStartingNode = true; |
|
287 |
boolean atRootDocumentNode = false; |
|
288 |
DBSAXNode nodePointer = this; |
|
289 |
StringBuffer currentPath = new StringBuffer(); |
|
290 |
int counter = 0; |
|
291 |
|
|
292 |
// Create a Hashtable of all of the paths to reach this node |
|
293 |
// including absolute paths and relative paths |
|
294 |
while (!atRootDocumentNode) { |
|
295 |
if (atStartingNode) { |
|
296 |
currentPath.insert(0, nodePointer.getTagName()); |
|
297 |
pathlist.put(currentPath.toString(), new Long(getNodeID())); |
|
298 |
counter++; |
|
299 |
atStartingNode = false; |
|
300 |
} else { |
|
301 |
currentPath.insert(0, "/"); |
|
302 |
currentPath.insert(0, nodePointer.getTagName()); |
|
303 |
pathlist.put(currentPath.toString(), new Long(getNodeID())); |
|
304 |
counter++; |
|
305 |
} |
|
306 |
|
|
307 |
// advance to the next parent node |
|
308 |
nodePointer = nodePointer.getParentNode(); |
|
309 |
|
|
310 |
// If we're at the DOCUMENT node (root of DOM tree), add |
|
311 |
// the root "/" to make the absolute path |
|
312 |
if (nodePointer.getNodeType().equals("DOCUMENT")) { |
|
313 |
currentPath.insert(0, "/"); |
|
314 |
pathlist.put(currentPath.toString(), new Long(getNodeID())); |
|
315 |
counter++; |
|
316 |
atRootDocumentNode = true; |
|
317 |
} |
|
318 |
} |
|
319 |
|
|
320 |
try { |
|
321 |
// Create an insert statement to reuse for all of the path insertions |
|
322 |
PreparedStatement pstmt = conn.prepareStatement( |
|
323 |
"INSERT INTO xml_index (nodeid, path, docid, doctype, " + |
|
324 |
"parentnodeid) " + |
|
325 |
"VALUES (?, ?, ?, ?, ?)"); |
|
326 |
((OraclePreparedStatement)pstmt).setExecuteBatch(counter); |
|
327 |
|
|
328 |
pstmt.setString(3, docid); |
|
329 |
pstmt.setString(4, doctype); |
|
330 |
pstmt.setLong(5, getParentID()); |
|
331 |
|
|
332 |
// Step through the hashtable and insert each of the path values |
|
288 | 333 |
Enumeration en = pathlist.keys(); |
289 | 334 |
while (en.hasMoreElements()) { |
290 | 335 |
String path = (String)en.nextElement(); |
Also available in: Unified diff
Separate thread used for writing into xml_index table.
This cut the time of the response on insert almost in half.
The tread is started afterwards
(on end of document parsing and inserting into xml_nodes) from
DBSAXHandler and uses new(separate) db connection.
But I did not find a good way to show the work done of that thread.