Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that tracks sessions for MetaCatServlet users.
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones
7
 *
8
 *   '$Author: daigle $'
9
 *     '$Date: 2008-07-06 21:25:34 -0700 (Sun, 06 Jul 2008) $'
10
 * '$Revision: 4080 $'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26

    
27
package edu.ucsb.nceas.metacat;
28

    
29
import java.sql.PreparedStatement;
30
import java.sql.ResultSet;
31
import java.sql.SQLException;
32
import java.util.Vector;
33
import java.util.HashMap;
34
import java.lang.Comparable;
35

    
36
import edu.ucsb.nceas.metacat.service.PropertyService;
37
import edu.ucsb.nceas.metacat.util.MetaCatUtil;
38
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
39

    
40
import org.apache.log4j.Logger;
41

    
42
public class IndexingQueue {
43

    
44
	private Logger logMetacat = Logger.getLogger(IndexingQueue.class);
45
	//	 Map used to keep tracks of docids to be indexed
46
	private HashMap indexingMap = new HashMap();     
47
	private Vector currentThreads = new Vector();
48
	public Vector currentDocidsBeingIndexed = new Vector();
49
	private boolean metacatRunning = true;
50
	
51
	private static IndexingQueue instance = null;
52

    
53
	final static int NUMBEROFINDEXINGTHREADS;
54
	static {
55
		int numIndexingThreads = 0;
56
		try {
57
			numIndexingThreads = 
58
				Integer.parseInt(PropertyService.getProperty("database.numberOfIndexingThreads"));
59
		} catch (PropertyNotFoundException pnfe) {
60
			System.err.println("Could not get property in static block: " 
61
					+ pnfe.getMessage());
62
		}
63
		NUMBEROFINDEXINGTHREADS = numIndexingThreads;
64
	}
65

    
66
	
67
	private int sleepTime = 2000; 
68

    
69
    private IndexingQueue() {
70
	    for (int i = 0; i < NUMBEROFINDEXINGTHREADS; i++) {
71
	      Thread thread = new IndexingTask();
72
	      thread.start();
73
	      currentThreads.add(thread);
74
	    }
75
    }
76
	
77
	public static synchronized IndexingQueue getInstance(){
78
		if (instance == null) {
79
			instance = new IndexingQueue();
80
		}
81
		return instance;
82
	}//getInstance
83

    
84
    public void add(String docid, String rev) {
85
    	add(new IndexingQueueObject(docid, rev, 0));
86
    }
87
    
88
    protected void add(IndexingQueueObject queueObject) {
89
	    synchronized (indexingMap) {
90
	    	if(!indexingMap.containsKey(queueObject.getDocid())){
91
	    		indexingMap.put(queueObject.getDocid(), queueObject);
92
	    		indexingMap.notify();
93
	    	} else {
94
	    		IndexingQueueObject oldQueueObject = 
95
	    			(IndexingQueueObject) indexingMap.get(queueObject.getDocid());
96
	    		if(oldQueueObject.compareTo(queueObject) < 0){
97
	    	  		indexingMap.put(queueObject.getDocid(), queueObject);
98
		    		indexingMap.notify();  			
99
	    		}
100
	    	}
101
	    }
102
	  }
103
    
104
	public boolean getMetacatRunning(){
105
		return this.metacatRunning;
106
	}
107
	
108
	public void setMetacatRunning(boolean metacatRunning){
109
		this.metacatRunning = metacatRunning;
110
		
111
		if(!metacatRunning){
112
			for(int count=0; count<currentThreads.size(); count++){
113
				((IndexingTask)currentThreads.get(count)).metacatRunning = false;
114
				((Thread)currentThreads.get(count)).interrupt();
115
			}
116
		}
117
	}
118
	
119
    protected IndexingQueueObject getNext() {
120
    	IndexingQueueObject returnVal = null;
121
        synchronized (indexingMap) {
122
          while (indexingMap.isEmpty() && metacatRunning) {
123
            try {
124
            	indexingMap.wait();
125
            } catch (InterruptedException ex) {
126
              System.err.println("Interrupted");
127
            }
128
          }
129
          
130
          if(metacatRunning){
131
        	  String docid = (String) indexingMap.keySet().iterator().next();
132
        	  returnVal = (IndexingQueueObject)indexingMap.get(docid);
133
        	  indexingMap.remove(docid);
134
          }
135
        }
136
        return returnVal;
137
      }
138

    
139
}
140

    
141
class IndexingTask extends Thread {
142
  	  private Logger logMetacat = Logger.getLogger(IndexingTask.class);
143
  	  
144
  	  
145
      protected final static long MAXIMUMINDEXDELAY;
146
      static {
147
    	  long maxIndexDelay = 0;
148
    	  try {
149
    		  maxIndexDelay = 
150
    			  Integer.parseInt(PropertyService.getProperty("database.maximumIndexDelay")); 
151
    	  } catch (PropertyNotFoundException pnfe) {
152
    		  System.err.println("Could not get property in static block: " 
153
  					+ pnfe.getMessage());
154
    	  }
155
    	  MAXIMUMINDEXDELAY = maxIndexDelay;
156
      }
157
      
158
      protected boolean metacatRunning = true;
159
      	
160
	  public void run() {
161
	    while (metacatRunning) {
162
	      // blocks until job
163
	      IndexingQueueObject returnVal = 
164
	    	  IndexingQueue.getInstance().getNext();
165

    
166
	      if(returnVal != null){
167
	    	  if(!IndexingQueue.getInstance().
168
	    			currentDocidsBeingIndexed.contains(returnVal.getDocid())){
169
    		  try {
170
    			  IndexingQueue.getInstance().
171
    			  		currentDocidsBeingIndexed.add(returnVal.getDocid());
172
    		      String docid = returnVal.getDocid() + "." + returnVal.getRev();
173
    			  if(checkDocumentTable(docid, "xml_documents")){
174
    				  logMetacat.warn("Calling buildIndex for " + docid);
175
    				  DocumentImpl doc = new DocumentImpl(docid, false);
176
    				  doc.buildIndex();
177
    				  logMetacat.warn("finish building index for doicd "+docid);
178
    			  } else {
179
    				  logMetacat.warn("Couldn't find the docid:" + docid 
180
	                			+ " in xml_documents table");
181
	                  sleep(MAXIMUMINDEXDELAY);
182
	                  throw(new Exception("Couldn't find the docid:" + docid 
183
	                			+ " in xml_documents table"));
184
    			  }
185
    		  	} catch (Exception e) {
186
    			  logMetacat.warn("Exception: " + e);
187
    			  e.printStackTrace();
188
	        
189
    			  if(returnVal.getCount() < 25){
190
    				  returnVal.setCount(returnVal.getCount()+1);
191
    				  // add the docid back to the list
192
    				  IndexingQueue.getInstance().add(returnVal);
193
    			  } else {
194
    				  logMetacat.fatal("Docid " + returnVal.getDocid() 
195
	        			+ " has been inserted to IndexingQueue "
196
	        			+ "more than 25 times. Not adding the docid to"
197
	        			+ " the queue again.");
198
    			  }
199
    		  	} finally {
200
    			  	IndexingQueue.getInstance().currentDocidsBeingIndexed
201
    			  		.remove(returnVal.getDocid());	    	  
202
    		  	}
203
	    	  } else {
204
	    		  returnVal.setCount(returnVal.getCount()+1);
205
	    		  IndexingQueue.getInstance().add(returnVal);    		  
206
	    	  }
207
	      }
208
	    }
209
	  }
210
	  
211
      private boolean checkDocumentTable(String docid, String tablename) throws Exception{
212
	        DBConnection dbConn = null;
213
	        int serialNumber = -1;
214
	        boolean inxmldoc = false;
215
            
216
	        String revision = docid.substring(docid.lastIndexOf(".")+1,docid.length());
217
	        docid = docid.substring(0,docid.lastIndexOf("."));
218

    
219
	        logMetacat.info("Checking if document exsists in xml_documents: docid is " 
220
	        		+ docid + " and revision is " + revision);
221

    
222
	        try {
223
	            // Opening separate db connection for writing XML Index
224
	            dbConn = DBConnectionPool
225
	                    .getDBConnection("DBSAXHandler.checkDocumentTable");
226
	            serialNumber = dbConn.getCheckOutSerialNumber();
227

    
228
	            String xmlDocumentsCheck = "SELECT distinct docid FROM " + tablename
229
	                        + " WHERE docid ='" + docid
230
	                        + "' AND rev ='" + revision + "'";
231

    
232
                PreparedStatement xmlDocCheck = dbConn.prepareStatement(xmlDocumentsCheck);
233
                // Increase usage count
234
	            
235
                dbConn.increaseUsageCount(1);
236
	            xmlDocCheck.execute();
237
	            ResultSet doccheckRS = xmlDocCheck.getResultSet();
238
	            boolean tableHasRows = doccheckRS.next();
239
	            if (tableHasRows) {
240
	            	inxmldoc = true;
241
	            }
242
	            doccheckRS.close();
243
	            xmlDocCheck.close();
244
	        } catch (SQLException e) {
245
	        	   e.printStackTrace();
246
	        } finally {
247
	            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
248
	        }//finally
249
	        
250
	        return inxmldoc;
251
      }
252
	}
253

    
254
class IndexingQueueObject implements Comparable{
255
	// the docid of the document to be indexed. 
256
	private String docid;
257
	// the docid of the document to be indexed. 
258
	private String rev;
259
	// the count of number of times the document has been in the queue
260
	private int count;
261
	
262
	IndexingQueueObject(String docid, String rev, int count){
263
		this.docid = docid;
264
		this.rev = rev;
265
		this.count = count;
266
	}
267
	
268
	public int getCount(){
269
		return count;
270
	}
271

    
272
	public String getDocid(){
273
		return docid;
274
	}
275

    
276
	public String getRev(){
277
		return rev;
278
	}
279

    
280
	public void setCount(int count){
281
		this.count = count;
282
	}
283
	
284
	public void setDocid(String docid){
285
		this.docid = docid;
286
	}
287

    
288
	public void setRev(String rev){
289
		this.rev = rev;
290
	}
291
	
292
	public int compareTo(Object o){
293
		if(o instanceof IndexingQueueObject){
294
			int revision = Integer.parseInt(rev);
295
			int oRevision = Integer.parseInt(((IndexingQueueObject)o).getRev());
296
			
297
			if(revision == oRevision) {
298
				return 0;
299
			} else if (revision > oRevision) {
300
				return 1;
301
			} else {
302
				return -1;
303
			}
304
		} else {
305
			throw new java.lang.ClassCastException();
306
		}
307
	}
308
}
(40-40/67)