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: daigle $'
9
 *     '$Date: 2010-01-04 09:01:25 -0800 (Mon, 04 Jan 2010) $'
10
 * '$Revision: 5175 $'
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.utilities.PropertyNotFoundException;
44

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

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

    
61

    
62

    
63
/**
64
 * This class handles deltaT replication checking.  Whenever this TimerTask
65
 * is fired it checks each server in xml_replication for updates and updates
66
 * the local db as needed.
67
 */
68
public class ReplicationHandler extends TimerTask
69
{
70
  int serverCheckCode = 1;
71
  ReplicationServerList serverList = null;
72
  //PrintWriter out;
73
//  private static final AbstractDatabase dbAdapter = MetacatUtil.dbAdapter;
74
  private static Logger logReplication = Logger.getLogger("ReplicationLogging");
75
  private static Logger logMetacat = Logger.getLogger(ReplicationHandler.class);
76
  private static int DOCINSERTNUMBER = 1;
77
  private static int DOCERRORNUMBER  = 1;
78
  private static int REVINSERTNUMBER = 1;
79
  private static int REVERRORNUMBER  = 1;
80
  
81
  private static int _xmlDocQueryCount = 0;
82
  private static int _xmlRevQueryCount = 0;
83
  private static long _xmlDocQueryTime = 0;
84
  private static long _xmlRevQueryTime = 0;
85
  
86
  
87
  public ReplicationHandler()
88
  {
89
    //this.out = o;
90
    serverList = new ReplicationServerList();
91
  }
92

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

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

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

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

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

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

    
205

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

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

    
312
  }//update
313

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

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

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

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

    
427
    }//try
428
    catch(Exception e)
429
    {
430
        
431
        if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
432
        {
433
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
434
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +DOCERRORNUMBER + " Failed to write xml doc " + accNumber +
435
                                       " into "+tableName + " from " +
436
                                           remoteserver + " because "+e.getMessage());
437
          DOCERRORNUMBER++;
438
        }
439
        else
440
        {
441
        	logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
442
        	logReplication.error("ReplicationHandler.handleSingleXMLDocument - " +REVERRORNUMBER + " Failed to write xml doc " + accNumber +
443
                    " into "+tableName + " from " +
444
                        remoteserver +" because "+e.getMessage());
445
            REVERRORNUMBER++;
446
        }
447
        logMetacat.error("ReplicationHandler.handleSingleXMLDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
448
        logReplication.error("ReplicationHandler.handleSingleXMLDocument - Failed to write doc " + accNumber +
449
                                      " into db because " +e.getMessage());
450
      throw new HandlerException("ReplicationHandler.handleSingleXMLDocument - generic exception " 
451
    		  + "writing Replication: " +e.getMessage());
452
    }
453
    finally
454
    {
455
       //return DBConnection
456
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
457
    }//finally
458
  }
459

    
460

    
461

    
462
  /* Handle replicate single xml document*/
463
  private void handleSingleDataFile(String remoteserver, String actions,
464
                                    String accNumber, String tableName)
465
               throws HandlerException
466
  {
467
    logReplication.info("ReplicationHandler.handleSingleDataFile - Try to replicate data file: " + accNumber);
468
    DBConnection dbConn = null;
469
    int serialNumber = -1;
470
    try
471
    {
472
      // Get DBConnection from pool
473
      dbConn=DBConnectionPool.
474
                  getDBConnection("ReplicationHandler.handleSinlgeDataFile");
475
      serialNumber=dbConn.getCheckOutSerialNumber();
476
      // Try get docid info from remote server
477
      DocInfoHandler dih = new DocInfoHandler();
478
      XMLReader docinfoParser = initParser(dih);
479
      String docInfoURLString = "https://" + remoteserver +
480
                  "?server="+MetacatUtil.getLocalReplicationServerName()+
481
                  "&action=getdocumentinfo&docid="+accNumber;
482
      docInfoURLString = MetacatUtil.replaceWhiteSpaceForURL(docInfoURLString);
483
      URL docinfoUrl = new URL(docInfoURLString);
484

    
485
      String docInfoStr = ReplicationService.getURLContent(docinfoUrl);
486
      docinfoParser.parse(new InputSource(new StringReader(docInfoStr)));
487
      Hashtable<String, String> docinfoHash = dih.getDocInfo();
488
      // Get docid owner
489
      String user = docinfoHash.get("user_owner");
490
      // Get docid name (such as acl or dataset)
491
      String docName = docinfoHash.get("docname");
492
      // Get doc type (eml public id)
493
      String docType = docinfoHash.get("doctype");
494
      // Get docid home sever. it might be different to remoteserver
495
      // because of hub feature
496
      String docHomeServer = docinfoHash.get("home_server");
497
      String createdDate = docinfoHash.get("date_created");
498
      String updatedDate = docinfoHash.get("date_updated");
499
      //docid should include rev number too
500
      /*String accnum=docId+util.getProperty("document.accNumSeparator")+
501
                                              (String)docinfoHash.get("rev");*/
502

    
503

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

    
565
    }//try
566
    catch(Exception e)
567
    {
568
      /*MetacatReplication.replErrorLog("Failed to try wrote data file " + accNumber +
569
                                      " because " +e.getMessage());*/
570
      if (tableName.equals(DocumentImpl.DOCUMENTTABLE))
571
      {
572
    	logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
573
    	logReplication.error("ReplicationHandler.handleSingleDataFile - " + DOCERRORNUMBER + " Failed to write data file " + accNumber +
574
                                     " into " + tableName + " from " +
575
                                         remoteserver + " because " + e.getMessage());
576
        DOCERRORNUMBER++;
577
      }
578
      else
579
      {
580
    	  logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
581
    	  logReplication.error("ReplicationHandler.handleSingleDataFile - " + REVERRORNUMBER + " Failed to write data file" + accNumber +
582
                  " into " + tableName + " from " +
583
                      remoteserver +" because "+ e.getMessage());
584
          REVERRORNUMBER++;
585
      }
586
      logMetacat.error("ReplicationHandler.handleSingleDataFile - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
587
      logReplication.error("ReplicationHandler.handleSingleDataFile - Failed to try wrote datafile " + accNumber +
588
                                      " because " + e.getMessage());
589
      throw new HandlerException("ReplicationHandler.handleSingleDataFile - generic exception " 
590
    		  + "writing Replication: " + e.getMessage());
591
    }
592
    finally
593
    {
594
       //return DBConnection
595
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
596
    }//finally
597
  }
598

    
599

    
600

    
601
  /* Handle delete single document*/
602
  private void handleDeleteSingleDocument(String docId, String notifyServer)
603
               throws HandlerException
604
  {
605
    logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Try delete doc: "+docId);
606
    DBConnection dbConn = null;
607
    int serialNumber = -1;
608
    try
609
    {
610
      // Get DBConnection from pool
611
      dbConn=DBConnectionPool.
612
                  getDBConnection("ReplicationHandler.handleDeleteSingleDoc");
613
      serialNumber=dbConn.getCheckOutSerialNumber();
614
      if(!alreadyDeleted(docId))
615
      {
616

    
617
         //because delete method docid should have rev number
618
         //so we just add one for it. This rev number is no sence.
619
         String accnum=docId+PropertyService.getProperty("document.accNumSeparator")+"1";
620
         //System.out.println("accnum: "+accnum);
621
         DocumentImpl.delete(accnum, null, null, notifyServer);
622
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Successfully deleted doc " + docId);
623
         logReplication.info("ReplicationHandler.handleDeleteSingleDocument - Doc " + docId + " deleted");
624
         URL u = new URL("https://"+notifyServer);
625
         String ip = getIpFromURL(u);
626
         EventLog.getInstance().log(ip, ReplicationService.REPLICATIONUSER, docId, "delete");
627
      }
628

    
629
    }//try
630
    catch(Exception e)
631
    {
632
      logMetacat.error("ReplicationHandler.handleDeleteSingleDocument - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
633
      logReplication.error("ReplicationHandler.handleDeleteSingleDocument - Failed to delete doc " + docId +
634
                                 " in db because because " + e.getMessage());
635
      throw new HandlerException("ReplicationHandler.handleDeleteSingleDocument - generic exception " 
636
    		  + "when handling document: " + e.getMessage());
637
    }
638
    finally
639
    {
640
       //return DBConnection
641
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
642
    }//finally
643
  }
644

    
645
  /* Handle updateLastCheckTimForSingleServer*/
646
  private void updateLastCheckTimeForSingleServer(ReplicationServer repServer)
647
                                                  throws HandlerException
648
  {
649
    String server = repServer.getServerName();
650
    DBConnection dbConn = null;
651
    int serialNumber = -1;
652
    PreparedStatement pstmt = null;
653
    try
654
    {
655
      // Get DBConnection from pool
656
      dbConn=DBConnectionPool.
657
             getDBConnection("ReplicationHandler.updateLastCheckTimeForServer");
658
      serialNumber=dbConn.getCheckOutSerialNumber();
659

    
660
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Try to update last_check for server: "+server);
661
      // Get time from remote server
662
      URL dateurl = new URL("https://" + server + "?server="+
663
      MetacatUtil.getLocalReplicationServerName()+"&action=gettime");
664
      String datexml = ReplicationService.getURLContent(dateurl);
665
      logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - datexml: "+datexml);
666
      if (datexml!=null && !datexml.equals(""))
667
      {
668
         String datestr = datexml.substring(11, datexml.indexOf('<', 11));
669
         StringBuffer sql = new StringBuffer();
670
         /*sql.append("update xml_replication set last_checked = to_date('");
671
         sql.append(datestr).append("', 'YY-MM-DD HH24:MI:SS') where ");
672
         sql.append("server like '").append(server).append("'");*/
673
         sql.append("update xml_replication set last_checked = ");
674
         sql.append(DatabaseService.getDBAdapter().toDate(datestr, "MM/DD/YY HH24:MI:SS"));
675
         sql.append(" where server like '").append(server).append("'");
676
         pstmt = dbConn.prepareStatement(sql.toString());
677

    
678
         pstmt.executeUpdate();
679
         dbConn.commit();
680
         pstmt.close();
681
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - last_checked updated to "+datestr+" on "
682
                                      + server);
683
      }//if
684
      else
685
      {
686

    
687
         logReplication.info("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server "  +
688
                                  server + " in db because couldn't get time "
689
                                  );
690
         throw new Exception("Couldn't get time for server "+ server);
691
      }
692

    
693
    }//try
694
    catch(Exception e)
695
    {
696
      logMetacat.error("ReplicationHandler.updateLastCheckTimeForSingleServer - " + ReplicationService.METACAT_REPL_ERROR_MSG); 
697
      logReplication.error("ReplicationHandler.updateLastCheckTimeForSingleServer - Failed to update last_checked for server " +
698
                                server + " in db because because " + e.getMessage());
699
      throw new HandlerException("ReplicationHandler.updateLastCheckTimeForSingleServer - " 
700
    		  + "Error updating last checked time: " + e.getMessage());
701
    }
702
    finally
703
    {
704
       //return DBConnection
705
       DBConnectionPool.returnDBConnection(dbConn, serialNumber);
706
    }//finally
707
  }
708

    
709

    
710

    
711
  /**
712
   * updates xml_catalog with entries from other servers.
713
   */
714
  private void updateCatalog()
715
  {
716
    logReplication.info("ReplicationHandler.updateCatalog - Start of updateCatalog");
717
    // ReplicationServer object in server list
718
    ReplicationServer replServer = null;
719
    PreparedStatement pstmt = null;
720
    String server = null;
721

    
722

    
723
    // Go through each ReplicationServer object in sererlist
724
    for (int j=0; j<serverList.size(); j++)
725
    {
726
      Vector<Vector<String>> remoteCatalog = new Vector<Vector<String>>();
727
      Vector<String> publicId = new Vector<String>();
728
      try
729
      {
730
        // Get ReplicationServer object from server list
731
        replServer = serverList.serverAt(j);
732
        // Get server name from the ReplicationServer object
733
        server = replServer.getServerName();
734
        // Try to get catalog
735
        URL u = new URL("https://" + server + "?server="+
736
        MetacatUtil.getLocalReplicationServerName()+"&action=getcatalog");
737
        logReplication.info("ReplicationHandler.updateCatalog - sending message " + u.toString());
738
        String catxml = ReplicationService.getURLContent(u);
739

    
740
        // Make sure there are not error, no empty string
741
        if (catxml.indexOf("error")!=-1 || catxml==null||catxml.equals(""))
742
        {
743
          throw new Exception("Couldn't get catalog list form server " +server);
744
        }
745
        logReplication.debug("ReplicationHandler.updateCatalog - catxml: " + catxml);
746
        CatalogMessageHandler cmh = new CatalogMessageHandler();
747
        XMLReader catparser = initParser(cmh);
748
        catparser.parse(new InputSource(new StringReader(catxml)));
749
        //parse the returned catalog xml and put it into a vector
750
        remoteCatalog = cmh.getCatalogVect();
751

    
752
        // Make sure remoteCatalog is not empty
753
        if (remoteCatalog.isEmpty())
754
        {
755
          throw new Exception("Couldn't get catalog list form server " +server);
756
        }
757

    
758
        String localcatxml = ReplicationService.getCatalogXML();
759

    
760
        // Make sure local catalog is no empty
761
        if (localcatxml==null||localcatxml.equals(""))
762
        {
763
          throw new Exception("Couldn't get catalog list form server " +server);
764
        }
765

    
766
        cmh = new CatalogMessageHandler();
767
        catparser = initParser(cmh);
768
        catparser.parse(new InputSource(new StringReader(localcatxml)));
769
        Vector<Vector<String>> localCatalog = cmh.getCatalogVect();
770

    
771
        //now we have the catalog from the remote server and this local server
772
        //we now need to compare the two and merge the differences.
773
        //the comparison is base on the public_id fields which is the 4th
774
        //entry in each row vector.
775
        publicId = new Vector<String>();
776
        for(int i=0; i<localCatalog.size(); i++)
777
        {
778
          Vector<String> v = new Vector<String>(localCatalog.elementAt(i));
779
          logReplication.info("ReplicationHandler.updateCatalog - v1: " + v.toString());
780
          publicId.add(new String((String)v.elementAt(3)));
781
          //System.out.println("adding " + (String)v.elementAt(3));
782
        }
783
      }//try
784
      catch (Exception e)
785
      {
786
        logMetacat.error("ReplicationHandler.updateCatalog - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
787
        logReplication.error("ReplicationHandler.updateCatalog - Failed to update catalog for server "+
788
                                    server + " because " +e.getMessage());
789
      }//catch
790

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

    
845
  /**
846
   * Method that returns true if docid has already been "deleted" from metacat.
847
   * This method really implements a truth table for deleted documents
848
   * The table is (a docid in one of the tables is represented by the X):
849
   * xml_docs      xml_revs      deleted?
850
   * ------------------------------------
851
   *   X             X             FALSE
852
   *   X             _             FALSE
853
   *   _             X             TRUE
854
   *   _             _             TRUE
855
   */
856
  private static boolean alreadyDeleted(String docid) throws HandlerException
857
  {
858
    DBConnection dbConn = null;
859
    int serialNumber = -1;
860
    PreparedStatement pstmt = null;
861
    try
862
    {
863
      dbConn=DBConnectionPool.
864
                  getDBConnection("ReplicationHandler.alreadyDeleted");
865
      serialNumber=dbConn.getCheckOutSerialNumber();
866
      boolean xml_docs = false;
867
      boolean xml_revs = false;
868

    
869
      StringBuffer sb = new StringBuffer();
870
      sb.append("select docid from xml_revisions where docid like '");
871
      sb.append(docid).append("'");
872
      pstmt = dbConn.prepareStatement(sb.toString());
873
      pstmt.execute();
874
      ResultSet rs = pstmt.getResultSet();
875
      boolean tablehasrows = rs.next();
876
      if(tablehasrows)
877
      {
878
        xml_revs = true;
879
      }
880

    
881
      sb = new StringBuffer();
882
      sb.append("select docid from xml_documents where docid like '");
883
      sb.append(docid).append("'");
884
      pstmt.close();
885
      pstmt = dbConn.prepareStatement(sb.toString());
886
      //increase usage count
887
      dbConn.increaseUsageCount(1);
888
      pstmt.execute();
889
      rs = pstmt.getResultSet();
890
      tablehasrows = rs.next();
891
      pstmt.close();
892
      if(tablehasrows)
893
      {
894
        xml_docs = true;
895
      }
896

    
897
      if(xml_docs && xml_revs)
898
      {
899
        return false;
900
      }
901
      else if(xml_docs && !xml_revs)
902
      {
903
        return false;
904
      }
905
      else if(!xml_docs && xml_revs)
906
      {
907
        return true;
908
      }
909
      else if(!xml_docs && !xml_revs)
910
      {
911
        return true;
912
      }
913
    }
914
    catch(Exception e)
915
    {
916
      logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
917
      logReplication.error("ReplicationHandler.alreadyDeleted - general error in alreadyDeleted: " +
918
                          e.getMessage());
919
      throw new HandlerException("ReplicationHandler.alreadyDeleted - general error: " 
920
    		  + e.getMessage());
921
    }
922
    finally
923
    {
924
      try
925
      {
926
        pstmt.close();
927
      }//try
928
      catch (SQLException ee)
929
      {
930
    	logMetacat.error("ReplicationHandler.alreadyDeleted - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
931
        logReplication.error("ReplicationHandler.alreadyDeleted - Error in replicationHandler.alreadyDeleted "+
932
                          "to close pstmt: "+ee.getMessage());
933
        throw new HandlerException("ReplicationHandler.alreadyDeleted - SQL error when closing prepared statement: " 
934
      		  + ee.getMessage());
935
      }//catch
936
      finally
937
      {
938
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
939
      }//finally
940
    }//finally
941
    return false;
942
  }
943

    
944

    
945
  /**
946
   * Method to initialize the message parser
947
   */
948
  public static XMLReader initParser(DefaultHandler dh)
949
          throws HandlerException
950
  {
951
    XMLReader parser = null;
952

    
953
    try {
954
      ContentHandler chandler = dh;
955

    
956
      // Get an instance of the parser
957
      String parserName = PropertyService.getProperty("xml.saxparser");
958
      parser = XMLReaderFactory.createXMLReader(parserName);
959

    
960
      // Turn off validation
961
      parser.setFeature("http://xml.org/sax/features/validation", false);
962

    
963
      parser.setContentHandler((ContentHandler)chandler);
964
      parser.setErrorHandler((ErrorHandler)chandler);
965

    
966
    } catch (SAXException se) {
967
      throw new HandlerException("ReplicationHandler.initParser - Sax error when " 
968
    		  + " initializing parser: " + se.getMessage());
969
    } catch (PropertyNotFoundException pnfe) {
970
        throw new HandlerException("ReplicationHandler.initParser - Property error when " 
971
      		  + " getting parser name: " + pnfe.getMessage());
972
    } 
973

    
974
    return parser;
975
  }
976

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

    
1019
  /*
1020
	 * parse a given string to Time in short format. For example, given time is
1021
	 * 10:00 AM, the date will be return as Jan 1 1970, 10:00 AM
1022
	 */
1023
  private static Date parseTime(String timeString) throws ParseException
1024
  {
1025
    DateFormat format = DateFormat.getTimeInstance(DateFormat.SHORT);
1026
    Date time = format.parse(timeString); 
1027
    logReplication.info("ReplicationHandler.parseTime - Date string is after parse a time string "
1028
                              +time.toString());
1029
    return time;
1030

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

    
1104
			try {
1105
				if (tableName.equals(DocumentImpl.DOCUMENTTABLE)) {
1106
					handleDocInXMLDocuments(docid, rev, remoteServer, dataFile);
1107
				} else if (tableName.equals(DocumentImpl.REVISIONTABLE)) {
1108
					handleDocInXMLRevisions(docid, rev, remoteServer, dataFile);
1109
				} else {
1110
					continue;
1111
				}
1112

    
1113
			} catch (Exception e) {
1114
				logMetacat.error("ReplicationHandler.handleDocList - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1115
				logReplication.error("ReplicationHandler.handleDocList - error to handle update doc in " + tableName
1116
						+ " in time replication" + e.getMessage());
1117
				continue;
1118
			}
1119
			
1120
	        if (_xmlDocQueryCount > 0 && (_xmlDocQueryCount % 100) == 0) {
1121
	        	logMetacat.debug("ReplicationHandler.update - xml_doc query count: " + _xmlDocQueryCount + 
1122
	        			", xml_doc avg query time: " + (_xmlDocQueryTime / _xmlDocQueryCount));
1123
	        }
1124
	        
1125
	        if (_xmlRevQueryCount > 0 && (_xmlRevQueryCount % 100) == 0) {
1126
	        	logMetacat.debug("ReplicationHandler.update - xml_rev query count: " + _xmlRevQueryCount + 
1127
	        			", xml_rev avg query time: " + (_xmlRevQueryTime / _xmlRevQueryCount));
1128
	        }
1129

    
1130
		}// for update docs
1131

    
1132
	}
1133
   
1134
   /*
1135
	 * This method will handle doc in xml_documents table.
1136
	 */
1137
   private void handleDocInXMLDocuments(String docid, int rev, String remoteServer, boolean dataFile) 
1138
                                        throws HandlerException
1139
   {
1140
       // compare the update rev and local rev to see what need happen
1141
       int localrev = -1;
1142
       String action = null;
1143
       boolean flag = false;
1144
       try
1145
       {
1146
    	 long docQueryStartTime = System.currentTimeMillis();
1147
         localrev = DBUtil.getLatestRevisionInDocumentTable(docid);
1148
         long docQueryEndTime = System.currentTimeMillis();
1149
         _xmlDocQueryTime += (docQueryEndTime - docQueryStartTime);
1150
         _xmlDocQueryCount++;
1151
       }
1152
       catch (SQLException e)
1153
       {
1154
    	 logMetacat.error("ReplicationHandler.handleDocInXMLDocuments - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1155
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1156
                                " be found because " + e.getMessage());
1157
         logReplication.error("ReplicationHandler.handleDocInXMLDocuments - " + DOCERRORNUMBER+"Docid "+ docid + " could not be "+
1158
                 "written because error happend to find it's local revision");
1159
         DOCERRORNUMBER++;
1160
         throw new HandlerException ("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " could not "+
1161
                 " be found: " + e.getMessage());
1162
       }
1163
       logReplication.info("ReplicationHandler.handleDocInXMLDocuments - Local rev for docid "+ docid + " is "+
1164
                               localrev);
1165

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

    
1231
        // this is for data file
1232
       if(flag && dataFile)
1233
       {
1234
         try
1235
         {
1236
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.DOCUMENTTABLE);
1237
         }
1238
         catch(HandlerException he)
1239
         {
1240
           // skip this data file
1241
           throw he;
1242
         }
1243

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

    
1308
        // this is for data file
1309
       if(flag && dataFile)
1310
       {
1311
         try
1312
         {
1313
           handleSingleDataFile(remoteServer, action, accNumber, DocumentImpl.REVISIONTABLE);
1314
         }
1315
         catch(HandlerException he)
1316
         {
1317
           // skip this data file
1318
           throw he;
1319
         }
1320

    
1321
       }//for data file
1322
   }
1323
   
1324
   /*
1325
    * Return a ip address for given url
1326
    */
1327
   private String getIpFromURL(URL url)
1328
   {
1329
	   String ip = null;
1330
	   try
1331
	   {
1332
	      InetAddress address = InetAddress.getByName(url.getHost());
1333
	      ip = address.getHostAddress();
1334
	   }
1335
	   catch(UnknownHostException e)
1336
	   {
1337
		   logMetacat.error("ReplicationHandler.getIpFromURL - " + ReplicationService.METACAT_REPL_ERROR_MSG);                         
1338
		   logReplication.error("ReplicationHandler.getIpFromURL - Error in get ip address for host: "
1339
                   +e.getMessage());
1340
	   }
1341

    
1342
	   return ip;
1343
   }
1344
  
1345
}
1346

    
(3-3/7)