Project

General

Profile

1 522 berkley
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class to asyncronously do delta-T replication checking
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Chad Berkley
7
 *
8
 *   '$Author$'
9
 *     '$Date$'
10
 * '$Revision$'
11 669 jones
 *
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 522 berkley
 */
26 2286 tao
27 5014 daigle
package edu.ucsb.nceas.metacat.replication;
28 522 berkley
29 5014 daigle
import edu.ucsb.nceas.metacat.CatalogMessageHandler;
30
import edu.ucsb.nceas.metacat.DBUtil;
31
import edu.ucsb.nceas.metacat.DocInfoHandler;
32
import edu.ucsb.nceas.metacat.DocumentImpl;
33
import edu.ucsb.nceas.metacat.DocumentImplWrapper;
34
import edu.ucsb.nceas.metacat.EventLog;
35 5089 daigle
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
36 5098 daigle
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
37 5014 daigle
import edu.ucsb.nceas.metacat.database.DBConnection;
38
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
39
import edu.ucsb.nceas.metacat.database.DatabaseService;
40 5030 daigle
import edu.ucsb.nceas.metacat.properties.PropertyService;
41 5014 daigle
import edu.ucsb.nceas.metacat.shared.HandlerException;
42 4698 daigle
import edu.ucsb.nceas.metacat.util.MetacatUtil;
43 5324 berkley
import edu.ucsb.nceas.metacat.IdentifierManager;
44 4080 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
45
46 522 berkley
import java.sql.*;
47
import java.util.*;
48 2555 tao
import java.util.Date;
49 522 berkley
import java.io.*;
50
import java.net.*;
51 543 berkley
import java.text.*;
52 2663 sgarg
53
import org.apache.log4j.Logger;
54 522 berkley
import org.xml.sax.ContentHandler;
55
import org.xml.sax.ErrorHandler;
56
import org.xml.sax.InputSource;
57 5014 daigle
import org.xml.sax.SAXException;
58 522 berkley
import org.xml.sax.XMLReader;
59
import org.xml.sax.helpers.XMLReaderFactory;
60 561 berkley
import org.xml.sax.helpers.DefaultHandler;
61 522 berkley
62 561 berkley
63
64 522 berkley
/**
65
 * This class handles deltaT replication checking.  Whenever this TimerTask
66
 * is fired it checks each server in xml_replication for updates and updates
67
 * the local db as needed.
68
 */
69
public class ReplicationHandler extends TimerTask
70
{
71 573 berkley
  int serverCheckCode = 1;
72 2286 tao
  ReplicationServerList serverList = null;
73 2573 tao
  //PrintWriter out;
74 4698 daigle
//  private static final AbstractDatabase dbAdapter = MetacatUtil.dbAdapter;
75 5014 daigle
  private static Logger logReplication = Logger.getLogger("ReplicationLogging");
76 2663 sgarg
  private static Logger logMetacat = Logger.getLogger(ReplicationHandler.class);
77 2725 tao
  private static int DOCINSERTNUMBER = 1;
78
  private static int DOCERRORNUMBER  = 1;
79
  private static int REVINSERTNUMBER = 1;
80
  private static int REVERRORNUMBER  = 1;
81 5175 daigle
82
  private static int _xmlDocQueryCount = 0;
83
  private static int _xmlRevQueryCount = 0;
84
  private static long _xmlDocQueryTime = 0;
85
  private static long _xmlRevQueryTime = 0;
86
87
88 2573 tao
  public ReplicationHandler()
89 522 berkley
  {
90 2573 tao
    //this.out = o;
91 1292 tao
    serverList = new ReplicationServerList();
92 522 berkley
  }
93 2286 tao
94 2573 tao
  public ReplicationHandler(int serverCheckCode)
95 573 berkley
  {
96 2573 tao
    //this.out = o;
97 573 berkley
    this.serverCheckCode = serverCheckCode;
98 1292 tao
    serverList = new ReplicationServerList();
99 573 berkley
  }
100 2286 tao
101 522 berkley
  /**
102 2286 tao
   * Method that implements TimerTask.run().  It runs whenever the timer is
103 522 berkley
   * fired.
104
   */
105
  public void run()
106
  {
107
    //find out the last_checked time of each server in the server list and
108 2286 tao
    //send a query to each server to see if there are any documents in
109 522 berkley
    //xml_documents with an update_date > last_checked
110 5014 daigle
111 1032 tao
      //if serverList is null, metacat don't need to replication
112
      if (serverList==null||serverList.isEmpty())
113
      {
114
        return;
115
      }
116 1292 tao
      updateCatalog();
117
      update();
118 1217 tao
      //conn.close();
119 522 berkley
  }
120 2286 tao
121 522 berkley
  /**
122 5175 daigle
   * Method that uses revision tagging for replication instead of update_date.
123 577 berkley
   */
124 1292 tao
  private void update()
125 577 berkley
  {
126 5175 daigle
127
	  _xmlDocQueryCount = 0;
128
	  _xmlRevQueryCount = 0;
129
	  _xmlDocQueryTime = 0;
130
	  _xmlRevQueryTime = 0;
131 577 berkley
    /*
132
     Pseudo-algorithm
133
     - request a doc list from each server in xml_replication
134 2286 tao
     - check the rev number of each of those documents agains the
135 577 berkley
       documents in the local database
136
     - pull any documents that have a lesser rev number on the local server
137
       from the remote server
138
     - delete any documents that still exist in the local xml_documents but
139
       are in the deletedDocuments tag of the remote host response.
140
     - update last_checked to keep track of the last time it was checked.
141 2286 tao
       (this info is theoretically not needed using this system but probably
142 577 berkley
       should be kept anyway)
143
    */
144 2286 tao
145
    ReplicationServer replServer = null; // Variable to store the
146
                                        // ReplicationServer got from
147 1292 tao
                                        // Server list
148 2298 tao
    String server = null; // Variable to store server name
149 5014 daigle
//    String update;
150
    Vector<String> responses = new Vector<String>();
151 577 berkley
    URL u;
152 5175 daigle
    long replicationStartTime = System.currentTimeMillis();
153
    long timeToGetServerList = 0;
154 3898 tao
155 1585 tao
    //Check for every server in server list to get updated list and put
156
    // them in to response
157 5175 daigle
    long startTimeToGetServers = System.currentTimeMillis();
158 1585 tao
    for (int i=0; i<serverList.size(); i++)
159
    {
160 1292 tao
        // Get ReplicationServer object from server list
161
        replServer = serverList.serverAt(i);
162
        // Get server name from ReplicationServer object
163 2578 tao
        server = replServer.getServerName().trim();
164 1585 tao
        String result = null;
165 5014 daigle
        logReplication.info("ReplicationHandler.update - full update started to: " + server);
166 1292 tao
        // Send command to that server to get updated docid information
167
        try
168
        {
169 1585 tao
          u = new URL("https://" + server + "?server="
170 4698 daigle
          +MetacatUtil.getLocalReplicationServerName()+"&action=update");
171 5014 daigle
          logReplication.info("ReplicationHandler.update - Sending infomation " +u.toString());
172
          result = ReplicationService.getURLContent(u);
173 1585 tao
        }
174 1292 tao
        catch (Exception e)
175
        {
176 5014 daigle
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
177
          logReplication.error( "ReplicationHandler.update - Failed to get updated doc list "+
178 2663 sgarg
                       "for server " + server + " because "+e.getMessage());
179 1292 tao
          continue;
180 1585 tao
        }
181 2286 tao
182 5175 daigle
        //logReplication.info("ReplicationHandler.update - docid: "+server+" "+result);
183 1292 tao
        //check if result have error or not, if has skip it.
184 1609 tao
        if (result.indexOf("<error>")!=-1 && result.indexOf("</error>")!=-1)
185 1102 tao
        {
186 5014 daigle
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
187
          logReplication.error( "ReplicationHandler.update - Failed to get updated doc list "+
188 2663 sgarg
                       "for server " + server + " because "+result);
189 1102 tao
          continue;
190
        }
191 1585 tao
        //Add result to vector
192 577 berkley
        responses.add(result);
193 1585 tao
    }
194 5175 daigle
    timeToGetServerList = System.currentTimeMillis() - startTimeToGetServers;
195 2286 tao
196 1585 tao
    //make sure that there is updated file list
197
    //If response is null, metacat don't need do anything
198
    if (responses==null || responses.isEmpty())
199
    {
200 5014 daigle
    	logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
201
        logReplication.info( "ReplicationHandler.update - No updated doc list for "+
202 1585 tao
                           "every server and failed to replicate");
203 1032 tao
        return;
204 1585 tao
    }
205 2286 tao
206
207 5175 daigle
    //logReplication.info("ReplicationHandler.update - Responses from remote metacat about updated "+
208
    //               "document information: "+ responses.toString());
209
210
    long totalServerListParseTime = 0;
211 1585 tao
    // go through response vector(it contains updated vector and delete vector
212
    for(int i=0; i<responses.size(); i++)
213 2286 tao
    {
214 5175 daigle
    	long startServerListParseTime = System.currentTimeMillis();
215 3898 tao
    	XMLReader parser;
216
    	ReplMessageHandler message = new ReplMessageHandler();
217
    	try
218
        {
219
          parser = initParser(message);
220
        }
221
        catch (Exception e)
222
        {
223 5014 daigle
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
224
          logReplication.error("ReplicationHandler.update - Failed to replicate becaue couldn't " +
225 3898 tao
                                " initParser for message and " +e.getMessage());
226
           // stop replication
227
           return;
228
        }
229
230 1585 tao
        try
231
        {
232
          parser.parse(new InputSource(
233 577 berkley
                     new StringReader(
234
                     (String)(responses.elementAt(i)))));
235 1585 tao
        }
236
        catch(Exception e)
237
        {
238 5014 daigle
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
239
          logReplication.error("ReplicationHandler.update - Couldn't parse one responses "+
240 2663 sgarg
                                   "because "+ e.getMessage());
241 1585 tao
          continue;
242
        }
243 1037 tao
        //v is the list of updated documents
244 5014 daigle
        Vector<Vector<String>> updateList = new Vector<Vector<String>>(message.getUpdatesVect());
245
        logReplication.info("ReplicationHandler.update - The document list size is "+updateList.size()+ " from "+message.getServerName());
246 577 berkley
        //System.out.println("v: " + v.toString());
247 1037 tao
        //d is the list of deleted documents
248 5014 daigle
        Vector<Vector<String>> deleteList = new Vector<Vector<String>>(message.getDeletesVect());
249 1037 tao
        //System.out.println("d: " + d.toString());
250 5014 daigle
        logReplication.info("ReplicationHandler.update - Update vector size: "+ updateList.size()+" from "+message.getServerName());
251
        logReplication.info("ReplicationHandler.update - Delete vector size: "+ deleteList.size()+" from "+message.getServerName());
252
        logReplication.info("ReplicationHandler.update - The delete document list size is "+deleteList.size()+" from "+message.getServerName());
253 1585 tao
        // go though every element in updated document vector
254 2608 tao
        handleDocList(updateList, DocumentImpl.DOCUMENTTABLE);
255 1037 tao
        //handle deleted docs
256 1585 tao
        for(int k=0; k<deleteList.size(); k++)
257 577 berkley
        { //delete the deleted documents;
258 5014 daigle
          Vector<String> w = new Vector<String>(deleteList.elementAt(k));
259 1585 tao
          String docId = (String)w.elementAt(0);
260
          try
261 579 berkley
          {
262 2298 tao
            handleDeleteSingleDocument(docId, server);
263 579 berkley
          }
264 1585 tao
          catch (Exception ee)
265
          {
266
            continue;
267
          }
268 1037 tao
        }//for delete docs
269 2608 tao
270
        // handle replicate doc in xml_revision
271 5014 daigle
        Vector<Vector<String>> revisionList = new Vector<Vector<String>>(message.getRevisionsVect());
272
        logReplication.info("ReplicationHandler.update - The revision document list size is "+revisionList.size()+ " from "+message.getServerName());
273 2608 tao
        handleDocList(revisionList, DocumentImpl.REVISIONTABLE);
274 2725 tao
        DOCINSERTNUMBER = 1;
275
        DOCERRORNUMBER  = 1;
276
        REVINSERTNUMBER = 1;
277
        REVERRORNUMBER  = 1;
278 5175 daigle
279
        totalServerListParseTime += (System.currentTimeMillis() - startServerListParseTime);
280 1585 tao
    }//for response
281 2286 tao
282 1585 tao
    //updated last_checked
283
    for (int i=0;i<serverList.size(); i++)
284
    {
285
       // Get ReplicationServer object from server list
286
       replServer = serverList.serverAt(i);
287
       try
288
       {
289
         updateLastCheckTimeForSingleServer(replServer);
290
       }
291
       catch(Exception e)
292
       {
293
         continue;
294
       }
295
    }//for
296 5175 daigle
297
    long replicationEndTime = System.currentTimeMillis();
298
    logMetacat.debug("ReplicationHandler.update - Total replication time: " +
299
    		(replicationEndTime - replicationStartTime));
300
    logMetacat.debug("ReplicationHandler.update - time to get server list: " +
301
    		timeToGetServerList);
302
    logMetacat.debug("ReplicationHandler.update - server list parse time: " +
303
    		totalServerListParseTime);
304
    logMetacat.debug("ReplicationHandler.update - 'in xml_documents' total query count: " +
305
    		_xmlDocQueryCount);
306
    logMetacat.debug("ReplicationHandler.update - 'in xml_documents' total query time: " +
307
    		_xmlDocQueryTime + " ms");
308
    logMetacat.debug("ReplicationHandler.update - 'in xml_revisions' total query count: " +
309
    		_xmlRevQueryCount);
310
    logMetacat.debug("ReplicationHandler.update - 'in xml_revisions' total query time: " +
311
    		_xmlRevQueryTime + " ms");;
312 2286 tao
313 1585 tao
  }//update
314 2286 tao
315 1585 tao
  /* Handle replicate single xml document*/
316 2286 tao
  private void handleSingleXMLDocument(String remoteserver, String actions,
317 2641 tao
                                       String accNumber, String tableName)
318 5014 daigle
               throws HandlerException
319 1585 tao
  {
320
    DBConnection dbConn = null;
321
    int serialNumber = -1;
322
    try
323
    {
324
      // Get DBConnection from pool
325
      dbConn=DBConnectionPool.
326
                  getDBConnection("ReplicationHandler.handleSingleXMLDocument");
327
      serialNumber=dbConn.getCheckOutSerialNumber();
328
      //if the document needs to be updated or inserted, this is executed
329 1600 tao
      String readDocURLString = "https://" + remoteserver + "?server="+
330 4698 daigle
              MetacatUtil.getLocalReplicationServerName()+"&action=read&docid="+accNumber;
331
      readDocURLString = MetacatUtil.replaceWhiteSpaceForURL(readDocURLString);
332 1600 tao
      URL u = new URL(readDocURLString);
333 2286 tao
334 1585 tao
      // Get docid content
335 5014 daigle
      String newxmldoc = ReplicationService.getURLContent(u);
336 1585 tao
      // If couldn't get skip it
337 1609 tao
      if ( newxmldoc.indexOf("<error>")!= -1 && newxmldoc.indexOf("</error>")!=-1)
338 1292 tao
      {
339 5014 daigle
         throw new HandlerException("ReplicationHandler.handleSingleXMLDocument - " + newxmldoc);
340 1585 tao
      }
341 5014 daigle
      //logReplication.info("xml documnet:");
342
      //logReplication.info(newxmldoc);
343 2286 tao
344 1585 tao
      // Try get the docid info from remote server
345
      DocInfoHandler dih = new DocInfoHandler();
346
      XMLReader docinfoParser = initParser(dih);
347 2286 tao
      String docInfoURLStr = "https://" + remoteserver +
348 4698 daigle
                       "?server="+MetacatUtil.getLocalReplicationServerName()+
349 2641 tao
                       "&action=getdocumentinfo&docid="+accNumber;
350 4698 daigle
      docInfoURLStr = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLStr);
351 1600 tao
      URL docinfoUrl = new URL(docInfoURLStr);
352 5014 daigle
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - Sending message: " +
353 2663 sgarg
                                                  docinfoUrl.toString());
354 5014 daigle
      String docInfoStr = ReplicationService.getURLContent(docinfoUrl);
355 1585 tao
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
356 5014 daigle
      Hashtable<String, String> docinfoHash = dih.getDocInfo();
357 1585 tao
      // Get home server of the docid
358 5014 daigle
      String docHomeServer = docinfoHash.get("home_server");
359
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - doc home server in repl: "+docHomeServer);
360
      String createdDate = docinfoHash.get("date_created");
361
      String updatedDate = docinfoHash.get("date_updated");
362 1585 tao
      //docid should include rev number too
363 4212 daigle
      /*String accnum=docId+util.getProperty("document.accNumSeparator")+
364 2641 tao
                                              (String)docinfoHash.get("rev");*/
365 5014 daigle
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - docid in repl: "+accNumber);
366
      String docType = docinfoHash.get("doctype");
367
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - doctype in repl: "+docType);
368 2286 tao
369 1585 tao
      String parserBase = null;
370
      // this for eml2 and we need user eml2 parser
371 2169 sgarg
      if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE))
372 1585 tao
      {
373 2163 tao
         parserBase = DocumentImpl.EML200;
374 1585 tao
      }
375 2286 tao
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE))
376
      {
377
        parserBase = DocumentImpl.EML200;
378
      }
379
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE))
380
      {
381
        parserBase = DocumentImpl.EML210;
382
      }
383 1585 tao
      // Write the document into local host
384
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
385 2286 tao
      String newDocid = wrapper.writeReplication(dbConn,
386 5195 daigle
                              newxmldoc,
387 5014 daigle
                              docinfoHash.get("public_access"),
388 1585 tao
                              null,  /* the dtd text */
389 2286 tao
                              actions,
390 2641 tao
                              accNumber,
391 5014 daigle
                              docinfoHash.get("user_owner"),
392 1585 tao
                              null, /* null for groups[] */
393 2286 tao
                              docHomeServer,
394 2624 tao
                              remoteserver, tableName, true,// true is for time replication
395
                              createdDate,
396 3230 tao
                              updatedDate);
397 4419 leinfelder
398 5098 daigle
      //process extra access rules
399
      Vector<XMLAccessDAO> xmlAccessDAOList = dih.getAccessControlList();
400
      if (xmlAccessDAOList != null) {
401
      	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(accNumber);
402
      	for (XMLAccessDAO xmlAccessDAO : xmlAccessDAOList) {
403
      		if (!acfsf.accessControlExists(xmlAccessDAO)) {
404
      			acfsf.insertPermissions(xmlAccessDAO);
405
      		}
406 4419 leinfelder
          }
407
      }
408
409 5324 berkley
      //process guid
410
      logReplication.debug("Processing guid information from docinfoHash: " + docinfoHash.toString());
411
      String guid = docinfoHash.get("guid");
412
      IdentifierManager idman = IdentifierManager.getInstance();
413
      if(guid != null && !idman.identifierExists(guid))
414
      { //if the guid was passed in, put it in the identifiers table
415
        logReplication.debug("Creating guid/docid mapping for docid " +
416
          docinfoHash.get("docid") + " and guid: " + guid);
417
        idman.createMapping(guid, docinfoHash.get("docid"));
418
      }
419
      else
420
      {
421
        logReplication.debug("No guid information was included with the replicated document");
422
      }
423
424 5014 daigle
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - Successfully replicated doc " + accNumber);
425 2725 tao
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
426
      {
427 5014 daigle
        logReplication.info("ReplicationHandler.handleSingleXMLDocument - " + DOCINSERTNUMBER + " Wrote xml doc " + accNumber +
428 2725 tao
                                     " into "+tableName + " from " +
429 1585 tao
                                         remoteserver);
430 2725 tao
        DOCINSERTNUMBER++;
431
      }
432
      else
433
      {
434 5014 daigle
          logReplication.info("ReplicationHandler.handleSingleXMLDocument - " +REVINSERTNUMBER + " Wrote xml doc " + accNumber +
435 2725 tao
                  " into "+tableName + " from " +
436
                      remoteserver);
437
          REVINSERTNUMBER++;
438
      }
439 3234 tao
      String ip = getIpFromURL(u);
440 5014 daigle
      EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
441 2725 tao
442 2286 tao
443
    }//try
444 577 berkley
    catch(Exception e)
445
    {
446 2725 tao
447
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
448
        {
449 5014 daigle
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
450
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +DOCERRORNUMBER + " Failed to write xml doc " + accNumber +
451 2725 tao
                                       " into "+tableName + " from " +
452
                                           remoteserver + " because "+e.getMessage());
453
          DOCERRORNUMBER++;
454
        }
455
        else
456
        {
457 5014 daigle
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
458
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +REVERRORNUMBER + " Failed to write xml doc " + accNumber +
459 2725 tao
                    " into "+tableName + " from " +
460
                        remoteserver +" because "+e.getMessage());
461
            REVERRORNUMBER++;
462
        }
463 5014 daigle
        logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
464
        logReplication.error("ReplicationHandler.handleSingleXMLDocument - Failed to write doc " + accNumber +
465 2663 sgarg
                                      " into db because " +e.getMessage());
466 5014 daigle
      throw new HandlerException("ReplicationHandler.handleSingleXMLDocument - generic exception "
467
    		  + "writing Replication: " +e.getMessage());
468 577 berkley
    }
469 667 berkley
    finally
470
    {
471 1585 tao
       //return DBConnection
472
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
473
    }//finally
474
  }
475 2286 tao
476
477
478 1585 tao
  /* Handle replicate single xml document*/
479 2286 tao
  private void handleSingleDataFile(String remoteserver, String actions,
480 2641 tao
                                    String accNumber, String tableName)
481 5014 daigle
               throws HandlerException
482 1585 tao
  {
483 5014 daigle
    logReplication.info("ReplicationHandler.handleSingleDataFile - Try to replicate data file: " + accNumber);
484 1585 tao
    DBConnection dbConn = null;
485
    int serialNumber = -1;
486
    try
487
    {
488
      // Get DBConnection from pool
489
      dbConn=DBConnectionPool.
490
                  getDBConnection("ReplicationHandler.handleSinlgeDataFile");
491
      serialNumber=dbConn.getCheckOutSerialNumber();
492
      // Try get docid info from remote server
493
      DocInfoHandler dih = new DocInfoHandler();
494
      XMLReader docinfoParser = initParser(dih);
495 2286 tao
      String docInfoURLString = "https://" + remoteserver +
496 4698 daigle
                  "?server="+MetacatUtil.getLocalReplicationServerName()+
497 2641 tao
                  "&action=getdocumentinfo&docid="+accNumber;
498 4698 daigle
      docInfoURLString = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLString);
499 1600 tao
      URL docinfoUrl = new URL(docInfoURLString);
500 2286 tao
501 5014 daigle
      String docInfoStr = ReplicationService.getURLContent(docinfoUrl);
502 1585 tao
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
503 5014 daigle
      Hashtable<String, String> docinfoHash = dih.getDocInfo();
504 5175 daigle
      // Get docid owner
505 5014 daigle
      String user = docinfoHash.get("user_owner");
506 1585 tao
      // Get docid name (such as acl or dataset)
507 5014 daigle
      String docName = docinfoHash.get("docname");
508 2286 tao
      // Get doc type (eml public id)
509 5014 daigle
      String docType = docinfoHash.get("doctype");
510 1585 tao
      // Get docid home sever. it might be different to remoteserver
511 5175 daigle
      // because of hub feature
512 5014 daigle
      String docHomeServer = docinfoHash.get("home_server");
513
      String createdDate = docinfoHash.get("date_created");
514
      String updatedDate = docinfoHash.get("date_updated");
515 1585 tao
      //docid should include rev number too
516 4212 daigle
      /*String accnum=docId+util.getProperty("document.accNumSeparator")+
517 2641 tao
                                              (String)docinfoHash.get("rev");*/
518 2286 tao
519
520 4080 daigle
      String datafilePath = PropertyService.getProperty("application.datafilepath");
521 1585 tao
      // Get data file content
522 1600 tao
      String readDataURLString = "https://" + remoteserver + "?server="+
523 4698 daigle
                                        MetacatUtil.getLocalReplicationServerName()+
524 2641 tao
                                            "&action=readdata&docid="+accNumber;
525 4698 daigle
      readDataURLString = MetacatUtil.replaceWhiteSpaceForURL(readDataURLString);
526 1600 tao
      URL u = new URL(readDataURLString);
527 2286 tao
      InputStream input = u.openStream();
528 1585 tao
      //register data file into xml_documents table and wite data file
529
      //into file system
530 1600 tao
      if ( input != null)
531 667 berkley
      {
532 2286 tao
        DocumentImpl.writeDataFileInReplication(input,
533 2608 tao
                                                datafilePath,
534
                                                docName,docType,
535 2641 tao
                                                accNumber, user,
536 2608 tao
                                                docHomeServer,
537
                                                remoteserver,
538
                                                tableName,
539 2624 tao
                                                true, //true means timed replication
540
                                                createdDate,
541 3230 tao
                                                updatedDate);
542 2624 tao
543 4419 leinfelder
        //process extra access rules
544 5098 daigle
        Vector<XMLAccessDAO> xmlAccessDAOList = dih.getAccessControlList();
545
        if (xmlAccessDAOList != null) {
546
        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(accNumber);
547
        	for (XMLAccessDAO xmlAccessDAO : xmlAccessDAOList) {
548
        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
549
        			acfsf.insertPermissions(xmlAccessDAO);
550
        		}
551 4419 leinfelder
            }
552
        }
553
554 5014 daigle
        logReplication.info("ReplicationHandler.handleSingleDataFile - Successfully to write datafile " + accNumber);
555 2725 tao
        /*MetacatReplication.replLog("wrote datafile " + accNumber + " from " +
556 5175 daigle
                                    remote server);*/
557 2725 tao
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
558
        {
559 5014 daigle
          logReplication.info("ReplicationHandler.handleSingleDataFile - " + DOCINSERTNUMBER + " Wrote data file" + accNumber +
560 2725 tao
                                       " into "+tableName + " from " +
561
                                           remoteserver);
562
          DOCINSERTNUMBER++;
563
        }
564
        else
565
        {
566 5014 daigle
            logReplication.info("ReplicationHandler.handleSingleDataFile - " + REVINSERTNUMBER + " Wrote data file" + accNumber +
567 2725 tao
                    " into "+tableName + " from " +
568
                        remoteserver);
569
            REVINSERTNUMBER++;
570
        }
571 3234 tao
        String ip = getIpFromURL(u);
572 5014 daigle
        EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
573 2725 tao
574 1585 tao
      }//if
575
      else
576 1217 tao
      {
577 5014 daigle
         logReplication.info("ReplicationHandler.handleSingleDataFile - Couldn't open the data file: " + accNumber);
578
         throw new HandlerException("ReplicationHandler.handleSingleDataFile - Couldn't open the data file: " + accNumber);
579 1585 tao
      }//else
580 2286 tao
581
    }//try
582 1585 tao
    catch(Exception e)
583
    {
584 5175 daigle
      /*MetacatReplication.replErrorLog("Failed to try wrote data file " + accNumber +
585 2725 tao
                                      " because " +e.getMessage());*/
586
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
587
      {
588 5014 daigle
    	logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG);
589
    	logReplication.error("ReplicationHandler.handleSingleDataFile - " + DOCERRORNUMBER + " Failed to write data file " + accNumber +
590
                                     " into " + tableName + " from " +
591
                                         remoteserver + " because " + e.getMessage());
592 2725 tao
        DOCERRORNUMBER++;
593
      }
594
      else
595
      {
596 5014 daigle
    	  logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG);
597
    	  logReplication.error("ReplicationHandler.handleSingleDataFile - " + REVERRORNUMBER + " Failed to write data file" + accNumber +
598
                  " into " + tableName + " from " +
599
                      remoteserver +" because "+ e.getMessage());
600 2725 tao
          REVERRORNUMBER++;
601
      }
602 5014 daigle
      logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG);
603
      logReplication.error("ReplicationHandler.handleSingleDataFile - Failed to try wrote datafile " + accNumber +
604
                                      " because " + e.getMessage());
605
      throw new HandlerException("ReplicationHandler.handleSingleDataFile - generic exception "
606
    		  + "writing Replication: " + e.getMessage());
607 1585 tao
    }
608
    finally
609
    {
610
       //return DBConnection
611
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
612
    }//finally
613
  }
614 2286 tao
615
616
617 1585 tao
  /* Handle delete single document*/
618 2298 tao
  private void handleDeleteSingleDocument(String docId, String notifyServer)
619 5014 daigle
               throws HandlerException
620 1585 tao
  {
621 5014 daigle
    logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Try delete doc: "+docId);
622 1585 tao
    DBConnection dbConn = null;
623
    int serialNumber = -1;
624
    try
625
    {
626
      // Get DBConnection from pool
627
      dbConn=DBConnectionPool.
628
                  getDBConnection("ReplicationHandler.handleDeleteSingleDoc");
629
      serialNumber=dbConn.getCheckOutSerialNumber();
630
      if(!alreadyDeleted(docId))
631 1217 tao
      {
632 2286 tao
633 1585 tao
         //because delete method docid should have rev number
634
         //so we just add one for it. This rev number is no sence.
635 4212 daigle
         String accnum=docId+PropertyService.getProperty("document.accNumSeparator")+"1";
636 1585 tao
         //System.out.println("accnum: "+accnum);
637 3230 tao
         DocumentImpl.delete(accnum, null, null, notifyServer);
638 5014 daigle
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Successfully deleted doc " + docId);
639
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Doc " + docId + " deleted");
640 3234 tao
         URL u = new URL("https://"+notifyServer);
641
         String ip = getIpFromURL(u);
642 5014 daigle
         EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, docId, "delete");
643 1585 tao
      }
644 2286 tao
645
    }//try
646 1585 tao
    catch(Exception e)
647
    {
648 5014 daigle
      logMetacat.error("ReplicationHandler.handleDeleteSingleDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
649
      logReplication.error("ReplicationHandler.handleDeleteSingleDocument - Failed to delete doc " + docId +
650 2663 sgarg
                                 " in db because because " + e.getMessage());
651 5014 daigle
      throw new HandlerException("ReplicationHandler.handleDeleteSingleDocument - generic exception "
652
    		  + "when handling document: " + e.getMessage());
653 1585 tao
    }
654
    finally
655
    {
656
       //return DBConnection
657
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
658 1037 tao
    }//finally
659 1585 tao
  }
660 2286 tao
661 1585 tao
  /* Handle updateLastCheckTimForSingleServer*/
662 2286 tao
  private void updateLastCheckTimeForSingleServer(ReplicationServer repServer)
663 5014 daigle
                                                  throws HandlerException
664 590 berkley
  {
665 1585 tao
    String server = repServer.getServerName();
666 1217 tao
    DBConnection dbConn = null;
667
    int serialNumber = -1;
668
    PreparedStatement pstmt = null;
669 590 berkley
    try
670
    {
671 1585 tao
      // Get DBConnection from pool
672 1217 tao
      dbConn=DBConnectionPool.
673 1585 tao
             getDBConnection("ReplicationHandler.updateLastCheckTimeForServer");
674 1217 tao
      serialNumber=dbConn.getCheckOutSerialNumber();
675 2286 tao
676 5014 daigle
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Try to update last_check for server: "+server);
677 1585 tao
      // Get time from remote server
678
      URL dateurl = new URL("https://" + server + "?server="+
679 4698 daigle
      MetacatUtil.getLocalReplicationServerName()+"&action=gettime");
680 5014 daigle
      String datexml = ReplicationService.getURLContent(dateurl);
681
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - datexml: "+datexml);
682 1585 tao
      if (datexml!=null && !datexml.equals(""))
683
      {
684
         String datestr = datexml.substring(11, datexml.indexOf('<', 11));
685
         StringBuffer sql = new StringBuffer();
686 1751 tao
         /*sql.append("update xml_replication set last_checked = to_date('");
687 1585 tao
         sql.append(datestr).append("', 'YY-MM-DD HH24:MI:SS') where ");
688 1751 tao
         sql.append("server like '").append(server).append("'");*/
689
         sql.append("update xml_replication set last_checked = ");
690 5319 jones
         sql.append(DatabaseService.getInstance().getDBAdapter().toDate(datestr, "MM/DD/YY HH24:MI:SS"));
691 1751 tao
         sql.append(" where server like '").append(server).append("'");
692 1585 tao
         pstmt = dbConn.prepareStatement(sql.toString());
693 2286 tao
694 1585 tao
         pstmt.executeUpdate();
695
         dbConn.commit();
696
         pstmt.close();
697 5014 daigle
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - last_checked updated to "+datestr+" on "
698 2663 sgarg
                                      + server);
699 1585 tao
      }//if
700
      else
701
      {
702 2286 tao
703 5014 daigle
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server "  +
704 2286 tao
                                  server + " in db because couldn't get time "
705 2663 sgarg
                                  );
706 1585 tao
         throw new Exception("Couldn't get time for server "+ server);
707
      }
708 2286 tao
709
    }//try
710 1585 tao
    catch(Exception e)
711
    {
712 5014 daigle
      logMetacat.error("ReplicationHandler.updateLastCheckTimeForSingleServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);
713
      logReplication.error("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server " +
714
                                server + " in db because because " + e.getMessage());
715
      throw new HandlerException("ReplicationHandler.updateLastCheckTimeForSingleServer - "
716
    		  + "Error updating last checked time: " + e.getMessage());
717 1585 tao
    }
718
    finally
719
    {
720
       //return DBConnection
721
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
722
    }//finally
723
  }
724 2286 tao
725
726
727 1585 tao
  /**
728
   * updates xml_catalog with entries from other servers.
729
   */
730
  private void updateCatalog()
731
  {
732 5014 daigle
    logReplication.info("ReplicationHandler.updateCatalog - Start of updateCatalog");
733 1585 tao
    // ReplicationServer object in server list
734
    ReplicationServer replServer = null;
735
    PreparedStatement pstmt = null;
736
    String server = null;
737 2286 tao
738
739 1585 tao
    // Go through each ReplicationServer object in sererlist
740
    for (int j=0; j<serverList.size(); j++)
741 2286 tao
    {
742 5014 daigle
      Vector<Vector<String>> remoteCatalog = new Vector<Vector<String>>();
743
      Vector<String> publicId = new Vector<String>();
744 1585 tao
      try
745
      {
746 1292 tao
        // Get ReplicationServer object from server list
747
        replServer = serverList.serverAt(j);
748
        // Get server name from the ReplicationServer object
749
        server = replServer.getServerName();
750
        // Try to get catalog
751 1011 tao
        URL u = new URL("https://" + server + "?server="+
752 4698 daigle
        MetacatUtil.getLocalReplicationServerName()+"&action=getcatalog");
753 5014 daigle
        logReplication.info("ReplicationHandler.updateCatalog - sending message " + u.toString());
754
        String catxml = ReplicationService.getURLContent(u);
755 2286 tao
756 1292 tao
        // Make sure there are not error, no empty string
757
        if (catxml.indexOf("error")!=-1 || catxml==null||catxml.equals(""))
758
        {
759 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
760 1292 tao
        }
761 5175 daigle
        logReplication.debug("ReplicationHandler.updateCatalog - catxml: " + catxml);
762 590 berkley
        CatalogMessageHandler cmh = new CatalogMessageHandler();
763
        XMLReader catparser = initParser(cmh);
764
        catparser.parse(new InputSource(new StringReader(catxml)));
765
        //parse the returned catalog xml and put it into a vector
766 1585 tao
        remoteCatalog = cmh.getCatalogVect();
767 2286 tao
768 5175 daigle
        // Make sure remoteCatalog is not empty
769 1292 tao
        if (remoteCatalog.isEmpty())
770
        {
771 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
772 1292 tao
        }
773 2286 tao
774 5014 daigle
        String localcatxml = ReplicationService.getCatalogXML();
775 2286 tao
776 1292 tao
        // Make sure local catalog is no empty
777
        if (localcatxml==null||localcatxml.equals(""))
778
        {
779 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
780 1292 tao
        }
781 2286 tao
782 590 berkley
        cmh = new CatalogMessageHandler();
783
        catparser = initParser(cmh);
784
        catparser.parse(new InputSource(new StringReader(localcatxml)));
785 5014 daigle
        Vector<Vector<String>> localCatalog = cmh.getCatalogVect();
786 2286 tao
787 590 berkley
        //now we have the catalog from the remote server and this local server
788
        //we now need to compare the two and merge the differences.
789
        //the comparison is base on the public_id fields which is the 4th
790
        //entry in each row vector.
791 5014 daigle
        publicId = new Vector<String>();
792 590 berkley
        for(int i=0; i<localCatalog.size(); i++)
793
        {
794 5014 daigle
          Vector<String> v = new Vector<String>(localCatalog.elementAt(i));
795
          logReplication.info("ReplicationHandler.updateCatalog - v1: " + v.toString());
796 590 berkley
          publicId.add(new String((String)v.elementAt(3)));
797 595 berkley
          //System.out.println("adding " + (String)v.elementAt(3));
798 590 berkley
        }
799 1585 tao
      }//try
800
      catch (Exception e)
801
      {
802 5014 daigle
        logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);
803
        logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
804 1585 tao
                                    server + " because " +e.getMessage());
805
      }//catch
806 2286 tao
807 1585 tao
      for(int i=0; i<remoteCatalog.size(); i++)
808
      {
809
         // DConnection
810
        DBConnection dbConn = null;
811
        // DBConnection checkout serial number
812
        int serialNumber = -1;
813
        try
814 590 berkley
        {
815 1585 tao
            dbConn=DBConnectionPool.
816
                  getDBConnection("ReplicationHandler.updateCatalog");
817
            serialNumber=dbConn.getCheckOutSerialNumber();
818 5014 daigle
            Vector<String> v = remoteCatalog.elementAt(i);
819 1585 tao
            //System.out.println("v2: " + v.toString());
820
            //System.out.println("i: " + i);
821
            //System.out.println("remoteCatalog.size(): " + remoteCatalog.size());
822
            //System.out.println("publicID: " + publicId.toString());
823 5014 daigle
            logReplication.info
824
                              ("ReplicationHandler.updateCatalog - v.elementAt(3): " + (String)v.elementAt(3));
825 1585 tao
           if(!publicId.contains(v.elementAt(3)))
826
           { //so we don't have this public id in our local table so we need to
827
             //add it.
828
             //System.out.println("in if");
829
             StringBuffer sql = new StringBuffer();
830
             sql.append("insert into xml_catalog (entry_type, source_doctype, ");
831
             sql.append("target_doctype, public_id, system_id) values (?,?,?,");
832
             sql.append("?,?)");
833
             //System.out.println("sql: " + sql.toString());
834
             pstmt = dbConn.prepareStatement(sql.toString());
835
             pstmt.setString(1, (String)v.elementAt(0));
836
             pstmt.setString(2, (String)v.elementAt(1));
837
             pstmt.setString(3, (String)v.elementAt(2));
838
             pstmt.setString(4, (String)v.elementAt(3));
839
             pstmt.setString(5, (String)v.elementAt(4));
840
             pstmt.execute();
841
             pstmt.close();
842 5014 daigle
             logReplication.info("ReplicationHandler.updateCatalog - Success fully to insert new publicid "+
843 1585 tao
                               (String)v.elementAt(3) + " from server"+server);
844
           }
845 590 berkley
        }
846 1585 tao
        catch(Exception e)
847
        {
848 5014 daigle
           logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);
849
           logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
850 1585 tao
                                    server + " because " +e.getMessage());
851
        }//catch
852
        finally
853
        {
854
           DBConnectionPool.returnDBConnection(dbConn, serialNumber);
855 5175 daigle
        }//finally
856 1585 tao
      }//for remote catalog
857
    }//for server list
858 5014 daigle
    logReplication.info("End of updateCatalog");
859 590 berkley
  }
860 2286 tao
861 590 berkley
  /**
862 579 berkley
   * Method that returns true if docid has already been "deleted" from metacat.
863 582 berkley
   * This method really implements a truth table for deleted documents
864 590 berkley
   * The table is (a docid in one of the tables is represented by the X):
865 582 berkley
   * xml_docs      xml_revs      deleted?
866
   * ------------------------------------
867
   *   X             X             FALSE
868
   *   X             _             FALSE
869
   *   _             X             TRUE
870
   *   _             _             TRUE
871 579 berkley
   */
872 5014 daigle
  private static boolean alreadyDeleted(String docid) throws HandlerException
873 579 berkley
  {
874 1217 tao
    DBConnection dbConn = null;
875
    int serialNumber = -1;
876
    PreparedStatement pstmt = null;
877 579 berkley
    try
878
    {
879 1217 tao
      dbConn=DBConnectionPool.
880
                  getDBConnection("ReplicationHandler.alreadyDeleted");
881
      serialNumber=dbConn.getCheckOutSerialNumber();
882 582 berkley
      boolean xml_docs = false;
883
      boolean xml_revs = false;
884 2286 tao
885 579 berkley
      StringBuffer sb = new StringBuffer();
886 582 berkley
      sb.append("select docid from xml_revisions where docid like '");
887 579 berkley
      sb.append(docid).append("'");
888 1217 tao
      pstmt = dbConn.prepareStatement(sb.toString());
889 579 berkley
      pstmt.execute();
890
      ResultSet rs = pstmt.getResultSet();
891
      boolean tablehasrows = rs.next();
892
      if(tablehasrows)
893
      {
894 582 berkley
        xml_revs = true;
895
      }
896 2286 tao
897 582 berkley
      sb = new StringBuffer();
898
      sb.append("select docid from xml_documents where docid like '");
899
      sb.append(docid).append("'");
900 667 berkley
      pstmt.close();
901 1217 tao
      pstmt = dbConn.prepareStatement(sb.toString());
902
      //increase usage count
903
      dbConn.increaseUsageCount(1);
904 582 berkley
      pstmt.execute();
905
      rs = pstmt.getResultSet();
906
      tablehasrows = rs.next();
907 667 berkley
      pstmt.close();
908 582 berkley
      if(tablehasrows)
909
      {
910
        xml_docs = true;
911
      }
912 2286 tao
913 582 berkley
      if(xml_docs && xml_revs)
914
      {
915
        return false;
916
      }
917
      else if(xml_docs && !xml_revs)
918
      {
919
        return false;
920
      }
921
      else if(!xml_docs && xml_revs)
922
      {
923 579 berkley
        return true;
924
      }
925 582 berkley
      else if(!xml_docs && !xml_revs)
926
      {
927
        return true;
928
      }
929 579 berkley
    }
930
    catch(Exception e)
931
    {
932 5014 daigle
      logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);
933
      logReplication.error("ReplicationHandler.alreadyDeleted - general error in alreadyDeleted: " +
934 2663 sgarg
                          e.getMessage());
935 5014 daigle
      throw new HandlerException("ReplicationHandler.alreadyDeleted - general error: "
936
    		  + e.getMessage());
937 579 berkley
    }
938 667 berkley
    finally
939
    {
940 1217 tao
      try
941
      {
942
        pstmt.close();
943
      }//try
944
      catch (SQLException ee)
945
      {
946 5014 daigle
    	logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);
947
        logReplication.error("ReplicationHandler.alreadyDeleted - Error in replicationHandler.alreadyDeleted "+
948 2663 sgarg
                          "to close pstmt: "+ee.getMessage());
949 5014 daigle
        throw new HandlerException("ReplicationHandler.alreadyDeleted - SQL error when closing prepared statement: "
950
      		  + ee.getMessage());
951 1217 tao
      }//catch
952
      finally
953
      {
954
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
955
      }//finally
956
    }//finally
957 579 berkley
    return false;
958
  }
959 533 berkley
960 2286 tao
961 533 berkley
  /**
962 574 berkley
   * Method to initialize the message parser
963
   */
964
  public static XMLReader initParser(DefaultHandler dh)
965 5014 daigle
          throws HandlerException
966 574 berkley
  {
967
    XMLReader parser = null;
968
969
    try {
970
      ContentHandler chandler = dh;
971
972
      // Get an instance of the parser
973 4213 daigle
      String parserName = PropertyService.getProperty("xml.saxparser");
974 574 berkley
      parser = XMLReaderFactory.createXMLReader(parserName);
975
976
      // Turn off validation
977
      parser.setFeature("http://xml.org/sax/features/validation", false);
978 2286 tao
979 574 berkley
      parser.setContentHandler((ContentHandler)chandler);
980
      parser.setErrorHandler((ErrorHandler)chandler);
981
982 5014 daigle
    } catch (SAXException se) {
983
      throw new HandlerException("ReplicationHandler.initParser - Sax error when "
984
    		  + " initializing parser: " + se.getMessage());
985
    } catch (PropertyNotFoundException pnfe) {
986
        throw new HandlerException("ReplicationHandler.initParser - Property error when "
987
      		  + " getting parser name: " + pnfe.getMessage());
988
    }
989 574 berkley
990
    return parser;
991
  }
992 2286 tao
993 2555 tao
  /**
994 5175 daigle
	 * This method will combine given time string(in short format) to current
995 5014 daigle
	 * date. If the given time (e.g 10:00 AM) passed the current time (e.g 2:00
996
	 * PM Aug 21, 2005), then the time will set to second day, 10:00 AM Aug 22,
997
	 * 2005. If the given time (e.g 10:00 AM) haven't passed the current time
998
	 * (e.g 8:00 AM Aug 21, 2005) The time will set to be 10:00 AM Aug 21, 2005.
999
	 *
1000
	 * @param givenTime
1001
	 *            the format should be "10:00 AM " or "2:00 PM"
1002
	 * @return
1003
	 * @throws Exception
1004
	 */
1005
	public static Date combinateCurrentDateAndGivenTime(String givenTime) throws HandlerException
1006 2555 tao
  {
1007 5014 daigle
	  try {
1008 2555 tao
     Date givenDate = parseTime(givenTime);
1009
     Date newDate = null;
1010
     Date now = new Date();
1011
     String currentTimeString = getTimeString(now);
1012
     Date currentTime = parseTime(currentTimeString);
1013
     if ( currentTime.getTime() >= givenDate.getTime())
1014
     {
1015 5014 daigle
        logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today already pass the given time, we should set it as tomorrow");
1016 2555 tao
        String dateAndTime = getDateString(now) + " " + givenTime;
1017
        Date combinationDate = parseDateTime(dateAndTime);
1018
        // new date should plus 24 hours to make is the second day
1019
        newDate = new Date(combinationDate.getTime()+24*3600*1000);
1020
     }
1021
     else
1022
     {
1023 5014 daigle
         logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today haven't pass the given time, we should it as today");
1024 2555 tao
         String dateAndTime = getDateString(now) + " " + givenTime;
1025
         newDate = parseDateTime(dateAndTime);
1026
     }
1027 5014 daigle
     logReplication.warn("ReplicationHandler.combinateCurrentDateAndGivenTime - final setting time is "+ newDate.toString());
1028 2555 tao
     return newDate;
1029 5014 daigle
	  } catch (ParseException pe) {
1030
		  throw new HandlerException("ReplicationHandler.combinateCurrentDateAndGivenTime - "
1031
				  + "parsing error: "  + pe.getMessage());
1032
	  }
1033 2555 tao
  }
1034 2286 tao
1035 2555 tao
  /*
1036 5014 daigle
	 * parse a given string to Time in short format. For example, given time is
1037
	 * 10:00 AM, the date will be return as Jan 1 1970, 10:00 AM
1038
	 */
1039
  private static Date parseTime(String timeString) throws ParseException
1040 2555 tao
  {
1041
    DateFormat format = DateFormat.getTimeInstance(DateFormat.SHORT);
1042
    Date time = format.parse(timeString);
1043 5014 daigle
    logReplication.info("ReplicationHandler.parseTime - Date string is after parse a time string "
1044 2663 sgarg
                              +time.toString());
1045 2555 tao
    return time;
1046
1047
  }
1048
1049
  /*
1050 5175 daigle
   * Parse a given string to date and time. Date format is long and time
1051 2555 tao
   * format is short.
1052
   */
1053 5014 daigle
  private static Date parseDateTime(String timeString) throws ParseException
1054 2555 tao
  {
1055
    DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT);
1056
    Date time = format.parse(timeString);
1057 5014 daigle
    logReplication.info("ReplicationHandler.parseDateTime - Date string is after parse a time string "+
1058 2663 sgarg
                             time.toString());
1059 2555 tao
    return time;
1060
  }
1061
1062
  /*
1063
   * Get a date string from a Date object. The date format will be long
1064
   */
1065
  private static String getDateString(Date now)
1066
  {
1067
     DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
1068
     String s = df.format(now);
1069 5014 daigle
     logReplication.info("ReplicationHandler.getDateString - Today is " + s);
1070 2555 tao
     return s;
1071
  }
1072
1073
  /*
1074
   * Get a time string from a Date object, the time format will be short
1075
   */
1076
  private static String getTimeString(Date now)
1077
  {
1078
     DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
1079
     String s = df.format(now);
1080 5014 daigle
     logReplication.info("ReplicationHandler.getTimeString - Time is " + s);
1081 2555 tao
     return s;
1082
  }
1083 2608 tao
1084
1085
  /*
1086 4080 daigle
	 * This method will go through the docid list both in xml_Documents table
1087
	 * and in xml_revisions table @author tao
1088
	 */
1089 5014 daigle
	private void handleDocList(Vector<Vector<String>> docList, String tableName) {
1090 4080 daigle
		boolean dataFile = false;
1091
		for (int j = 0; j < docList.size(); j++) {
1092
			// initial dataFile is false
1093
			dataFile = false;
1094
			// w is information for one document, information contain
1095
			// docid, rev, server or datafile.
1096 5014 daigle
			Vector<String> w = new Vector<String>(docList.elementAt(j));
1097 4080 daigle
			// Check if the vector w contain "datafile"
1098
			// If it has, this document is data file
1099
			try {
1100 4173 daigle
				if (w.contains((String) PropertyService.getProperty("replication.datafileflag"))) {
1101 4080 daigle
					dataFile = true;
1102
				}
1103
			} catch (PropertyNotFoundException pnfe) {
1104 5014 daigle
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1105
				logReplication.error("ReplicationHandler.handleDocList - Could not retrieve data file flag property.  "
1106 4080 daigle
						+ "Leaving as false: " + pnfe.getMessage());
1107
			}
1108
			// System.out.println("w: " + w.toString());
1109
			// Get docid
1110
			String docid = (String) w.elementAt(0);
1111 5014 daigle
			logReplication.info("docid: " + docid);
1112 4080 daigle
			// Get revision number
1113
			int rev = Integer.parseInt((String) w.elementAt(1));
1114 5014 daigle
			logReplication.info("rev: " + rev);
1115 5175 daigle
			// Get remote server name (it is may not be doc home server because
1116 4080 daigle
			// the new hub feature
1117
			String remoteServer = (String) w.elementAt(2);
1118
			remoteServer = remoteServer.trim();
1119 2608 tao
1120 4080 daigle
			try {
1121
				if (tableName.equals(DocumentImpl.DOCUMENTTABLE)) {
1122
					handleDocInXMLDocuments(docid, rev, remoteServer, dataFile);
1123
				} else if (tableName.equals(DocumentImpl.REVISIONTABLE)) {
1124
					handleDocInXMLRevisions(docid, rev, remoteServer, dataFile);
1125
				} else {
1126
					continue;
1127
				}
1128 2608 tao
1129 4861 daigle
			} catch (Exception e) {
1130 5014 daigle
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1131
				logReplication.error("ReplicationHandler.handleDocList - error to handle update doc in " + tableName
1132 4861 daigle
						+ " in time replication" + e.getMessage());
1133 4080 daigle
				continue;
1134
			}
1135 5175 daigle
1136
	        if (_xmlDocQueryCount > 0 && (_xmlDocQueryCount % 100) == 0) {
1137
	        	logMetacat.debug("ReplicationHandler.update - xml_doc query count: " + _xmlDocQueryCount +
1138
	        			", xml_doc avg query time: " + (_xmlDocQueryTime / _xmlDocQueryCount));
1139
	        }
1140
1141
	        if (_xmlRevQueryCount > 0 && (_xmlRevQueryCount % 100) == 0) {
1142
	        	logMetacat.debug("ReplicationHandler.update - xml_rev query count: " + _xmlRevQueryCount +
1143
	        			", xml_rev avg query time: " + (_xmlRevQueryTime / _xmlRevQueryCount));
1144
	        }
1145 4080 daigle
1146
		}// for update docs
1147
1148
	}
1149 2608 tao
1150
   /*
1151 4080 daigle
	 * This method will handle doc in xml_documents table.
1152
	 */
1153 2608 tao
   private void handleDocInXMLDocuments(String docid, int rev, String remoteServer, boolean dataFile)
1154 5014 daigle
                                        throws HandlerException
1155 2608 tao
   {
1156
       // compare the update rev and local rev to see what need happen
1157
       int localrev = -1;
1158
       String action = null;
1159
       boolean flag = false;
1160
       try
1161
       {
1162 5175 daigle
    	 long docQueryStartTime = System.currentTimeMillis();
1163 2641 tao
         localrev = DBUtil.getLatestRevisionInDocumentTable(docid);
1164 5175 daigle
         long docQueryEndTime = System.currentTimeMillis();
1165
         _xmlDocQueryTime += (docQueryEndTime - docQueryStartTime);
1166
         _xmlDocQueryCount++;
1167 2608 tao
       }
1168
       catch (SQLException e)
1169
       {
1170 5014 daigle
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1171
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1172 2663 sgarg
                                " be found because " + e.getMessage());
1173 5014 daigle
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - " + DOCERRORNUMBER+"Docid "+ docid + " could not be "+
1174 2608 tao
                 "written because error happend to find it's local revision");
1175 2739 tao
         DOCERRORNUMBER++;
1176 5014 daigle
         throw new HandlerException ("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1177
                 " be found: " + e.getMessage());
1178 2608 tao
       }
1179 5014 daigle
       logReplication.info("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " is "+
1180 2663 sgarg
                               localrev);
1181 2608 tao
1182
       //check the revs for an update because this document is in the
1183
       //local DB, it might be out of date.
1184
       if (localrev == -1)
1185
       {
1186 2713 tao
          // check if the revision is in the revision table
1187 5014 daigle
    	   Vector<Integer> localRevVector = null;
1188
    	 try {
1189 5175 daigle
        	 long revQueryStartTime = System.currentTimeMillis();
1190 5014 daigle
    		 localRevVector = DBUtil.getRevListFromRevisionTable(docid);
1191 5175 daigle
             long revQueryEndTime = System.currentTimeMillis();
1192
             _xmlRevQueryTime += (revQueryEndTime - revQueryStartTime);
1193
             _xmlRevQueryCount++;
1194 5014 daigle
    	 } catch (SQLException sqle) {
1195
    		 throw new HandlerException("ReplicationHandler.handleDocInXMLDocuments - SQL error "
1196
    				 + " when getting rev list for docid: " + docid + " : " + sqle.getMessage());
1197
    	 }
1198 2713 tao
         if (localRevVector != null && localRevVector.contains(new Integer(rev)))
1199
         {
1200
             // this version was deleted, so don't need replicate
1201
             flag = false;
1202
         }
1203
         else
1204
         {
1205
           //insert this document as new because it is not in the local DB
1206
           action = "INSERT";
1207
           flag = true;
1208
         }
1209 2608 tao
       }
1210
       else
1211
       {
1212
         if(localrev == rev)
1213
         {
1214
           // Local meatacat has the same rev to remote host, don't need
1215
           // update and flag set false
1216
           flag = false;
1217
         }
1218
         else if(localrev < rev)
1219
         {
1220
           //this document needs to be updated so send an read request
1221
           action = "UPDATE";
1222
           flag = true;
1223
         }
1224
       }
1225 2641 tao
1226 5014 daigle
       String accNumber = null;
1227
       try {
1228
    	   accNumber = docid + PropertyService.getProperty("document.accNumSeparator") + rev;
1229
       } catch (PropertyNotFoundException pnfe) {
1230
    	   throw new HandlerException("ReplicationHandler.handleDocInXMLDocuments - error getting "
1231
    			   + "account number separator : " + pnfe.getMessage());
1232
       }
1233 2608 tao
       // this is non-data file
1234
       if(flag && !dataFile)
1235
       {
1236
         try
1237
         {
1238 2641 tao
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1239 2608 tao
         }
1240 5014 daigle
         catch(HandlerException he)
1241 2608 tao
         {
1242
           // skip this document
1243 5014 daigle
           throw he;
1244 2608 tao
         }
1245
       }//if for non-data file
1246
1247
        // this is for data file
1248
       if(flag && dataFile)
1249
       {
1250
         try
1251
         {
1252 2641 tao
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1253 2608 tao
         }
1254 5014 daigle
         catch(HandlerException he)
1255 2608 tao
         {
1256 5175 daigle
           // skip this data file
1257 5014 daigle
           throw he;
1258 2608 tao
         }
1259
1260 5175 daigle
       }//for data file
1261 2608 tao
   }
1262
1263
   /*
1264
    * This method will handle doc in xml_documents table.
1265
    */
1266
   private void handleDocInXMLRevisions(String docid, int rev, String remoteServer, boolean dataFile)
1267 5014 daigle
                                        throws HandlerException
1268 2608 tao
   {
1269
       // compare the update rev and local rev to see what need happen
1270 5014 daigle
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - In handle repliation revsion table");
1271
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - the docid is "+ docid);
1272
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - The rev is "+rev);
1273
       Vector<Integer> localrev = null;
1274 2608 tao
       String action = "INSERT";
1275
       boolean flag = false;
1276
       try
1277
       {
1278 5175 daigle
      	 long revQueryStartTime = System.currentTimeMillis();
1279 2608 tao
         localrev = DBUtil.getRevListFromRevisionTable(docid);
1280 5175 daigle
         long revQueryEndTime = System.currentTimeMillis();
1281
         _xmlRevQueryTime += (revQueryEndTime - revQueryStartTime);
1282
         _xmlRevQueryCount++;
1283 2608 tao
       }
1284 5014 daigle
       catch (SQLException sqle)
1285 2608 tao
       {
1286 5014 daigle
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1287
         logReplication.error("ReplicationHandler.handleDocInXMLRevisions - Local rev for docid "+ docid + " could not "+
1288
                                " be found because " + sqle.getMessage());
1289 2739 tao
         REVERRORNUMBER++;
1290 5014 daigle
         throw new HandlerException ("ReplicationHandler.handleDocInXMLRevisions - SQL exception getting rev list: "
1291
        		 + sqle.getMessage());
1292 2608 tao
       }
1293 5014 daigle
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - rev list in xml_revision table for docid "+ docid + " is "+
1294 2663 sgarg
                               localrev.toString());
1295 2608 tao
1296
       // if the rev is not in the xml_revision, we need insert it
1297
       if (!localrev.contains(new Integer(rev)))
1298
       {
1299
           flag = true;
1300
       }
1301 2641 tao
1302 5014 daigle
       String accNumber = null;
1303
       try {
1304
    	   accNumber = docid + PropertyService.getProperty("document.accNumSeparator") + rev;
1305
       } catch (PropertyNotFoundException pnfe) {
1306
    	   throw new HandlerException("ReplicationHandler.handleDocInXMLRevisions - error getting "
1307
    			   + "account number separator : " + pnfe.getMessage());
1308
       }
1309 2608 tao
       // this is non-data file
1310
       if(flag && !dataFile)
1311
       {
1312
         try
1313
         {
1314 2641 tao
1315
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1316 2608 tao
         }
1317 5014 daigle
         catch(HandlerException he)
1318 2608 tao
         {
1319
           // skip this document
1320 5014 daigle
           throw he;
1321 2608 tao
         }
1322
       }//if for non-data file
1323
1324
        // this is for data file
1325
       if(flag && dataFile)
1326
       {
1327
         try
1328
         {
1329 2641 tao
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1330 2608 tao
         }
1331 5014 daigle
         catch(HandlerException he)
1332 2608 tao
         {
1333 5175 daigle
           // skip this data file
1334 5014 daigle
           throw he;
1335 2608 tao
         }
1336
1337 5175 daigle
       }//for data file
1338 2608 tao
   }
1339 3234 tao
1340
   /*
1341
    * Return a ip address for given url
1342
    */
1343
   private String getIpFromURL(URL url)
1344
   {
1345
	   String ip = null;
1346
	   try
1347
	   {
1348
	      InetAddress address = InetAddress.getByName(url.getHost());
1349
	      ip = address.getHostAddress();
1350
	   }
1351
	   catch(UnknownHostException e)
1352
	   {
1353 5014 daigle
		   logMetacat.error("ReplicationHandler.getIpFromURL - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1354
		   logReplication.error("ReplicationHandler.getIpFromURL - Error in get ip address for host: "
1355 3234 tao
                   +e.getMessage());
1356
	   }
1357
1358
	   return ip;
1359
   }
1360 2608 tao
1361 522 berkley
}