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