Project

General

Profile

1
/**
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: berkley $'
9
 *     '$Date: 2010-04-26 16:11:12 -0700 (Mon, 26 Apr 2010) $'
10
 * '$Revision: 5324 $'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26

    
27
package edu.ucsb.nceas.metacat.replication;
28

    
29
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
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
36
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
37
import edu.ucsb.nceas.metacat.database.DBConnection;
38
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
39
import edu.ucsb.nceas.metacat.database.DatabaseService;
40
import edu.ucsb.nceas.metacat.properties.PropertyService;
41
import edu.ucsb.nceas.metacat.shared.HandlerException;
42
import edu.ucsb.nceas.metacat.util.MetacatUtil;
43
import edu.ucsb.nceas.metacat.IdentifierManager;
44
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
45

    
46
import java.sql.*;
47
import java.util.*;
48
import java.util.Date;
49
import java.io.*;
50
import java.net.*;
51
import java.text.*;
52

    
53
import org.apache.log4j.Logger;
54
import org.xml.sax.ContentHandler;
55
import org.xml.sax.ErrorHandler;
56
import org.xml.sax.InputSource;
57
import org.xml.sax.SAXException;
58
import org.xml.sax.XMLReader;
59
import org.xml.sax.helpers.XMLReaderFactory;
60
import org.xml.sax.helpers.DefaultHandler;
61

    
62

    
63

    
64
/**
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
  int serverCheckCode = 1;
72
  ReplicationServerList serverList = null;
73
  //PrintWriter out;
74
//  private static final AbstractDatabase dbAdapter = MetacatUtil.dbAdapter;
75
  private static Logger logReplication = Logger.getLogger("ReplicationLogging");
76
  private static Logger logMetacat = Logger.getLogger(ReplicationHandler.class);
77
  private static int DOCINSERTNUMBER = 1;
78
  private static int DOCERRORNUMBER  = 1;
79
  private static int REVINSERTNUMBER = 1;
80
  private static int REVERRORNUMBER  = 1;
81
  
82
  private static int _xmlDocQueryCount = 0;
83
  private static int _xmlRevQueryCount = 0;
84
  private static long _xmlDocQueryTime = 0;
85
  private static long _xmlRevQueryTime = 0;
86
  
87
  
88
  public ReplicationHandler()
89
  {
90
    //this.out = o;
91
    serverList = new ReplicationServerList();
92
  }
93

    
94
  public ReplicationHandler(int serverCheckCode)
95
  {
96
    //this.out = o;
97
    this.serverCheckCode = serverCheckCode;
98
    serverList = new ReplicationServerList();
99
  }
100

    
101
  /**
102
   * Method that implements TimerTask.run().  It runs whenever the timer is
103
   * fired.
104
   */
105
  public void run()
106
  {
107
    //find out the last_checked time of each server in the server list and
108
    //send a query to each server to see if there are any documents in
109
    //xml_documents with an update_date > last_checked
110
	  
111
      //if serverList is null, metacat don't need to replication
112
      if (serverList==null||serverList.isEmpty())
113
      {
114
        return;
115
      }
116
      updateCatalog();
117
      update();
118
      //conn.close();
119
  }
120

    
121
  /**
122
   * Method that uses revision tagging for replication instead of update_date.
123
   */
124
  private void update()
125
  {
126
	  
127
	  _xmlDocQueryCount = 0;
128
	  _xmlRevQueryCount = 0;
129
	  _xmlDocQueryTime = 0;
130
	  _xmlRevQueryTime = 0;
131
    /*
132
     Pseudo-algorithm
133
     - request a doc list from each server in xml_replication
134
     - check the rev number of each of those documents agains the
135
       documents in the local database
136
     - pull any documents that have a lesser rev number on the local server
137
       from the remote server
138
     - delete any documents that still exist in the local xml_documents but
139
       are in the deletedDocuments tag of the remote host response.
140
     - update last_checked to keep track of the last time it was checked.
141
       (this info is theoretically not needed using this system but probably
142
       should be kept anyway)
143
    */
144

    
145
    ReplicationServer replServer = null; // Variable to store the
146
                                        // ReplicationServer got from
147
                                        // Server list
148
    String server = null; // Variable to store server name
149
//    String update;
150
    Vector<String> responses = new Vector<String>();
151
    URL u;
152
    long replicationStartTime = System.currentTimeMillis();
153
    long timeToGetServerList = 0;
154
    
155
    //Check for every server in server list to get updated list and put
156
    // them in to response
157
    long startTimeToGetServers = System.currentTimeMillis();
158
    for (int i=0; i<serverList.size(); i++)
159
    {
160
        // Get ReplicationServer object from server list
161
        replServer = serverList.serverAt(i);
162
        // Get server name from ReplicationServer object
163
        server = replServer.getServerName().trim();
164
        String result = null;
165
        logReplication.info("ReplicationHandler.update - full update started to: " + server);
166
        // Send command to that server to get updated docid information
167
        try
168
        {
169
          u = new URL("https://" + server + "?server="
170
          +MetacatUtil.getLocalReplicationServerName()+"&action=update");
171
          logReplication.info("ReplicationHandler.update - Sending infomation " +u.toString());
172
          result = ReplicationService.getURLContent(u);
173
        }
174
        catch (Exception e)
175
        {
176
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
177
          logReplication.error( "ReplicationHandler.update - Failed to get updated doc list "+
178
                       "for server " + server + " because "+e.getMessage());
179
          continue;
180
        }
181

    
182
        //logReplication.info("ReplicationHandler.update - docid: "+server+" "+result);
183
        //check if result have error or not, if has skip it.
184
        if (result.indexOf("<error>")!=-1 && result.indexOf("</error>")!=-1)
185
        {
186
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
187
          logReplication.error( "ReplicationHandler.update - Failed to get updated doc list "+
188
                       "for server " + server + " because "+result);
189
          continue;
190
        }
191
        //Add result to vector
192
        responses.add(result);
193
    }
194
    timeToGetServerList = System.currentTimeMillis() - startTimeToGetServers;
195

    
196
    //make sure that there is updated file list
197
    //If response is null, metacat don't need do anything
198
    if (responses==null || responses.isEmpty())
199
    {
200
    	logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
201
        logReplication.info( "ReplicationHandler.update - No updated doc list for "+
202
                           "every server and failed to replicate");
203
        return;
204
    }
205

    
206

    
207
    //logReplication.info("ReplicationHandler.update - Responses from remote metacat about updated "+
208
    //               "document information: "+ responses.toString());
209
    
210
    long totalServerListParseTime = 0;
211
    // go through response vector(it contains updated vector and delete vector
212
    for(int i=0; i<responses.size(); i++)
213
    {
214
    	long startServerListParseTime = System.currentTimeMillis();
215
    	XMLReader parser;
216
    	ReplMessageHandler message = new ReplMessageHandler();
217
    	try
218
        {
219
          parser = initParser(message);
220
        }
221
        catch (Exception e)
222
        {
223
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
224
          logReplication.error("ReplicationHandler.update - Failed to replicate becaue couldn't " +
225
                                " initParser for message and " +e.getMessage());
226
           // stop replication
227
           return;
228
        }
229
    	
230
        try
231
        {
232
          parser.parse(new InputSource(
233
                     new StringReader(
234
                     (String)(responses.elementAt(i)))));
235
        }
236
        catch(Exception e)
237
        {
238
          logMetacat.error("ReplicationHandler.update - " + ReplicationService.METACAT_REPL_ERROR_MSG);
239
          logReplication.error("ReplicationHandler.update - Couldn't parse one responses "+
240
                                   "because "+ e.getMessage());
241
          continue;
242
        }
243
        //v is the list of updated documents
244
        Vector<Vector<String>> updateList = new Vector<Vector<String>>(message.getUpdatesVect());
245
        logReplication.info("ReplicationHandler.update - The document list size is "+updateList.size()+ " from "+message.getServerName());
246
        //System.out.println("v: " + v.toString());
247
        //d is the list of deleted documents
248
        Vector<Vector<String>> deleteList = new Vector<Vector<String>>(message.getDeletesVect());
249
        //System.out.println("d: " + d.toString());
250
        logReplication.info("ReplicationHandler.update - Update vector size: "+ updateList.size()+" from "+message.getServerName());
251
        logReplication.info("ReplicationHandler.update - Delete vector size: "+ deleteList.size()+" from "+message.getServerName());
252
        logReplication.info("ReplicationHandler.update - The delete document list size is "+deleteList.size()+" from "+message.getServerName());
253
        // go though every element in updated document vector
254
        handleDocList(updateList, DocumentImpl.DOCUMENTTABLE);
255
        //handle deleted docs
256
        for(int k=0; k<deleteList.size(); k++)
257
        { //delete the deleted documents;
258
          Vector<String> w = new Vector<String>(deleteList.elementAt(k));
259
          String docId = (String)w.elementAt(0);
260
          try
261
          {
262
            handleDeleteSingleDocument(docId, server);
263
          }
264
          catch (Exception ee)
265
          {
266
            continue;
267
          }
268
        }//for delete docs
269
        
270
        // handle replicate doc in xml_revision
271
        Vector<Vector<String>> revisionList = new Vector<Vector<String>>(message.getRevisionsVect());
272
        logReplication.info("ReplicationHandler.update - The revision document list size is "+revisionList.size()+ " from "+message.getServerName());
273
        handleDocList(revisionList, DocumentImpl.REVISIONTABLE);
274
        DOCINSERTNUMBER = 1;
275
        DOCERRORNUMBER  = 1;
276
        REVINSERTNUMBER = 1;
277
        REVERRORNUMBER  = 1;
278
        
279
        totalServerListParseTime += (System.currentTimeMillis() - startServerListParseTime);
280
    }//for response
281

    
282
    //updated last_checked
283
    for (int i=0;i<serverList.size(); i++)
284
    {
285
       // Get ReplicationServer object from server list
286
       replServer = serverList.serverAt(i);
287
       try
288
       {
289
         updateLastCheckTimeForSingleServer(replServer);
290
       }
291
       catch(Exception e)
292
       {
293
         continue;
294
       }
295
    }//for
296
    
297
    long replicationEndTime = System.currentTimeMillis();
298
    logMetacat.debug("ReplicationHandler.update - Total replication time: " + 
299
    		(replicationEndTime - replicationStartTime));
300
    logMetacat.debug("ReplicationHandler.update - time to get server list: " + 
301
    		timeToGetServerList);
302
    logMetacat.debug("ReplicationHandler.update - server list parse time: " + 
303
    		totalServerListParseTime);
304
    logMetacat.debug("ReplicationHandler.update - 'in xml_documents' total query count: " + 
305
    		_xmlDocQueryCount);
306
    logMetacat.debug("ReplicationHandler.update - 'in xml_documents' total query time: " + 
307
    		_xmlDocQueryTime + " ms");
308
    logMetacat.debug("ReplicationHandler.update - 'in xml_revisions' total query count: " + 
309
    		_xmlRevQueryCount);
310
    logMetacat.debug("ReplicationHandler.update - 'in xml_revisions' total query time: " + 
311
    		_xmlRevQueryTime + " ms");;
312

    
313
  }//update
314

    
315
  /* Handle replicate single xml document*/
316
  private void handleSingleXMLDocument(String remoteserver, String actions,
317
                                       String accNumber, String tableName)
318
               throws HandlerException
319
  {
320
    DBConnection dbConn = null;
321
    int serialNumber = -1;
322
    try
323
    {
324
      // Get DBConnection from pool
325
      dbConn=DBConnectionPool.
326
                  getDBConnection("ReplicationHandler.handleSingleXMLDocument");
327
      serialNumber=dbConn.getCheckOutSerialNumber();
328
      //if the document needs to be updated or inserted, this is executed
329
      String readDocURLString = "https://" + remoteserver + "?server="+
330
              MetacatUtil.getLocalReplicationServerName()+"&action=read&docid="+accNumber;
331
      readDocURLString = MetacatUtil.replaceWhiteSpaceForURL(readDocURLString);
332
      URL u = new URL(readDocURLString);
333

    
334
      // Get docid content
335
      String newxmldoc = ReplicationService.getURLContent(u);
336
      // If couldn't get skip it
337
      if ( newxmldoc.indexOf("<error>")!= -1 && newxmldoc.indexOf("</error>")!=-1)
338
      {
339
         throw new HandlerException("ReplicationHandler.handleSingleXMLDocument - " + newxmldoc);
340
      }
341
      //logReplication.info("xml documnet:");
342
      //logReplication.info(newxmldoc);
343

    
344
      // Try get the docid info from remote server
345
      DocInfoHandler dih = new DocInfoHandler();
346
      XMLReader docinfoParser = initParser(dih);
347
      String docInfoURLStr = "https://" + remoteserver +
348
                       "?server="+MetacatUtil.getLocalReplicationServerName()+
349
                       "&action=getdocumentinfo&docid="+accNumber;
350
      docInfoURLStr = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLStr);
351
      URL docinfoUrl = new URL(docInfoURLStr);
352
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - Sending message: " +
353
                                                  docinfoUrl.toString());
354
      String docInfoStr = ReplicationService.getURLContent(docinfoUrl);
355
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
356
      Hashtable<String, String> docinfoHash = dih.getDocInfo();
357
      // Get home server of the docid
358
      String docHomeServer = docinfoHash.get("home_server");
359
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - doc home server in repl: "+docHomeServer);
360
      String createdDate = docinfoHash.get("date_created");
361
      String updatedDate = docinfoHash.get("date_updated");
362
      //docid should include rev number too
363
      /*String accnum=docId+util.getProperty("document.accNumSeparator")+
364
                                              (String)docinfoHash.get("rev");*/
365
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - docid in repl: "+accNumber);
366
      String docType = docinfoHash.get("doctype");
367
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - doctype in repl: "+docType);
368

    
369
      String parserBase = null;
370
      // this for eml2 and we need user eml2 parser
371
      if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_0NAMESPACE))
372
      {
373
         parserBase = DocumentImpl.EML200;
374
      }
375
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_0_1NAMESPACE))
376
      {
377
        parserBase = DocumentImpl.EML200;
378
      }
379
      else if (docType != null && (docType.trim()).equals(DocumentImpl.EML2_1_0NAMESPACE))
380
      {
381
        parserBase = DocumentImpl.EML210;
382
      }
383
      // Write the document into local host
384
      DocumentImplWrapper wrapper = new DocumentImplWrapper(parserBase, false);
385
      String newDocid = wrapper.writeReplication(dbConn,
386
                              newxmldoc,
387
                              docinfoHash.get("public_access"),
388
                              null,  /* the dtd text */
389
                              actions,
390
                              accNumber,
391
                              docinfoHash.get("user_owner"),
392
                              null, /* null for groups[] */
393
                              docHomeServer,
394
                              remoteserver, tableName, true,// true is for time replication 
395
                              createdDate,
396
                              updatedDate);
397
      
398
      //process extra access rules 
399
      Vector<XMLAccessDAO> xmlAccessDAOList = dih.getAccessControlList();
400
      if (xmlAccessDAOList != null) {
401
      	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(accNumber);
402
      	for (XMLAccessDAO xmlAccessDAO : xmlAccessDAOList) {
403
      		if (!acfsf.accessControlExists(xmlAccessDAO)) {
404
      			acfsf.insertPermissions(xmlAccessDAO);
405
      		}
406
          }
407
      }
408
      
409
      //process guid
410
      logReplication.debug("Processing guid information from docinfoHash: " + docinfoHash.toString());
411
      String guid = docinfoHash.get("guid");
412
      IdentifierManager idman = IdentifierManager.getInstance();
413
      if(guid != null && !idman.identifierExists(guid))
414
      { //if the guid was passed in, put it in the identifiers table
415
        logReplication.debug("Creating guid/docid mapping for docid " + 
416
          docinfoHash.get("docid") + " and guid: " + guid);
417
        idman.createMapping(guid, docinfoHash.get("docid"));
418
      }
419
      else
420
      {
421
        logReplication.debug("No guid information was included with the replicated document");
422
      }
423
      
424
      logReplication.info("ReplicationHandler.handleSingleXMLDocument - Successfully replicated doc " + accNumber);
425
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
426
      {
427
        logReplication.info("ReplicationHandler.handleSingleXMLDocument - " + DOCINSERTNUMBER + " Wrote xml doc " + accNumber +
428
                                     " into "+tableName + " from " +
429
                                         remoteserver);
430
        DOCINSERTNUMBER++;
431
      }
432
      else
433
      {
434
          logReplication.info("ReplicationHandler.handleSingleXMLDocument - " +REVINSERTNUMBER + " Wrote xml doc " + accNumber +
435
                  " into "+tableName + " from " +
436
                      remoteserver);
437
          REVINSERTNUMBER++;
438
      }
439
      String ip = getIpFromURL(u);
440
      EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
441
      
442

    
443
    }//try
444
    catch(Exception e)
445
    {
446
        
447
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
448
        {
449
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
450
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +DOCERRORNUMBER + " Failed to write xml doc " + accNumber +
451
                                       " into "+tableName + " from " +
452
                                           remoteserver + " because "+e.getMessage());
453
          DOCERRORNUMBER++;
454
        }
455
        else
456
        {
457
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
458
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +REVERRORNUMBER + " Failed to write xml doc " + accNumber +
459
                    " into "+tableName + " from " +
460
                        remoteserver +" because "+e.getMessage());
461
            REVERRORNUMBER++;
462
        }
463
        logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
464
        logReplication.error("ReplicationHandler.handleSingleXMLDocument - Failed to write doc " + accNumber +
465
                                      " into db because " +e.getMessage());
466
      throw new HandlerException("ReplicationHandler.handleSingleXMLDocument - generic exception " 
467
    		  + "writing Replication: " +e.getMessage());
468
    }
469
    finally
470
    {
471
       //return DBConnection
472
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
473
    }//finally
474
  }
475

    
476

    
477

    
478
  /* Handle replicate single xml document*/
479
  private void handleSingleDataFile(String remoteserver, String actions,
480
                                    String accNumber, String tableName)
481
               throws HandlerException
482
  {
483
    logReplication.info("ReplicationHandler.handleSingleDataFile - Try to replicate data file: " + accNumber);
484
    DBConnection dbConn = null;
485
    int serialNumber = -1;
486
    try
487
    {
488
      // Get DBConnection from pool
489
      dbConn=DBConnectionPool.
490
                  getDBConnection("ReplicationHandler.handleSinlgeDataFile");
491
      serialNumber=dbConn.getCheckOutSerialNumber();
492
      // Try get docid info from remote server
493
      DocInfoHandler dih = new DocInfoHandler();
494
      XMLReader docinfoParser = initParser(dih);
495
      String docInfoURLString = "https://" + remoteserver +
496
                  "?server="+MetacatUtil.getLocalReplicationServerName()+
497
                  "&action=getdocumentinfo&docid="+accNumber;
498
      docInfoURLString = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLString);
499
      URL docinfoUrl = new URL(docInfoURLString);
500

    
501
      String docInfoStr = ReplicationService.getURLContent(docinfoUrl);
502
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
503
      Hashtable<String, String> docinfoHash = dih.getDocInfo();
504
      // Get docid owner
505
      String user = docinfoHash.get("user_owner");
506
      // Get docid name (such as acl or dataset)
507
      String docName = docinfoHash.get("docname");
508
      // Get doc type (eml public id)
509
      String docType = docinfoHash.get("doctype");
510
      // Get docid home sever. it might be different to remoteserver
511
      // because of hub feature
512
      String docHomeServer = docinfoHash.get("home_server");
513
      String createdDate = docinfoHash.get("date_created");
514
      String updatedDate = docinfoHash.get("date_updated");
515
      //docid should include rev number too
516
      /*String accnum=docId+util.getProperty("document.accNumSeparator")+
517
                                              (String)docinfoHash.get("rev");*/
518

    
519

    
520
      String datafilePath = PropertyService.getProperty("application.datafilepath");
521
      // Get data file content
522
      String readDataURLString = "https://" + remoteserver + "?server="+
523
                                        MetacatUtil.getLocalReplicationServerName()+
524
                                            "&action=readdata&docid="+accNumber;
525
      readDataURLString = MetacatUtil.replaceWhiteSpaceForURL(readDataURLString);
526
      URL u = new URL(readDataURLString);
527
      InputStream input = u.openStream();
528
      //register data file into xml_documents table and wite data file
529
      //into file system
530
      if ( input != null)
531
      {
532
        DocumentImpl.writeDataFileInReplication(input,
533
                                                datafilePath,
534
                                                docName,docType,
535
                                                accNumber, user,
536
                                                docHomeServer,
537
                                                remoteserver,
538
                                                tableName,
539
                                                true, //true means timed replication
540
                                                createdDate,
541
                                                updatedDate);
542
                                         
543
        //process extra access rules
544
        Vector<XMLAccessDAO> xmlAccessDAOList = dih.getAccessControlList();
545
        if (xmlAccessDAOList != null) {
546
        	AccessControlForSingleFile acfsf = new AccessControlForSingleFile(accNumber);
547
        	for (XMLAccessDAO xmlAccessDAO : xmlAccessDAOList) {
548
        		if (!acfsf.accessControlExists(xmlAccessDAO)) {
549
        			acfsf.insertPermissions(xmlAccessDAO);
550
        		}
551
            }
552
        }
553
        
554
        logReplication.info("ReplicationHandler.handleSingleDataFile - Successfully to write datafile " + accNumber);
555
        /*MetacatReplication.replLog("wrote datafile " + accNumber + " from " +
556
                                    remote server);*/
557
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
558
        {
559
          logReplication.info("ReplicationHandler.handleSingleDataFile - " + DOCINSERTNUMBER + " Wrote data file" + accNumber +
560
                                       " into "+tableName + " from " +
561
                                           remoteserver);
562
          DOCINSERTNUMBER++;
563
        }
564
        else
565
        {
566
            logReplication.info("ReplicationHandler.handleSingleDataFile - " + REVINSERTNUMBER + " Wrote data file" + accNumber +
567
                    " into "+tableName + " from " +
568
                        remoteserver);
569
            REVINSERTNUMBER++;
570
        }
571
        String ip = getIpFromURL(u);
572
        EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, accNumber, actions);
573
        
574
      }//if
575
      else
576
      {
577
         logReplication.info("ReplicationHandler.handleSingleDataFile - Couldn't open the data file: " + accNumber);
578
         throw new HandlerException("ReplicationHandler.handleSingleDataFile - Couldn't open the data file: " + accNumber);
579
      }//else
580

    
581
    }//try
582
    catch(Exception e)
583
    {
584
      /*MetacatReplication.replErrorLog("Failed to try wrote data file " + accNumber +
585
                                      " because " +e.getMessage());*/
586
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
587
      {
588
    	logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
589
    	logReplication.error("ReplicationHandler.handleSingleDataFile - " + DOCERRORNUMBER + " Failed to write data file " + accNumber +
590
                                     " into " + tableName + " from " +
591
                                         remoteserver + " because " + e.getMessage());
592
        DOCERRORNUMBER++;
593
      }
594
      else
595
      {
596
    	  logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
597
    	  logReplication.error("ReplicationHandler.handleSingleDataFile - " + REVERRORNUMBER + " Failed to write data file" + accNumber +
598
                  " into " + tableName + " from " +
599
                      remoteserver +" because "+ e.getMessage());
600
          REVERRORNUMBER++;
601
      }
602
      logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
603
      logReplication.error("ReplicationHandler.handleSingleDataFile - Failed to try wrote datafile " + accNumber +
604
                                      " because " + e.getMessage());
605
      throw new HandlerException("ReplicationHandler.handleSingleDataFile - generic exception " 
606
    		  + "writing Replication: " + e.getMessage());
607
    }
608
    finally
609
    {
610
       //return DBConnection
611
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
612
    }//finally
613
  }
614

    
615

    
616

    
617
  /* Handle delete single document*/
618
  private void handleDeleteSingleDocument(String docId, String notifyServer)
619
               throws HandlerException
620
  {
621
    logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Try delete doc: "+docId);
622
    DBConnection dbConn = null;
623
    int serialNumber = -1;
624
    try
625
    {
626
      // Get DBConnection from pool
627
      dbConn=DBConnectionPool.
628
                  getDBConnection("ReplicationHandler.handleDeleteSingleDoc");
629
      serialNumber=dbConn.getCheckOutSerialNumber();
630
      if(!alreadyDeleted(docId))
631
      {
632

    
633
         //because delete method docid should have rev number
634
         //so we just add one for it. This rev number is no sence.
635
         String accnum=docId+PropertyService.getProperty("document.accNumSeparator")+"1";
636
         //System.out.println("accnum: "+accnum);
637
         DocumentImpl.delete(accnum, null, null, notifyServer);
638
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Successfully deleted doc " + docId);
639
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Doc " + docId + " deleted");
640
         URL u = new URL("https://"+notifyServer);
641
         String ip = getIpFromURL(u);
642
         EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, docId, "delete");
643
      }
644

    
645
    }//try
646
    catch(Exception e)
647
    {
648
      logMetacat.error("ReplicationHandler.handleDeleteSingleDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
649
      logReplication.error("ReplicationHandler.handleDeleteSingleDocument - Failed to delete doc " + docId +
650
                                 " in db because because " + e.getMessage());
651
      throw new HandlerException("ReplicationHandler.handleDeleteSingleDocument - generic exception " 
652
    		  + "when handling document: " + e.getMessage());
653
    }
654
    finally
655
    {
656
       //return DBConnection
657
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
658
    }//finally
659
  }
660

    
661
  /* Handle updateLastCheckTimForSingleServer*/
662
  private void updateLastCheckTimeForSingleServer(ReplicationServer repServer)
663
                                                  throws HandlerException
664
  {
665
    String server = repServer.getServerName();
666
    DBConnection dbConn = null;
667
    int serialNumber = -1;
668
    PreparedStatement pstmt = null;
669
    try
670
    {
671
      // Get DBConnection from pool
672
      dbConn=DBConnectionPool.
673
             getDBConnection("ReplicationHandler.updateLastCheckTimeForServer");
674
      serialNumber=dbConn.getCheckOutSerialNumber();
675

    
676
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Try to update last_check for server: "+server);
677
      // Get time from remote server
678
      URL dateurl = new URL("https://" + server + "?server="+
679
      MetacatUtil.getLocalReplicationServerName()+"&action=gettime");
680
      String datexml = ReplicationService.getURLContent(dateurl);
681
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - datexml: "+datexml);
682
      if (datexml!=null && !datexml.equals(""))
683
      {
684
         String datestr = datexml.substring(11, datexml.indexOf('<', 11));
685
         StringBuffer sql = new StringBuffer();
686
         /*sql.append("update xml_replication set last_checked = to_date('");
687
         sql.append(datestr).append("', 'YY-MM-DD HH24:MI:SS') where ");
688
         sql.append("server like '").append(server).append("'");*/
689
         sql.append("update xml_replication set last_checked = ");
690
         sql.append(DatabaseService.getInstance().getDBAdapter().toDate(datestr, "MM/DD/YY HH24:MI:SS"));
691
         sql.append(" where server like '").append(server).append("'");
692
         pstmt = dbConn.prepareStatement(sql.toString());
693

    
694
         pstmt.executeUpdate();
695
         dbConn.commit();
696
         pstmt.close();
697
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - last_checked updated to "+datestr+" on "
698
                                      + server);
699
      }//if
700
      else
701
      {
702

    
703
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server "  +
704
                                  server + " in db because couldn't get time "
705
                                  );
706
         throw new Exception("Couldn't get time for server "+ server);
707
      }
708

    
709
    }//try
710
    catch(Exception e)
711
    {
712
      logMetacat.error("ReplicationHandler.updateLastCheckTimeForSingleServer - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
713
      logReplication.error("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server " +
714
                                server + " in db because because " + e.getMessage());
715
      throw new HandlerException("ReplicationHandler.updateLastCheckTimeForSingleServer - " 
716
    		  + "Error updating last checked time: " + e.getMessage());
717
    }
718
    finally
719
    {
720
       //return DBConnection
721
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
722
    }//finally
723
  }
724

    
725

    
726

    
727
  /**
728
   * updates xml_catalog with entries from other servers.
729
   */
730
  private void updateCatalog()
731
  {
732
    logReplication.info("ReplicationHandler.updateCatalog - Start of updateCatalog");
733
    // ReplicationServer object in server list
734
    ReplicationServer replServer = null;
735
    PreparedStatement pstmt = null;
736
    String server = null;
737

    
738

    
739
    // Go through each ReplicationServer object in sererlist
740
    for (int j=0; j<serverList.size(); j++)
741
    {
742
      Vector<Vector<String>> remoteCatalog = new Vector<Vector<String>>();
743
      Vector<String> publicId = new Vector<String>();
744
      try
745
      {
746
        // Get ReplicationServer object from server list
747
        replServer = serverList.serverAt(j);
748
        // Get server name from the ReplicationServer object
749
        server = replServer.getServerName();
750
        // Try to get catalog
751
        URL u = new URL("https://" + server + "?server="+
752
        MetacatUtil.getLocalReplicationServerName()+"&action=getcatalog");
753
        logReplication.info("ReplicationHandler.updateCatalog - sending message " + u.toString());
754
        String catxml = ReplicationService.getURLContent(u);
755

    
756
        // Make sure there are not error, no empty string
757
        if (catxml.indexOf("error")!=-1 || catxml==null||catxml.equals(""))
758
        {
759
          throw new Exception("Couldn't get catalog list form server " +server);
760
        }
761
        logReplication.debug("ReplicationHandler.updateCatalog - catxml: " + catxml);
762
        CatalogMessageHandler cmh = new CatalogMessageHandler();
763
        XMLReader catparser = initParser(cmh);
764
        catparser.parse(new InputSource(new StringReader(catxml)));
765
        //parse the returned catalog xml and put it into a vector
766
        remoteCatalog = cmh.getCatalogVect();
767

    
768
        // Make sure remoteCatalog is not empty
769
        if (remoteCatalog.isEmpty())
770
        {
771
          throw new Exception("Couldn't get catalog list form server " +server);
772
        }
773

    
774
        String localcatxml = ReplicationService.getCatalogXML();
775

    
776
        // Make sure local catalog is no empty
777
        if (localcatxml==null||localcatxml.equals(""))
778
        {
779
          throw new Exception("Couldn't get catalog list form server " +server);
780
        }
781

    
782
        cmh = new CatalogMessageHandler();
783
        catparser = initParser(cmh);
784
        catparser.parse(new InputSource(new StringReader(localcatxml)));
785
        Vector<Vector<String>> localCatalog = cmh.getCatalogVect();
786

    
787
        //now we have the catalog from the remote server and this local server
788
        //we now need to compare the two and merge the differences.
789
        //the comparison is base on the public_id fields which is the 4th
790
        //entry in each row vector.
791
        publicId = new Vector<String>();
792
        for(int i=0; i<localCatalog.size(); i++)
793
        {
794
          Vector<String> v = new Vector<String>(localCatalog.elementAt(i));
795
          logReplication.info("ReplicationHandler.updateCatalog - v1: " + v.toString());
796
          publicId.add(new String((String)v.elementAt(3)));
797
          //System.out.println("adding " + (String)v.elementAt(3));
798
        }
799
      }//try
800
      catch (Exception e)
801
      {
802
        logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
803
        logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
804
                                    server + " because " +e.getMessage());
805
      }//catch
806

    
807
      for(int i=0; i<remoteCatalog.size(); i++)
808
      {
809
         // DConnection
810
        DBConnection dbConn = null;
811
        // DBConnection checkout serial number
812
        int serialNumber = -1;
813
        try
814
        {
815
            dbConn=DBConnectionPool.
816
                  getDBConnection("ReplicationHandler.updateCatalog");
817
            serialNumber=dbConn.getCheckOutSerialNumber();
818
            Vector<String> v = remoteCatalog.elementAt(i);
819
            //System.out.println("v2: " + v.toString());
820
            //System.out.println("i: " + i);
821
            //System.out.println("remoteCatalog.size(): " + remoteCatalog.size());
822
            //System.out.println("publicID: " + publicId.toString());
823
            logReplication.info
824
                              ("ReplicationHandler.updateCatalog - v.elementAt(3): " + (String)v.elementAt(3));
825
           if(!publicId.contains(v.elementAt(3)))
826
           { //so we don't have this public id in our local table so we need to
827
             //add it.
828
             //System.out.println("in if");
829
             StringBuffer sql = new StringBuffer();
830
             sql.append("insert into xml_catalog (entry_type, source_doctype, ");
831
             sql.append("target_doctype, public_id, system_id) values (?,?,?,");
832
             sql.append("?,?)");
833
             //System.out.println("sql: " + sql.toString());
834
             pstmt = dbConn.prepareStatement(sql.toString());
835
             pstmt.setString(1, (String)v.elementAt(0));
836
             pstmt.setString(2, (String)v.elementAt(1));
837
             pstmt.setString(3, (String)v.elementAt(2));
838
             pstmt.setString(4, (String)v.elementAt(3));
839
             pstmt.setString(5, (String)v.elementAt(4));
840
             pstmt.execute();
841
             pstmt.close();
842
             logReplication.info("ReplicationHandler.updateCatalog - Success fully to insert new publicid "+
843
                               (String)v.elementAt(3) + " from server"+server);
844
           }
845
        }
846
        catch(Exception e)
847
        {
848
           logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
849
           logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
850
                                    server + " because " +e.getMessage());
851
        }//catch
852
        finally
853
        {
854
           DBConnectionPool.returnDBConnection(dbConn, serialNumber);
855
        }//finally
856
      }//for remote catalog
857
    }//for server list
858
    logReplication.info("End of updateCatalog");
859
  }
860

    
861
  /**
862
   * Method that returns true if docid has already been "deleted" from metacat.
863
   * This method really implements a truth table for deleted documents
864
   * The table is (a docid in one of the tables is represented by the X):
865
   * xml_docs      xml_revs      deleted?
866
   * ------------------------------------
867
   *   X             X             FALSE
868
   *   X             _             FALSE
869
   *   _             X             TRUE
870
   *   _             _             TRUE
871
   */
872
  private static boolean alreadyDeleted(String docid) throws HandlerException
873
  {
874
    DBConnection dbConn = null;
875
    int serialNumber = -1;
876
    PreparedStatement pstmt = null;
877
    try
878
    {
879
      dbConn=DBConnectionPool.
880
                  getDBConnection("ReplicationHandler.alreadyDeleted");
881
      serialNumber=dbConn.getCheckOutSerialNumber();
882
      boolean xml_docs = false;
883
      boolean xml_revs = false;
884

    
885
      StringBuffer sb = new StringBuffer();
886
      sb.append("select docid from xml_revisions where docid like '");
887
      sb.append(docid).append("'");
888
      pstmt = dbConn.prepareStatement(sb.toString());
889
      pstmt.execute();
890
      ResultSet rs = pstmt.getResultSet();
891
      boolean tablehasrows = rs.next();
892
      if(tablehasrows)
893
      {
894
        xml_revs = true;
895
      }
896

    
897
      sb = new StringBuffer();
898
      sb.append("select docid from xml_documents where docid like '");
899
      sb.append(docid).append("'");
900
      pstmt.close();
901
      pstmt = dbConn.prepareStatement(sb.toString());
902
      //increase usage count
903
      dbConn.increaseUsageCount(1);
904
      pstmt.execute();
905
      rs = pstmt.getResultSet();
906
      tablehasrows = rs.next();
907
      pstmt.close();
908
      if(tablehasrows)
909
      {
910
        xml_docs = true;
911
      }
912

    
913
      if(xml_docs && xml_revs)
914
      {
915
        return false;
916
      }
917
      else if(xml_docs && !xml_revs)
918
      {
919
        return false;
920
      }
921
      else if(!xml_docs && xml_revs)
922
      {
923
        return true;
924
      }
925
      else if(!xml_docs && !xml_revs)
926
      {
927
        return true;
928
      }
929
    }
930
    catch(Exception e)
931
    {
932
      logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
933
      logReplication.error("ReplicationHandler.alreadyDeleted - general error in alreadyDeleted: " +
934
                          e.getMessage());
935
      throw new HandlerException("ReplicationHandler.alreadyDeleted - general error: " 
936
    		  + e.getMessage());
937
    }
938
    finally
939
    {
940
      try
941
      {
942
        pstmt.close();
943
      }//try
944
      catch (SQLException ee)
945
      {
946
    	logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
947
        logReplication.error("ReplicationHandler.alreadyDeleted - Error in replicationHandler.alreadyDeleted "+
948
                          "to close pstmt: "+ee.getMessage());
949
        throw new HandlerException("ReplicationHandler.alreadyDeleted - SQL error when closing prepared statement: " 
950
      		  + ee.getMessage());
951
      }//catch
952
      finally
953
      {
954
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
955
      }//finally
956
    }//finally
957
    return false;
958
  }
959

    
960

    
961
  /**
962
   * Method to initialize the message parser
963
   */
964
  public static XMLReader initParser(DefaultHandler dh)
965
          throws HandlerException
966
  {
967
    XMLReader parser = null;
968

    
969
    try {
970
      ContentHandler chandler = dh;
971

    
972
      // Get an instance of the parser
973
      String parserName = PropertyService.getProperty("xml.saxparser");
974
      parser = XMLReaderFactory.createXMLReader(parserName);
975

    
976
      // Turn off validation
977
      parser.setFeature("http://xml.org/sax/features/validation", false);
978

    
979
      parser.setContentHandler((ContentHandler)chandler);
980
      parser.setErrorHandler((ErrorHandler)chandler);
981

    
982
    } catch (SAXException se) {
983
      throw new HandlerException("ReplicationHandler.initParser - Sax error when " 
984
    		  + " initializing parser: " + se.getMessage());
985
    } catch (PropertyNotFoundException pnfe) {
986
        throw new HandlerException("ReplicationHandler.initParser - Property error when " 
987
      		  + " getting parser name: " + pnfe.getMessage());
988
    } 
989

    
990
    return parser;
991
  }
992

    
993
  /**
994
	 * This method will combine given time string(in short format) to current
995
	 * date. If the given time (e.g 10:00 AM) passed the current time (e.g 2:00
996
	 * PM Aug 21, 2005), then the time will set to second day, 10:00 AM Aug 22,
997
	 * 2005. If the given time (e.g 10:00 AM) haven't passed the current time
998
	 * (e.g 8:00 AM Aug 21, 2005) The time will set to be 10:00 AM Aug 21, 2005.
999
	 * 
1000
	 * @param givenTime
1001
	 *            the format should be "10:00 AM " or "2:00 PM"
1002
	 * @return
1003
	 * @throws Exception
1004
	 */
1005
	public static Date combinateCurrentDateAndGivenTime(String givenTime) throws HandlerException
1006
  {
1007
	  try {
1008
     Date givenDate = parseTime(givenTime);
1009
     Date newDate = null;
1010
     Date now = new Date();
1011
     String currentTimeString = getTimeString(now);
1012
     Date currentTime = parseTime(currentTimeString); 
1013
     if ( currentTime.getTime() >= givenDate.getTime())
1014
     {
1015
        logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today already pass the given time, we should set it as tomorrow");
1016
        String dateAndTime = getDateString(now) + " " + givenTime;
1017
        Date combinationDate = parseDateTime(dateAndTime);
1018
        // new date should plus 24 hours to make is the second day
1019
        newDate = new Date(combinationDate.getTime()+24*3600*1000);
1020
     }
1021
     else
1022
     {
1023
         logReplication.info("ReplicationHandler.combinateCurrentDateAndGivenTime - Today haven't pass the given time, we should it as today");
1024
         String dateAndTime = getDateString(now) + " " + givenTime;
1025
         newDate = parseDateTime(dateAndTime);
1026
     }
1027
     logReplication.warn("ReplicationHandler.combinateCurrentDateAndGivenTime - final setting time is "+ newDate.toString());
1028
     return newDate;
1029
	  } catch (ParseException pe) {
1030
		  throw new HandlerException("ReplicationHandler.combinateCurrentDateAndGivenTime - "
1031
				  + "parsing error: "  + pe.getMessage());
1032
	  }
1033
  }
1034

    
1035
  /*
1036
	 * parse a given string to Time in short format. For example, given time is
1037
	 * 10:00 AM, the date will be return as Jan 1 1970, 10:00 AM
1038
	 */
1039
  private static Date parseTime(String timeString) throws ParseException
1040
  {
1041
    DateFormat format = DateFormat.getTimeInstance(DateFormat.SHORT);
1042
    Date time = format.parse(timeString); 
1043
    logReplication.info("ReplicationHandler.parseTime - Date string is after parse a time string "
1044
                              +time.toString());
1045
    return time;
1046

    
1047
  }
1048
  
1049
  /*
1050
   * Parse a given string to date and time. Date format is long and time
1051
   * format is short.
1052
   */
1053
  private static Date parseDateTime(String timeString) throws ParseException
1054
  {
1055
    DateFormat format = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT);
1056
    Date time = format.parse(timeString);
1057
    logReplication.info("ReplicationHandler.parseDateTime - Date string is after parse a time string "+
1058
                             time.toString());
1059
    return time;
1060
  }
1061
  
1062
  /*
1063
   * Get a date string from a Date object. The date format will be long
1064
   */
1065
  private static String getDateString(Date now)
1066
  {
1067
     DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
1068
     String s = df.format(now);
1069
     logReplication.info("ReplicationHandler.getDateString - Today is " + s);
1070
     return s;
1071
  }
1072
  
1073
  /*
1074
   * Get a time string from a Date object, the time format will be short
1075
   */
1076
  private static String getTimeString(Date now)
1077
  {
1078
     DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
1079
     String s = df.format(now);
1080
     logReplication.info("ReplicationHandler.getTimeString - Time is " + s);
1081
     return s;
1082
  }
1083
  
1084
  
1085
  /*
1086
	 * This method will go through the docid list both in xml_Documents table
1087
	 * and in xml_revisions table @author tao
1088
	 */
1089
	private void handleDocList(Vector<Vector<String>> docList, String tableName) {
1090
		boolean dataFile = false;
1091
		for (int j = 0; j < docList.size(); j++) {
1092
			// initial dataFile is false
1093
			dataFile = false;
1094
			// w is information for one document, information contain
1095
			// docid, rev, server or datafile.
1096
			Vector<String> w = new Vector<String>(docList.elementAt(j));
1097
			// Check if the vector w contain "datafile"
1098
			// If it has, this document is data file
1099
			try {
1100
				if (w.contains((String) PropertyService.getProperty("replication.datafileflag"))) {
1101
					dataFile = true;
1102
				}
1103
			} catch (PropertyNotFoundException pnfe) {
1104
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1105
				logReplication.error("ReplicationHandler.handleDocList - Could not retrieve data file flag property.  "
1106
						+ "Leaving as false: " + pnfe.getMessage());
1107
			}
1108
			// System.out.println("w: " + w.toString());
1109
			// Get docid
1110
			String docid = (String) w.elementAt(0);
1111
			logReplication.info("docid: " + docid);
1112
			// Get revision number
1113
			int rev = Integer.parseInt((String) w.elementAt(1));
1114
			logReplication.info("rev: " + rev);
1115
			// Get remote server name (it is may not be doc home server because
1116
			// the new hub feature
1117
			String remoteServer = (String) w.elementAt(2);
1118
			remoteServer = remoteServer.trim();
1119

    
1120
			try {
1121
				if (tableName.equals(DocumentImpl.DOCUMENTTABLE)) {
1122
					handleDocInXMLDocuments(docid, rev, remoteServer, dataFile);
1123
				} else if (tableName.equals(DocumentImpl.REVISIONTABLE)) {
1124
					handleDocInXMLRevisions(docid, rev, remoteServer, dataFile);
1125
				} else {
1126
					continue;
1127
				}
1128

    
1129
			} catch (Exception e) {
1130
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1131
				logReplication.error("ReplicationHandler.handleDocList - error to handle update doc in " + tableName
1132
						+ " in time replication" + e.getMessage());
1133
				continue;
1134
			}
1135
			
1136
	        if (_xmlDocQueryCount > 0 && (_xmlDocQueryCount % 100) == 0) {
1137
	        	logMetacat.debug("ReplicationHandler.update - xml_doc query count: " + _xmlDocQueryCount + 
1138
	        			", xml_doc avg query time: " + (_xmlDocQueryTime / _xmlDocQueryCount));
1139
	        }
1140
	        
1141
	        if (_xmlRevQueryCount > 0 && (_xmlRevQueryCount % 100) == 0) {
1142
	        	logMetacat.debug("ReplicationHandler.update - xml_rev query count: " + _xmlRevQueryCount + 
1143
	        			", xml_rev avg query time: " + (_xmlRevQueryTime / _xmlRevQueryCount));
1144
	        }
1145

    
1146
		}// for update docs
1147

    
1148
	}
1149
   
1150
   /*
1151
	 * This method will handle doc in xml_documents table.
1152
	 */
1153
   private void handleDocInXMLDocuments(String docid, int rev, String remoteServer, boolean dataFile) 
1154
                                        throws HandlerException
1155
   {
1156
       // compare the update rev and local rev to see what need happen
1157
       int localrev = -1;
1158
       String action = null;
1159
       boolean flag = false;
1160
       try
1161
       {
1162
    	 long docQueryStartTime = System.currentTimeMillis();
1163
         localrev = DBUtil.getLatestRevisionInDocumentTable(docid);
1164
         long docQueryEndTime = System.currentTimeMillis();
1165
         _xmlDocQueryTime += (docQueryEndTime - docQueryStartTime);
1166
         _xmlDocQueryCount++;
1167
       }
1168
       catch (SQLException e)
1169
       {
1170
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1171
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1172
                                " be found because " + e.getMessage());
1173
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - " + DOCERRORNUMBER+"Docid "+ docid + " could not be "+
1174
                 "written because error happend to find it's local revision");
1175
         DOCERRORNUMBER++;
1176
         throw new HandlerException ("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1177
                 " be found: " + e.getMessage());
1178
       }
1179
       logReplication.info("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " is "+
1180
                               localrev);
1181

    
1182
       //check the revs for an update because this document is in the
1183
       //local DB, it might be out of date.
1184
       if (localrev == -1)
1185
       {
1186
          // check if the revision is in the revision table
1187
    	   Vector<Integer> localRevVector = null;
1188
    	 try {
1189
        	 long revQueryStartTime = System.currentTimeMillis();
1190
    		 localRevVector = DBUtil.getRevListFromRevisionTable(docid);
1191
             long revQueryEndTime = System.currentTimeMillis();
1192
             _xmlRevQueryTime += (revQueryEndTime - revQueryStartTime);
1193
             _xmlRevQueryCount++;
1194
    	 } catch (SQLException sqle) {
1195
    		 throw new HandlerException("ReplicationHandler.handleDocInXMLDocuments - SQL error " 
1196
    				 + " when getting rev list for docid: " + docid + " : " + sqle.getMessage());
1197
    	 }
1198
         if (localRevVector != null && localRevVector.contains(new Integer(rev)))
1199
         {
1200
             // this version was deleted, so don't need replicate
1201
             flag = false;
1202
         }
1203
         else
1204
         {
1205
           //insert this document as new because it is not in the local DB
1206
           action = "INSERT";
1207
           flag = true;
1208
         }
1209
       }
1210
       else
1211
       {
1212
         if(localrev == rev)
1213
         {
1214
           // Local meatacat has the same rev to remote host, don't need
1215
           // update and flag set false
1216
           flag = false;
1217
         }
1218
         else if(localrev < rev)
1219
         {
1220
           //this document needs to be updated so send an read request
1221
           action = "UPDATE";
1222
           flag = true;
1223
         }
1224
       }
1225
       
1226
       String accNumber = null;
1227
       try {
1228
    	   accNumber = docid + PropertyService.getProperty("document.accNumSeparator") + rev;
1229
       } catch (PropertyNotFoundException pnfe) {
1230
    	   throw new HandlerException("ReplicationHandler.handleDocInXMLDocuments - error getting " 
1231
    			   + "account number separator : " + pnfe.getMessage());
1232
       }
1233
       // this is non-data file
1234
       if(flag && !dataFile)
1235
       {
1236
         try
1237
         {
1238
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1239
         }
1240
         catch(HandlerException he)
1241
         {
1242
           // skip this document
1243
           throw he;
1244
         }
1245
       }//if for non-data file
1246

    
1247
        // this is for data file
1248
       if(flag && dataFile)
1249
       {
1250
         try
1251
         {
1252
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1253
         }
1254
         catch(HandlerException he)
1255
         {
1256
           // skip this data file
1257
           throw he;
1258
         }
1259

    
1260
       }//for data file
1261
   }
1262
   
1263
   /*
1264
    * This method will handle doc in xml_documents table.
1265
    */
1266
   private void handleDocInXMLRevisions(String docid, int rev, String remoteServer, boolean dataFile) 
1267
                                        throws HandlerException
1268
   {
1269
       // compare the update rev and local rev to see what need happen
1270
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - In handle repliation revsion table");
1271
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - the docid is "+ docid);
1272
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - The rev is "+rev);
1273
       Vector<Integer> localrev = null;
1274
       String action = "INSERT";
1275
       boolean flag = false;
1276
       try
1277
       {
1278
      	 long revQueryStartTime = System.currentTimeMillis();
1279
         localrev = DBUtil.getRevListFromRevisionTable(docid);
1280
         long revQueryEndTime = System.currentTimeMillis();
1281
         _xmlRevQueryTime += (revQueryEndTime - revQueryStartTime);
1282
         _xmlRevQueryCount++;
1283
       }
1284
       catch (SQLException sqle)
1285
       {
1286
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1287
         logReplication.error("ReplicationHandler.handleDocInXMLRevisions - Local rev for docid "+ docid + " could not "+
1288
                                " be found because " + sqle.getMessage());
1289
         REVERRORNUMBER++;
1290
         throw new HandlerException ("ReplicationHandler.handleDocInXMLRevisions - SQL exception getting rev list: " 
1291
        		 + sqle.getMessage());
1292
       }
1293
       logReplication.info("ReplicationHandler.handleDocInXMLRevisions - rev list in xml_revision table for docid "+ docid + " is "+
1294
                               localrev.toString());
1295
       
1296
       // if the rev is not in the xml_revision, we need insert it
1297
       if (!localrev.contains(new Integer(rev)))
1298
       {
1299
           flag = true;    
1300
       }
1301
     
1302
       String accNumber = null;
1303
       try {
1304
    	   accNumber = docid + PropertyService.getProperty("document.accNumSeparator") + rev;
1305
       } catch (PropertyNotFoundException pnfe) {
1306
    	   throw new HandlerException("ReplicationHandler.handleDocInXMLRevisions - error getting " 
1307
    			   + "account number separator : " + pnfe.getMessage());
1308
       }
1309
       // this is non-data file
1310
       if(flag && !dataFile)
1311
       {
1312
         try
1313
         {
1314
           
1315
           handleSingleXMLDocument(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1316
         }
1317
         catch(HandlerException he)
1318
         {
1319
           // skip this document
1320
           throw he;
1321
         }
1322
       }//if for non-data file
1323

    
1324
        // this is for data file
1325
       if(flag && dataFile)
1326
       {
1327
         try
1328
         {
1329
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1330
         }
1331
         catch(HandlerException he)
1332
         {
1333
           // skip this data file
1334
           throw he;
1335
         }
1336

    
1337
       }//for data file
1338
   }
1339
   
1340
   /*
1341
    * Return a ip address for given url
1342
    */
1343
   private String getIpFromURL(URL url)
1344
   {
1345
	   String ip = null;
1346
	   try
1347
	   {
1348
	      InetAddress address = InetAddress.getByName(url.getHost());
1349
	      ip = address.getHostAddress();
1350
	   }
1351
	   catch(UnknownHostException e)
1352
	   {
1353
		   logMetacat.error("ReplicationHandler.getIpFromURL - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1354
		   logReplication.error("ReplicationHandler.getIpFromURL - Error in get ip address for host: "
1355
                   +e.getMessage());
1356
	   }
1357

    
1358
	   return ip;
1359
   }
1360
  
1361
}
1362

    
(3-3/7)