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 5709 leinfelder
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_1_1NAMESPACE))
386
      {
387
        parserBase = DocumentImpl.EML210;
388
      }
389 1585 tao
      // Write the document into local host
390
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
391 2286 tao
      String newDocid = wrapper.writeReplication(dbConn,
392 5195 daigle
                              newxmldoc,
393 5014 daigle
                              docinfoHash.get("public_access"),
394 1585 tao
                              null,  /* the dtd text */
395 2286 tao
                              actions,
396 2641 tao
                              accNumber,
397 5014 daigle
                              docinfoHash.get("user_owner"),
398 1585 tao
                              null, /* null for groups[] */
399 2286 tao
                              docHomeServer,
400 2624 tao
                              remoteserver, tableName, true,// true is for time replication
401
                              createdDate,
402 3230 tao
                              updatedDate);
403 4419 leinfelder
404 5098 daigle
      //process extra access rules
405
      Vector<XMLAccessDAO> xmlAccessDAOList = dih.getAccessControlList();
406
      if (xmlAccessDAOList != null) {
407
      	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(accNumber);
408
      	for (XMLAccessDAO xmlAccessDAO : xmlAccessDAOList) {
409
      		if (!acfsf.accessControlExists(xmlAccessDAO)) {
410
      			acfsf.insertPermissions(xmlAccessDAO);
411
      		}
412 4419 leinfelder
          }
413
      }
414
415 5324 berkley
      //process guid
416
      logReplication.debug("Processing guid information from docinfoHash: " + docinfoHash.toString());
417
      String guid = docinfoHash.get("guid");
418 5944 berkley
      String docName = docinfoHash.get("docname");
419 5440 berkley
      System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%%%guid passed from docinfo hash: " + guid);
420 5324 berkley
      IdentifierManager idman = IdentifierManager.getInstance();
421 5944 berkley
422
      System.out.println("docname: " + docName);
423
424 5324 berkley
      if(guid != null && !idman.identifierExists(guid))
425
      { //if the guid was passed in, put it in the identifiers table
426
        logReplication.debug("Creating guid/docid mapping for docid " +
427
          docinfoHash.get("docid") + " and guid: " + guid);
428 5944 berkley
429
430
        System.out.println("creating mapping: guid: " + guid + " localId: " + docinfoHash.get("docid"));
431
        idman.createMapping(guid, docinfoHash.get("docid"));
432 5324 berkley
      }
433
      else
434
      {
435
        logReplication.debug("No guid information was included with the replicated document");
436
      }
437
438 5944 berkley
      //handle systemMetadata
439
      if(docName.trim().equals("systemMetadata"))
440
      {
441
          System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!creating mapping for systemMetadata: guid: " + guid + " localId: " + docinfoHash.get("docid"));
442
          idman.createSystemMetadataMapping(guid, docinfoHash.get("docid"));
443
          System.out.println("1");
444
          Long dateUploadedLong = new Long(docinfoHash.get("date_uploaded"));
445
          System.out.println("2");
446
          Long dateModifiedLong = new Long(docinfoHash.get("date_modified"));
447
          System.out.println("3");
448
          idman.insertAdditionalSystemMetadataFields(
449
                  dateUploadedLong.longValue(),
450
                  docinfoHash.get("rights_holder"),
451
                  docinfoHash.get("checksum"),
452
                  docinfoHash.get("checksum_algorithm"),
453
                  docinfoHash.get("origin_member_node"),
454
                  docinfoHash.get("authoritive_member_node"),
455
                  dateModifiedLong.longValue(),
456
                  docinfoHash.get("submitter"),
457
                  docinfoHash.get("guid"),
458
                  docinfoHash.get("objectFormat"),
459
                  new Long(docinfoHash.get("size")).longValue());
460
          System.out.println("4");
461
      }
462
463 5457 berkley
      if(guid != null)
464
      {
465 5459 berkley
          if(!docName.trim().equals("systemMetadata"))
466
          {
467
              logReplication.info("replicate D1GUID:" + guid + ":D1SCIMETADATA:" +
468
                      accNumber + ":");
469
          }
470
          else
471
          {
472
              logReplication.info("replicate D1GUID:" + guid + ":D1SYSMETADATA:" +
473
                      accNumber + ":");
474
          }
475 5457 berkley
      }
476
477 5014 daigle
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - Successfully replicated doc " + accNumber);
478 2725 tao
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
479
      {
480 5014 daigle
        logReplication.info("ReplicationHandler.handleSingleXMLDocument - " + DOCINSERTNUMBER + " Wrote xml doc " + accNumber +
481 2725 tao
                                     " into "+tableName + " from " +
482 1585 tao
                                         remoteserver);
483 2725 tao
        DOCINSERTNUMBER++;
484
      }
485
      else
486
      {
487 5014 daigle
          logReplication.info("ReplicationHandler.handleSingleXMLDocument - " +REVINSERTNUMBER + " Wrote xml doc " + accNumber +
488 2725 tao
                  " into "+tableName + " from " +
489
                      remoteserver);
490
          REVINSERTNUMBER++;
491
      }
492 3234 tao
      String ip = getIpFromURL(u);
493 5014 daigle
      EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
494 2725 tao
495 2286 tao
496
    }//try
497 577 berkley
    catch(Exception e)
498
    {
499 2725 tao
500
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
501
        {
502 5014 daigle
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
503
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +DOCERRORNUMBER + " Failed to write xml doc " + accNumber +
504 2725 tao
                                       " into "+tableName + " from " +
505
                                           remoteserver + " because "+e.getMessage());
506
          DOCERRORNUMBER++;
507
        }
508
        else
509
        {
510 5014 daigle
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
511
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +REVERRORNUMBER + " Failed to write xml doc " + accNumber +
512 2725 tao
                    " into "+tableName + " from " +
513
                        remoteserver +" because "+e.getMessage());
514
            REVERRORNUMBER++;
515
        }
516 5014 daigle
        logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
517
        logReplication.error("ReplicationHandler.handleSingleXMLDocument - Failed to write doc " + accNumber +
518 2663 sgarg
                                      " into db because " +e.getMessage());
519 5014 daigle
      throw new HandlerException("ReplicationHandler.handleSingleXMLDocument - generic exception "
520
    		  + "writing Replication: " +e.getMessage());
521 577 berkley
    }
522 667 berkley
    finally
523
    {
524 1585 tao
       //return DBConnection
525
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
526
    }//finally
527 5392 berkley
    logD1.info("replication.create localId:" + accNumber);
528 1585 tao
  }
529 2286 tao
530
531
532 1585 tao
  /* Handle replicate single xml document*/
533 2286 tao
  private void handleSingleDataFile(String remoteserver, String actions,
534 2641 tao
                                    String accNumber, String tableName)
535 5014 daigle
               throws HandlerException
536 1585 tao
  {
537 5014 daigle
    logReplication.info("ReplicationHandler.handleSingleDataFile - Try to replicate data file: " + accNumber);
538 1585 tao
    DBConnection dbConn = null;
539
    int serialNumber = -1;
540
    try
541
    {
542
      // Get DBConnection from pool
543
      dbConn=DBConnectionPool.
544
                  getDBConnection("ReplicationHandler.handleSinlgeDataFile");
545
      serialNumber=dbConn.getCheckOutSerialNumber();
546
      // Try get docid info from remote server
547
      DocInfoHandler dih = new DocInfoHandler();
548
      XMLReader docinfoParser = initParser(dih);
549 2286 tao
      String docInfoURLString = "https://" + remoteserver +
550 4698 daigle
                  "?server="+MetacatUtil.getLocalReplicationServerName()+
551 2641 tao
                  "&action=getdocumentinfo&docid="+accNumber;
552 4698 daigle
      docInfoURLString = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLString);
553 1600 tao
      URL docinfoUrl = new URL(docInfoURLString);
554 2286 tao
555 5014 daigle
      String docInfoStr = ReplicationService.getURLContent(docinfoUrl);
556 1585 tao
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
557 5014 daigle
      Hashtable<String, String> docinfoHash = dih.getDocInfo();
558 5175 daigle
      // Get docid owner
559 5014 daigle
      String user = docinfoHash.get("user_owner");
560 1585 tao
      // Get docid name (such as acl or dataset)
561 5014 daigle
      String docName = docinfoHash.get("docname");
562 2286 tao
      // Get doc type (eml public id)
563 5014 daigle
      String docType = docinfoHash.get("doctype");
564 1585 tao
      // Get docid home sever. it might be different to remoteserver
565 5175 daigle
      // because of hub feature
566 5014 daigle
      String docHomeServer = docinfoHash.get("home_server");
567
      String createdDate = docinfoHash.get("date_created");
568
      String updatedDate = docinfoHash.get("date_updated");
569 1585 tao
      //docid should include rev number too
570 4212 daigle
      /*String accnum=docId+util.getProperty("document.accNumSeparator")+
571 2641 tao
                                              (String)docinfoHash.get("rev");*/
572 2286 tao
573
574 4080 daigle
      String datafilePath = PropertyService.getProperty("application.datafilepath");
575 1585 tao
      // Get data file content
576 1600 tao
      String readDataURLString = "https://" + remoteserver + "?server="+
577 4698 daigle
                                        MetacatUtil.getLocalReplicationServerName()+
578 2641 tao
                                            "&action=readdata&docid="+accNumber;
579 4698 daigle
      readDataURLString = MetacatUtil.replaceWhiteSpaceForURL(readDataURLString);
580 1600 tao
      URL u = new URL(readDataURLString);
581 2286 tao
      InputStream input = u.openStream();
582 1585 tao
      //register data file into xml_documents table and wite data file
583
      //into file system
584 1600 tao
      if ( input != null)
585 667 berkley
      {
586 2286 tao
        DocumentImpl.writeDataFileInReplication(input,
587 2608 tao
                                                datafilePath,
588
                                                docName,docType,
589 2641 tao
                                                accNumber, user,
590 2608 tao
                                                docHomeServer,
591
                                                remoteserver,
592
                                                tableName,
593 2624 tao
                                                true, //true means timed replication
594
                                                createdDate,
595 3230 tao
                                                updatedDate);
596 2624 tao
597 4419 leinfelder
        //process extra access rules
598 5098 daigle
        Vector<XMLAccessDAO> xmlAccessDAOList = dih.getAccessControlList();
599
        if (xmlAccessDAOList != null) {
600
        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(accNumber);
601
        	for (XMLAccessDAO xmlAccessDAO : xmlAccessDAOList) {
602
        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
603
        			acfsf.insertPermissions(xmlAccessDAO);
604
        		}
605 4419 leinfelder
            }
606
        }
607
608 5014 daigle
        logReplication.info("ReplicationHandler.handleSingleDataFile - Successfully to write datafile " + accNumber);
609 2725 tao
        /*MetacatReplication.replLog("wrote datafile " + accNumber + " from " +
610 5175 daigle
                                    remote server);*/
611 2725 tao
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
612
        {
613 5014 daigle
          logReplication.info("ReplicationHandler.handleSingleDataFile - " + DOCINSERTNUMBER + " Wrote data file" + accNumber +
614 2725 tao
                                       " into "+tableName + " from " +
615
                                           remoteserver);
616
          DOCINSERTNUMBER++;
617
        }
618
        else
619
        {
620 5014 daigle
            logReplication.info("ReplicationHandler.handleSingleDataFile - " + REVINSERTNUMBER + " Wrote data file" + accNumber +
621 2725 tao
                    " into "+tableName + " from " +
622
                        remoteserver);
623
            REVINSERTNUMBER++;
624
        }
625 3234 tao
        String ip = getIpFromURL(u);
626 5014 daigle
        EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
627 2725 tao
628 1585 tao
      }//if
629
      else
630 1217 tao
      {
631 5014 daigle
         logReplication.info("ReplicationHandler.handleSingleDataFile - Couldn't open the data file: " + accNumber);
632
         throw new HandlerException("ReplicationHandler.handleSingleDataFile - Couldn't open the data file: " + accNumber);
633 1585 tao
      }//else
634 2286 tao
635
    }//try
636 1585 tao
    catch(Exception e)
637
    {
638 5175 daigle
      /*MetacatReplication.replErrorLog("Failed to try wrote data file " + accNumber +
639 2725 tao
                                      " because " +e.getMessage());*/
640
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
641
      {
642 5014 daigle
    	logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG);
643
    	logReplication.error("ReplicationHandler.handleSingleDataFile - " + DOCERRORNUMBER + " Failed to write data file " + accNumber +
644
                                     " into " + tableName + " from " +
645
                                         remoteserver + " because " + e.getMessage());
646 2725 tao
        DOCERRORNUMBER++;
647
      }
648
      else
649
      {
650 5014 daigle
    	  logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG);
651
    	  logReplication.error("ReplicationHandler.handleSingleDataFile - " + REVERRORNUMBER + " Failed to write data file" + accNumber +
652
                  " into " + tableName + " from " +
653
                      remoteserver +" because "+ e.getMessage());
654 2725 tao
          REVERRORNUMBER++;
655
      }
656 5014 daigle
      logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG);
657
      logReplication.error("ReplicationHandler.handleSingleDataFile - Failed to try wrote datafile " + accNumber +
658
                                      " because " + e.getMessage());
659
      throw new HandlerException("ReplicationHandler.handleSingleDataFile - generic exception "
660
    		  + "writing Replication: " + e.getMessage());
661 1585 tao
    }
662
    finally
663
    {
664
       //return DBConnection
665
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
666
    }//finally
667 5392 berkley
    logD1.info("replication.create localId:" + accNumber);
668 1585 tao
  }
669 2286 tao
670
671
672 1585 tao
  /* Handle delete single document*/
673 2298 tao
  private void handleDeleteSingleDocument(String docId, String notifyServer)
674 5014 daigle
               throws HandlerException
675 1585 tao
  {
676 5014 daigle
    logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Try delete doc: "+docId);
677 1585 tao
    DBConnection dbConn = null;
678
    int serialNumber = -1;
679
    try
680
    {
681
      // Get DBConnection from pool
682
      dbConn=DBConnectionPool.
683
                  getDBConnection("ReplicationHandler.handleDeleteSingleDoc");
684
      serialNumber=dbConn.getCheckOutSerialNumber();
685
      if(!alreadyDeleted(docId))
686 1217 tao
      {
687 2286 tao
688 1585 tao
         //because delete method docid should have rev number
689
         //so we just add one for it. This rev number is no sence.
690 4212 daigle
         String accnum=docId+PropertyService.getProperty("document.accNumSeparator")+"1";
691 1585 tao
         //System.out.println("accnum: "+accnum);
692 3230 tao
         DocumentImpl.delete(accnum, null, null, notifyServer);
693 5014 daigle
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Successfully deleted doc " + docId);
694
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Doc " + docId + " deleted");
695 3234 tao
         URL u = new URL("https://"+notifyServer);
696
         String ip = getIpFromURL(u);
697 5014 daigle
         EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, docId, "delete");
698 1585 tao
      }
699 2286 tao
700
    }//try
701 1585 tao
    catch(Exception e)
702
    {
703 5014 daigle
      logMetacat.error("ReplicationHandler.handleDeleteSingleDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG);
704
      logReplication.error("ReplicationHandler.handleDeleteSingleDocument - Failed to delete doc " + docId +
705 2663 sgarg
                                 " in db because because " + e.getMessage());
706 5014 daigle
      throw new HandlerException("ReplicationHandler.handleDeleteSingleDocument - generic exception "
707
    		  + "when handling document: " + e.getMessage());
708 1585 tao
    }
709
    finally
710
    {
711
       //return DBConnection
712
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
713 1037 tao
    }//finally
714 5392 berkley
    logD1.info("replication.handleDeleteSingleDocument localId:" + docId);
715 1585 tao
  }
716 2286 tao
717 1585 tao
  /* Handle updateLastCheckTimForSingleServer*/
718 2286 tao
  private void updateLastCheckTimeForSingleServer(ReplicationServer repServer)
719 5014 daigle
                                                  throws HandlerException
720 590 berkley
  {
721 1585 tao
    String server = repServer.getServerName();
722 1217 tao
    DBConnection dbConn = null;
723
    int serialNumber = -1;
724
    PreparedStatement pstmt = null;
725 590 berkley
    try
726
    {
727 1585 tao
      // Get DBConnection from pool
728 1217 tao
      dbConn=DBConnectionPool.
729 1585 tao
             getDBConnection("ReplicationHandler.updateLastCheckTimeForServer");
730 1217 tao
      serialNumber=dbConn.getCheckOutSerialNumber();
731 2286 tao
732 5014 daigle
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Try to update last_check for server: "+server);
733 1585 tao
      // Get time from remote server
734
      URL dateurl = new URL("https://" + server + "?server="+
735 4698 daigle
      MetacatUtil.getLocalReplicationServerName()+"&action=gettime");
736 5014 daigle
      String datexml = ReplicationService.getURLContent(dateurl);
737
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - datexml: "+datexml);
738 1585 tao
      if (datexml!=null && !datexml.equals(""))
739
      {
740
         String datestr = datexml.substring(11, datexml.indexOf('<', 11));
741
         StringBuffer sql = new StringBuffer();
742 1751 tao
         /*sql.append("update xml_replication set last_checked = to_date('");
743 1585 tao
         sql.append(datestr).append("', 'YY-MM-DD HH24:MI:SS') where ");
744 1751 tao
         sql.append("server like '").append(server).append("'");*/
745
         sql.append("update xml_replication set last_checked = ");
746 5319 jones
         sql.append(DatabaseService.getInstance().getDBAdapter().toDate(datestr, "MM/DD/YY HH24:MI:SS"));
747 1751 tao
         sql.append(" where server like '").append(server).append("'");
748 1585 tao
         pstmt = dbConn.prepareStatement(sql.toString());
749 2286 tao
750 1585 tao
         pstmt.executeUpdate();
751
         dbConn.commit();
752
         pstmt.close();
753 5014 daigle
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - last_checked updated to "+datestr+" on "
754 2663 sgarg
                                      + server);
755 1585 tao
      }//if
756
      else
757
      {
758 2286 tao
759 5014 daigle
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server "  +
760 2286 tao
                                  server + " in db because couldn't get time "
761 2663 sgarg
                                  );
762 1585 tao
         throw new Exception("Couldn't get time for server "+ server);
763
      }
764 2286 tao
765
    }//try
766 1585 tao
    catch(Exception e)
767
    {
768 5014 daigle
      logMetacat.error("ReplicationHandler.updateLastCheckTimeForSingleServer - " + ReplicationService.METACAT_REPL_ERROR_MSG);
769
      logReplication.error("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server " +
770
                                server + " in db because because " + e.getMessage());
771
      throw new HandlerException("ReplicationHandler.updateLastCheckTimeForSingleServer - "
772
    		  + "Error updating last checked time: " + e.getMessage());
773 1585 tao
    }
774
    finally
775
    {
776
       //return DBConnection
777
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
778
    }//finally
779
  }
780 2286 tao
781
782
783 1585 tao
  /**
784
   * updates xml_catalog with entries from other servers.
785
   */
786
  private void updateCatalog()
787
  {
788 5014 daigle
    logReplication.info("ReplicationHandler.updateCatalog - Start of updateCatalog");
789 1585 tao
    // ReplicationServer object in server list
790
    ReplicationServer replServer = null;
791
    PreparedStatement pstmt = null;
792
    String server = null;
793 2286 tao
794
795 1585 tao
    // Go through each ReplicationServer object in sererlist
796
    for (int j=0; j<serverList.size(); j++)
797 2286 tao
    {
798 5014 daigle
      Vector<Vector<String>> remoteCatalog = new Vector<Vector<String>>();
799
      Vector<String> publicId = new Vector<String>();
800 1585 tao
      try
801
      {
802 1292 tao
        // Get ReplicationServer object from server list
803
        replServer = serverList.serverAt(j);
804
        // Get server name from the ReplicationServer object
805
        server = replServer.getServerName();
806
        // Try to get catalog
807 1011 tao
        URL u = new URL("https://" + server + "?server="+
808 4698 daigle
        MetacatUtil.getLocalReplicationServerName()+"&action=getcatalog");
809 5014 daigle
        logReplication.info("ReplicationHandler.updateCatalog - sending message " + u.toString());
810
        String catxml = ReplicationService.getURLContent(u);
811 2286 tao
812 1292 tao
        // Make sure there are not error, no empty string
813
        if (catxml.indexOf("error")!=-1 || catxml==null||catxml.equals(""))
814
        {
815 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
816 1292 tao
        }
817 5175 daigle
        logReplication.debug("ReplicationHandler.updateCatalog - catxml: " + catxml);
818 590 berkley
        CatalogMessageHandler cmh = new CatalogMessageHandler();
819
        XMLReader catparser = initParser(cmh);
820
        catparser.parse(new InputSource(new StringReader(catxml)));
821
        //parse the returned catalog xml and put it into a vector
822 1585 tao
        remoteCatalog = cmh.getCatalogVect();
823 2286 tao
824 5175 daigle
        // Make sure remoteCatalog is not empty
825 1292 tao
        if (remoteCatalog.isEmpty())
826
        {
827 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
828 1292 tao
        }
829 2286 tao
830 5014 daigle
        String localcatxml = ReplicationService.getCatalogXML();
831 2286 tao
832 1292 tao
        // Make sure local catalog is no empty
833
        if (localcatxml==null||localcatxml.equals(""))
834
        {
835 1585 tao
          throw new Exception("Couldn't get catalog list form server " +server);
836 1292 tao
        }
837 2286 tao
838 590 berkley
        cmh = new CatalogMessageHandler();
839
        catparser = initParser(cmh);
840
        catparser.parse(new InputSource(new StringReader(localcatxml)));
841 5014 daigle
        Vector<Vector<String>> localCatalog = cmh.getCatalogVect();
842 2286 tao
843 590 berkley
        //now we have the catalog from the remote server and this local server
844
        //we now need to compare the two and merge the differences.
845
        //the comparison is base on the public_id fields which is the 4th
846
        //entry in each row vector.
847 5014 daigle
        publicId = new Vector<String>();
848 590 berkley
        for(int i=0; i<localCatalog.size(); i++)
849
        {
850 5014 daigle
          Vector<String> v = new Vector<String>(localCatalog.elementAt(i));
851
          logReplication.info("ReplicationHandler.updateCatalog - v1: " + v.toString());
852 590 berkley
          publicId.add(new String((String)v.elementAt(3)));
853 595 berkley
          //System.out.println("adding " + (String)v.elementAt(3));
854 590 berkley
        }
855 1585 tao
      }//try
856
      catch (Exception e)
857
      {
858 5014 daigle
        logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);
859
        logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
860 1585 tao
                                    server + " because " +e.getMessage());
861
      }//catch
862 2286 tao
863 1585 tao
      for(int i=0; i<remoteCatalog.size(); i++)
864
      {
865
         // DConnection
866
        DBConnection dbConn = null;
867
        // DBConnection checkout serial number
868
        int serialNumber = -1;
869
        try
870 590 berkley
        {
871 1585 tao
            dbConn=DBConnectionPool.
872
                  getDBConnection("ReplicationHandler.updateCatalog");
873
            serialNumber=dbConn.getCheckOutSerialNumber();
874 5014 daigle
            Vector<String> v = remoteCatalog.elementAt(i);
875 1585 tao
            //System.out.println("v2: " + v.toString());
876
            //System.out.println("i: " + i);
877
            //System.out.println("remoteCatalog.size(): " + remoteCatalog.size());
878
            //System.out.println("publicID: " + publicId.toString());
879 5014 daigle
            logReplication.info
880
                              ("ReplicationHandler.updateCatalog - v.elementAt(3): " + (String)v.elementAt(3));
881 1585 tao
           if(!publicId.contains(v.elementAt(3)))
882
           { //so we don't have this public id in our local table so we need to
883
             //add it.
884
             //System.out.println("in if");
885
             StringBuffer sql = new StringBuffer();
886
             sql.append("insert into xml_catalog (entry_type, source_doctype, ");
887
             sql.append("target_doctype, public_id, system_id) values (?,?,?,");
888
             sql.append("?,?)");
889
             //System.out.println("sql: " + sql.toString());
890
             pstmt = dbConn.prepareStatement(sql.toString());
891
             pstmt.setString(1, (String)v.elementAt(0));
892
             pstmt.setString(2, (String)v.elementAt(1));
893
             pstmt.setString(3, (String)v.elementAt(2));
894
             pstmt.setString(4, (String)v.elementAt(3));
895
             pstmt.setString(5, (String)v.elementAt(4));
896
             pstmt.execute();
897
             pstmt.close();
898 5014 daigle
             logReplication.info("ReplicationHandler.updateCatalog - Success fully to insert new publicid "+
899 1585 tao
                               (String)v.elementAt(3) + " from server"+server);
900
           }
901 590 berkley
        }
902 1585 tao
        catch(Exception e)
903
        {
904 5014 daigle
           logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);
905
           logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
906 1585 tao
                                    server + " because " +e.getMessage());
907
        }//catch
908
        finally
909
        {
910
           DBConnectionPool.returnDBConnection(dbConn, serialNumber);
911 5175 daigle
        }//finally
912 1585 tao
      }//for remote catalog
913
    }//for server list
914 5014 daigle
    logReplication.info("End of updateCatalog");
915 590 berkley
  }
916 2286 tao
917 590 berkley
  /**
918 579 berkley
   * Method that returns true if docid has already been "deleted" from metacat.
919 582 berkley
   * This method really implements a truth table for deleted documents
920 590 berkley
   * The table is (a docid in one of the tables is represented by the X):
921 582 berkley
   * xml_docs      xml_revs      deleted?
922
   * ------------------------------------
923
   *   X             X             FALSE
924
   *   X             _             FALSE
925
   *   _             X             TRUE
926
   *   _             _             TRUE
927 579 berkley
   */
928 5014 daigle
  private static boolean alreadyDeleted(String docid) throws HandlerException
929 579 berkley
  {
930 1217 tao
    DBConnection dbConn = null;
931
    int serialNumber = -1;
932
    PreparedStatement pstmt = null;
933 579 berkley
    try
934
    {
935 1217 tao
      dbConn=DBConnectionPool.
936
                  getDBConnection("ReplicationHandler.alreadyDeleted");
937
      serialNumber=dbConn.getCheckOutSerialNumber();
938 582 berkley
      boolean xml_docs = false;
939
      boolean xml_revs = false;
940 2286 tao
941 579 berkley
      StringBuffer sb = new StringBuffer();
942 582 berkley
      sb.append("select docid from xml_revisions where docid like '");
943 579 berkley
      sb.append(docid).append("'");
944 1217 tao
      pstmt = dbConn.prepareStatement(sb.toString());
945 579 berkley
      pstmt.execute();
946
      ResultSet rs = pstmt.getResultSet();
947
      boolean tablehasrows = rs.next();
948
      if(tablehasrows)
949
      {
950 582 berkley
        xml_revs = true;
951
      }
952 2286 tao
953 582 berkley
      sb = new StringBuffer();
954
      sb.append("select docid from xml_documents where docid like '");
955
      sb.append(docid).append("'");
956 667 berkley
      pstmt.close();
957 1217 tao
      pstmt = dbConn.prepareStatement(sb.toString());
958
      //increase usage count
959
      dbConn.increaseUsageCount(1);
960 582 berkley
      pstmt.execute();
961
      rs = pstmt.getResultSet();
962
      tablehasrows = rs.next();
963 667 berkley
      pstmt.close();
964 582 berkley
      if(tablehasrows)
965
      {
966
        xml_docs = true;
967
      }
968 2286 tao
969 582 berkley
      if(xml_docs && xml_revs)
970
      {
971
        return false;
972
      }
973
      else if(xml_docs && !xml_revs)
974
      {
975
        return false;
976
      }
977
      else if(!xml_docs && xml_revs)
978
      {
979 579 berkley
        return true;
980
      }
981 582 berkley
      else if(!xml_docs && !xml_revs)
982
      {
983
        return true;
984
      }
985 579 berkley
    }
986
    catch(Exception e)
987
    {
988 5014 daigle
      logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);
989
      logReplication.error("ReplicationHandler.alreadyDeleted - general error in alreadyDeleted: " +
990 2663 sgarg
                          e.getMessage());
991 5014 daigle
      throw new HandlerException("ReplicationHandler.alreadyDeleted - general error: "
992
    		  + e.getMessage());
993 579 berkley
    }
994 667 berkley
    finally
995
    {
996 1217 tao
      try
997
      {
998
        pstmt.close();
999
      }//try
1000
      catch (SQLException ee)
1001
      {
1002 5014 daigle
    	logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1003
        logReplication.error("ReplicationHandler.alreadyDeleted - Error in replicationHandler.alreadyDeleted "+
1004 2663 sgarg
                          "to close pstmt: "+ee.getMessage());
1005 5014 daigle
        throw new HandlerException("ReplicationHandler.alreadyDeleted - SQL error when closing prepared statement: "
1006
      		  + ee.getMessage());
1007 1217 tao
      }//catch
1008
      finally
1009
      {
1010
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1011
      }//finally
1012
    }//finally
1013 579 berkley
    return false;
1014
  }
1015 533 berkley
1016 2286 tao
1017 533 berkley
  /**
1018 574 berkley
   * Method to initialize the message parser
1019
   */
1020
  public static XMLReader initParser(DefaultHandler dh)
1021 5014 daigle
          throws HandlerException
1022 574 berkley
  {
1023
    XMLReader parser = null;
1024
1025
    try {
1026
      ContentHandler chandler = dh;
1027
1028
      // Get an instance of the parser
1029 4213 daigle
      String parserName = PropertyService.getProperty("xml.saxparser");
1030 574 berkley
      parser = XMLReaderFactory.createXMLReader(parserName);
1031
1032
      // Turn off validation
1033
      parser.setFeature("http://xml.org/sax/features/validation", false);
1034 2286 tao
1035 574 berkley
      parser.setContentHandler((ContentHandler)chandler);
1036
      parser.setErrorHandler((ErrorHandler)chandler);
1037
1038 5014 daigle
    } catch (SAXException se) {
1039
      throw new HandlerException("ReplicationHandler.initParser - Sax error when "
1040
    		  + " initializing parser: " + se.getMessage());
1041
    } catch (PropertyNotFoundException pnfe) {
1042
        throw new HandlerException("ReplicationHandler.initParser - Property error when "
1043
      		  + " getting parser name: " + pnfe.getMessage());
1044
    }
1045 574 berkley
1046
    return parser;
1047
  }
1048 2286 tao
1049 2555 tao
  /**
1050 5175 daigle
	 * This method will combine given time string(in short format) to current
1051 5014 daigle
	 * date. If the given time (e.g 10:00 AM) passed the current time (e.g 2:00
1052
	 * PM Aug 21, 2005), then the time will set to second day, 10:00 AM Aug 22,
1053
	 * 2005. If the given time (e.g 10:00 AM) haven't passed the current time
1054
	 * (e.g 8:00 AM Aug 21, 2005) The time will set to be 10:00 AM Aug 21, 2005.
1055
	 *
1056
	 * @param givenTime
1057
	 *            the format should be "10:00 AM " or "2:00 PM"
1058
	 * @return
1059
	 * @throws Exception
1060
	 */
1061
	public static Date combinateCurrentDateAndGivenTime(String givenTime) throws HandlerException
1062 2555 tao
  {
1063 5014 daigle
	  try {
1064 2555 tao
     Date givenDate = parseTime(givenTime);
1065
     Date newDate = null;
1066
     Date now = new Date();
1067
     String currentTimeString = getTimeString(now);
1068
     Date currentTime = parseTime(currentTimeString);
1069
     if ( currentTime.getTime() >= givenDate.getTime())
1070
     {
1071 5014 daigle
        logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today already pass the given time, we should set it as tomorrow");
1072 2555 tao
        String dateAndTime = getDateString(now) + " " + givenTime;
1073
        Date combinationDate = parseDateTime(dateAndTime);
1074
        // new date should plus 24 hours to make is the second day
1075
        newDate = new Date(combinationDate.getTime()+24*3600*1000);
1076
     }
1077
     else
1078
     {
1079 5014 daigle
         logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today haven't pass the given time, we should it as today");
1080 2555 tao
         String dateAndTime = getDateString(now) + " " + givenTime;
1081
         newDate = parseDateTime(dateAndTime);
1082
     }
1083 5014 daigle
     logReplication.warn("ReplicationHandler.combinateCurrentDateAndGivenTime - final setting time is "+ newDate.toString());
1084 2555 tao
     return newDate;
1085 5014 daigle
	  } catch (ParseException pe) {
1086
		  throw new HandlerException("ReplicationHandler.combinateCurrentDateAndGivenTime - "
1087
				  + "parsing error: "  + pe.getMessage());
1088
	  }
1089 2555 tao
  }
1090 2286 tao
1091 2555 tao
  /*
1092 5014 daigle
	 * parse a given string to Time in short format. For example, given time is
1093
	 * 10:00 AM, the date will be return as Jan 1 1970, 10:00 AM
1094
	 */
1095
  private static Date parseTime(String timeString) throws ParseException
1096 2555 tao
  {
1097
    DateFormat format = DateFormat.getTimeInstance(DateFormat.SHORT);
1098
    Date time = format.parse(timeString);
1099 5014 daigle
    logReplication.info("ReplicationHandler.parseTime - Date string is after parse a time string "
1100 2663 sgarg
                              +time.toString());
1101 2555 tao
    return time;
1102
1103
  }
1104
1105
  /*
1106 5175 daigle
   * Parse a given string to date and time. Date format is long and time
1107 2555 tao
   * format is short.
1108
   */
1109 5014 daigle
  private static Date parseDateTime(String timeString) throws ParseException
1110 2555 tao
  {
1111
    DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT);
1112
    Date time = format.parse(timeString);
1113 5014 daigle
    logReplication.info("ReplicationHandler.parseDateTime - Date string is after parse a time string "+
1114 2663 sgarg
                             time.toString());
1115 2555 tao
    return time;
1116
  }
1117
1118
  /*
1119
   * Get a date string from a Date object. The date format will be long
1120
   */
1121
  private static String getDateString(Date now)
1122
  {
1123
     DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
1124
     String s = df.format(now);
1125 5014 daigle
     logReplication.info("ReplicationHandler.getDateString - Today is " + s);
1126 2555 tao
     return s;
1127
  }
1128
1129
  /*
1130
   * Get a time string from a Date object, the time format will be short
1131
   */
1132
  private static String getTimeString(Date now)
1133
  {
1134
     DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
1135
     String s = df.format(now);
1136 5014 daigle
     logReplication.info("ReplicationHandler.getTimeString - Time is " + s);
1137 2555 tao
     return s;
1138
  }
1139 2608 tao
1140
1141
  /*
1142 4080 daigle
	 * This method will go through the docid list both in xml_Documents table
1143
	 * and in xml_revisions table @author tao
1144
	 */
1145 5014 daigle
	private void handleDocList(Vector<Vector<String>> docList, String tableName) {
1146 4080 daigle
		boolean dataFile = false;
1147
		for (int j = 0; j < docList.size(); j++) {
1148
			// initial dataFile is false
1149
			dataFile = false;
1150
			// w is information for one document, information contain
1151
			// docid, rev, server or datafile.
1152 5014 daigle
			Vector<String> w = new Vector<String>(docList.elementAt(j));
1153 4080 daigle
			// Check if the vector w contain "datafile"
1154
			// If it has, this document is data file
1155
			try {
1156 4173 daigle
				if (w.contains((String) PropertyService.getProperty("replication.datafileflag"))) {
1157 4080 daigle
					dataFile = true;
1158
				}
1159
			} catch (PropertyNotFoundException pnfe) {
1160 5014 daigle
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1161
				logReplication.error("ReplicationHandler.handleDocList - Could not retrieve data file flag property.  "
1162 4080 daigle
						+ "Leaving as false: " + pnfe.getMessage());
1163
			}
1164
			// System.out.println("w: " + w.toString());
1165
			// Get docid
1166
			String docid = (String) w.elementAt(0);
1167 5014 daigle
			logReplication.info("docid: " + docid);
1168 4080 daigle
			// Get revision number
1169
			int rev = Integer.parseInt((String) w.elementAt(1));
1170 5014 daigle
			logReplication.info("rev: " + rev);
1171 5175 daigle
			// Get remote server name (it is may not be doc home server because
1172 4080 daigle
			// the new hub feature
1173
			String remoteServer = (String) w.elementAt(2);
1174
			remoteServer = remoteServer.trim();
1175 2608 tao
1176 4080 daigle
			try {
1177
				if (tableName.equals(DocumentImpl.DOCUMENTTABLE)) {
1178
					handleDocInXMLDocuments(docid, rev, remoteServer, dataFile);
1179
				} else if (tableName.equals(DocumentImpl.REVISIONTABLE)) {
1180
					handleDocInXMLRevisions(docid, rev, remoteServer, dataFile);
1181
				} else {
1182
					continue;
1183
				}
1184 2608 tao
1185 4861 daigle
			} catch (Exception e) {
1186 5014 daigle
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1187
				logReplication.error("ReplicationHandler.handleDocList - error to handle update doc in " + tableName
1188 4861 daigle
						+ " in time replication" + e.getMessage());
1189 4080 daigle
				continue;
1190
			}
1191 5175 daigle
1192
	        if (_xmlDocQueryCount > 0 && (_xmlDocQueryCount % 100) == 0) {
1193
	        	logMetacat.debug("ReplicationHandler.update - xml_doc query count: " + _xmlDocQueryCount +
1194
	        			", xml_doc avg query time: " + (_xmlDocQueryTime / _xmlDocQueryCount));
1195
	        }
1196
1197
	        if (_xmlRevQueryCount > 0 && (_xmlRevQueryCount % 100) == 0) {
1198
	        	logMetacat.debug("ReplicationHandler.update - xml_rev query count: " + _xmlRevQueryCount +
1199
	        			", xml_rev avg query time: " + (_xmlRevQueryTime / _xmlRevQueryCount));
1200
	        }
1201 4080 daigle
1202
		}// for update docs
1203
1204
	}
1205 2608 tao
1206
   /*
1207 4080 daigle
	 * This method will handle doc in xml_documents table.
1208
	 */
1209 2608 tao
   private void handleDocInXMLDocuments(String docid, int rev, String remoteServer, boolean dataFile)
1210 5014 daigle
                                        throws HandlerException
1211 2608 tao
   {
1212
       // compare the update rev and local rev to see what need happen
1213
       int localrev = -1;
1214
       String action = null;
1215
       boolean flag = false;
1216
       try
1217
       {
1218 5175 daigle
    	 long docQueryStartTime = System.currentTimeMillis();
1219 2641 tao
         localrev = DBUtil.getLatestRevisionInDocumentTable(docid);
1220 5175 daigle
         long docQueryEndTime = System.currentTimeMillis();
1221
         _xmlDocQueryTime += (docQueryEndTime - docQueryStartTime);
1222
         _xmlDocQueryCount++;
1223 2608 tao
       }
1224
       catch (SQLException e)
1225
       {
1226 5014 daigle
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1227
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1228 2663 sgarg
                                " be found because " + e.getMessage());
1229 5014 daigle
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - " + DOCERRORNUMBER+"Docid "+ docid + " could not be "+
1230 2608 tao
                 "written because error happend to find it's local revision");
1231 2739 tao
         DOCERRORNUMBER++;
1232 5014 daigle
         throw new HandlerException ("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1233
                 " be found: " + e.getMessage());
1234 2608 tao
       }
1235 5014 daigle
       logReplication.info("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " is "+
1236 2663 sgarg
                               localrev);
1237 2608 tao
1238
       //check the revs for an update because this document is in the
1239
       //local DB, it might be out of date.
1240
       if (localrev == -1)
1241
       {
1242 2713 tao
          // check if the revision is in the revision table
1243 5014 daigle
    	   Vector<Integer> localRevVector = null;
1244
    	 try {
1245 5175 daigle
        	 long revQueryStartTime = System.currentTimeMillis();
1246 5014 daigle
    		 localRevVector = DBUtil.getRevListFromRevisionTable(docid);
1247 5175 daigle
             long revQueryEndTime = System.currentTimeMillis();
1248
             _xmlRevQueryTime += (revQueryEndTime - revQueryStartTime);
1249
             _xmlRevQueryCount++;
1250 5014 daigle
    	 } catch (SQLException sqle) {
1251
    		 throw new HandlerException("ReplicationHandler.handleDocInXMLDocuments - SQL error "
1252
    				 + " when getting rev list for docid: " + docid + " : " + sqle.getMessage());
1253
    	 }
1254 2713 tao
         if (localRevVector != null && localRevVector.contains(new Integer(rev)))
1255
         {
1256
             // this version was deleted, so don't need replicate
1257
             flag = false;
1258
         }
1259
         else
1260
         {
1261
           //insert this document as new because it is not in the local DB
1262
           action = "INSERT";
1263
           flag = true;
1264
         }
1265 2608 tao
       }
1266
       else
1267
       {
1268
         if(localrev == rev)
1269
         {
1270
           // Local meatacat has the same rev to remote host, don't need
1271
           // update and flag set false
1272
           flag = false;
1273
         }
1274
         else if(localrev < rev)
1275
         {
1276
           //this document needs to be updated so send an read request
1277
           action = "UPDATE";
1278
           flag = true;
1279
         }
1280
       }
1281 2641 tao
1282 5014 daigle
       String accNumber = null;
1283
       try {
1284
    	   accNumber = docid + PropertyService.getProperty("document.accNumSeparator") + rev;
1285
       } catch (PropertyNotFoundException pnfe) {
1286
    	   throw new HandlerException("ReplicationHandler.handleDocInXMLDocuments - error getting "
1287
    			   + "account number separator : " + pnfe.getMessage());
1288
       }
1289 2608 tao
       // this is non-data file
1290
       if(flag && !dataFile)
1291
       {
1292
         try
1293
         {
1294 2641 tao
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1295 2608 tao
         }
1296 5014 daigle
         catch(HandlerException he)
1297 2608 tao
         {
1298
           // skip this document
1299 5014 daigle
           throw he;
1300 2608 tao
         }
1301
       }//if for non-data file
1302
1303
        // this is for data file
1304
       if(flag && dataFile)
1305
       {
1306
         try
1307
         {
1308 2641 tao
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1309 2608 tao
         }
1310 5014 daigle
         catch(HandlerException he)
1311 2608 tao
         {
1312 5175 daigle
           // skip this data file
1313 5014 daigle
           throw he;
1314 2608 tao
         }
1315
1316 5175 daigle
       }//for data file
1317 2608 tao
   }
1318
1319
   /*
1320
    * This method will handle doc in xml_documents table.
1321
    */
1322
   private void handleDocInXMLRevisions(String docid, int rev, String remoteServer, boolean dataFile)
1323 5014 daigle
                                        throws HandlerException
1324 2608 tao
   {
1325
       // compare the update rev and local rev to see what need happen
1326 5014 daigle
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - In handle repliation revsion table");
1327
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - the docid is "+ docid);
1328
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - The rev is "+rev);
1329
       Vector<Integer> localrev = null;
1330 2608 tao
       String action = "INSERT";
1331
       boolean flag = false;
1332
       try
1333
       {
1334 5175 daigle
      	 long revQueryStartTime = System.currentTimeMillis();
1335 2608 tao
         localrev = DBUtil.getRevListFromRevisionTable(docid);
1336 5175 daigle
         long revQueryEndTime = System.currentTimeMillis();
1337
         _xmlRevQueryTime += (revQueryEndTime - revQueryStartTime);
1338
         _xmlRevQueryCount++;
1339 2608 tao
       }
1340 5014 daigle
       catch (SQLException sqle)
1341 2608 tao
       {
1342 5014 daigle
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1343
         logReplication.error("ReplicationHandler.handleDocInXMLRevisions - Local rev for docid "+ docid + " could not "+
1344
                                " be found because " + sqle.getMessage());
1345 2739 tao
         REVERRORNUMBER++;
1346 5014 daigle
         throw new HandlerException ("ReplicationHandler.handleDocInXMLRevisions - SQL exception getting rev list: "
1347
        		 + sqle.getMessage());
1348 2608 tao
       }
1349 5014 daigle
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - rev list in xml_revision table for docid "+ docid + " is "+
1350 2663 sgarg
                               localrev.toString());
1351 2608 tao
1352
       // if the rev is not in the xml_revision, we need insert it
1353
       if (!localrev.contains(new Integer(rev)))
1354
       {
1355
           flag = true;
1356
       }
1357 2641 tao
1358 5014 daigle
       String accNumber = null;
1359
       try {
1360
    	   accNumber = docid + PropertyService.getProperty("document.accNumSeparator") + rev;
1361
       } catch (PropertyNotFoundException pnfe) {
1362
    	   throw new HandlerException("ReplicationHandler.handleDocInXMLRevisions - error getting "
1363
    			   + "account number separator : " + pnfe.getMessage());
1364
       }
1365 2608 tao
       // this is non-data file
1366
       if(flag && !dataFile)
1367
       {
1368
         try
1369
         {
1370 2641 tao
1371
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1372 2608 tao
         }
1373 5014 daigle
         catch(HandlerException he)
1374 2608 tao
         {
1375
           // skip this document
1376 5014 daigle
           throw he;
1377 2608 tao
         }
1378
       }//if for non-data file
1379
1380
        // this is for data file
1381
       if(flag && dataFile)
1382
       {
1383
         try
1384
         {
1385 2641 tao
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1386 2608 tao
         }
1387 5014 daigle
         catch(HandlerException he)
1388 2608 tao
         {
1389 5175 daigle
           // skip this data file
1390 5014 daigle
           throw he;
1391 2608 tao
         }
1392
1393 5175 daigle
       }//for data file
1394 2608 tao
   }
1395 3234 tao
1396
   /*
1397
    * Return a ip address for given url
1398
    */
1399
   private String getIpFromURL(URL url)
1400
   {
1401
	   String ip = null;
1402
	   try
1403
	   {
1404
	      InetAddress address = InetAddress.getByName(url.getHost());
1405
	      ip = address.getHostAddress();
1406
	   }
1407
	   catch(UnknownHostException e)
1408
	   {
1409 5014 daigle
		   logMetacat.error("ReplicationHandler.getIpFromURL - " + ReplicationService.METACAT_REPL_ERROR_MSG);
1410
		   logReplication.error("ReplicationHandler.getIpFromURL - Error in get ip address for host: "
1411 3234 tao
                   +e.getMessage());
1412
	   }
1413
1414
	   return ip;
1415
   }
1416 2608 tao
1417 522 berkley
}