Project

General

Profile

« Previous | Next » 

Revision 471

Added by bojilova about 24 years ago

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.

View differences:

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