Project

General

Profile

« Previous | Next » 

Revision 5014

Added by daigle over 15 years ago

Create replication directory. Move replication code there. Use log4j for replication logging (rollingfileappender). Beef up replication logging and error control.

View differences:

src/edu/ucsb/nceas/metacat/ReplicationServer.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class represent a server in xml_replcation table
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Jing Tao
7
 *
8
 *   '$Author$'
9
 *     '$Date$'
10
 * '$Revision$'
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;
28

  
29
/**
30
 * A class express a entry in xml_replication. It include server name,
31
 * lastChechedDate, replication or not, dataReplication or not, hub or not
32
 */
33
 
34
public class ReplicationServer
35
{
36
  private String serverName = null; //server name
37
  private String lastCheckedDate = null; //string of last 
38
  private boolean replication = false; //replciate xml document or not
39
  private boolean dataReplication = false; //replciate data file or not
40
                                           //it is relative to replcation
41
                                           //if replication is false, it should
42
                                           //be false
43
  private boolean hub = false; //it is hub or not. Hub means the localhost can
44
                               //replcate documents to the server if the 
45
                               //document's home server is not localhost
46
  /**
47
   * Consturctor of ReplicationServer
48
   */
49
  public ReplicationServer()
50
  {
51
    this.serverName = null;
52
    this.lastCheckedDate = null;
53
    this.replication = false;
54
    this.dataReplication = false;
55
    this.hub = false;
56
  }//constructor
57
  
58
  /**
59
   * Get server name
60
   */
61
  public String getServerName()
62
  {
63
    return this.serverName;
64
  }//getServerName
65
  
66
  /**
67
   * Set a sting as server name
68
   * @param myServerName, the string will set to object's serverName
69
   */
70
  public void setServerName(String myServerName)
71
  {
72
    this.serverName = myServerName;
73
  }//setServerName
74
  
75
  /**
76
   * Get last checked date
77
   */
78
  public String getLastCheckedDate()
79
  {
80
    return this.lastCheckedDate;
81
  }//getLastCheckedDate
82
  
83
  /**
84
   * Set a string as last checked date
85
   * @Param myLastCheckedDate, the string will set to object's lastCheckedDate
86
   */
87
  public void setLastCheckedDate(String myLastCheckedDate)
88
  {
89
    this.lastCheckedDate = myLastCheckedDate;
90
  }//setLastCheckedDate
91
   
92
  /**
93
   * Get replication xml or not option
94
   */
95
  public boolean getReplication()
96
  {
97
    return this.replication;
98
  }//getReplication
99
  
100
  /**
101
   * Set replication option
102
   * @param myReplication, the option will set to object's replication
103
   */
104
  public void setReplication(boolean myReplication)
105
  {
106
    this.replication = myReplication;
107
  }//setReplication
108
  
109
  /**
110
   * Get datareplication xml or not option
111
   */
112
  public boolean getDataReplication()
113
  {
114
    return this.dataReplication;
115
  }//getDataReplication
116
  
117
  /**
118
   * Set data replication option
119
   * @param myDataReplication, the option will set to object's datareplication
120
   */
121
  public void setDataReplication(boolean myDataReplication)
122
  {
123
    this.dataReplication = myDataReplication;
124
  }//setDataReplication   
125
   
126
  /**
127
   * Get hub option
128
   */
129
  public boolean getHub()
130
  {
131
    return this.hub;
132
  }//getHub
133
  
134
  /**
135
   * Set hub option
136
   * @param myHub, the option will set to object's hub option
137
   */
138
  public void setHub(boolean myHub)
139
  {
140
    this.hub = myHub;
141
  }//setHub     
142
  
143
}//class ReplicationServer
144

  
145 0

  
src/edu/ucsb/nceas/metacat/ForceReplicationHandler.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class to asyncronously force the replication of each server
4
 *             that has an entry in the xml_replication table.  When run,
5
 *             this thread communicates with each server in the list and
6
 *             solicites a read of an updated or newly inserted document
7
 *             with a certain docid.
8
 *  Copyright: 2000 Regents of the University of California and the
9
 *             National Center for Ecological Analysis and Synthesis
10
 *    Authors: Chad Berkley
11
 *
12
 *   '$Author$'
13
 *     '$Date$'
14
 * '$Revision$'
15
 *
16
 * This program is free software; you can redistribute it and/or modify
17
 * it under the terms of the GNU General Public License as published by
18
 * the Free Software Foundation; either version 2 of the License, or
19
 * (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU General Public License
27
 * along with this program; if not, write to the Free Software
28
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29
 */
30

  
31
package edu.ucsb.nceas.metacat;
32

  
33
import java.util.*;
34
import java.io.*;
35
import java.sql.*;
36
import java.net.*;
37
import java.lang.*;
38
import java.text.*;
39

  
40
import org.apache.log4j.Logger;
41

  
42
import edu.ucsb.nceas.metacat.service.PropertyService;
43
import edu.ucsb.nceas.metacat.util.MetacatUtil;
44

  
45
/**
46
 * A class to asyncronously force the replication of each server
47
 * that has an entry in the xml_replication table.  When run,
48
 * this thread communicates with each server in the list and
49
 * solicites a read of an updated or newly inserted document
50
 * with a certain docid.
51
 */
52
public class ForceReplicationHandler implements Runnable
53
{
54
  private Thread btThread;
55
  private String docid;
56
  private String action;
57
  private boolean xmlDocument;
58
  private boolean dbactionFlag = true;
59
  private ReplicationServerList serverLists = null;//Serverlist
60
  private int homeServerCode = 0; // home server code for the docid
61
  // When a metacat A got forcereplication
62
  // notification from B, then A will update its record. And A will notification
63
  // other metacat in its serverlist to update this docid if A is a hub. But we
64
  // don't want A to notify B again. B is nofitification of A
65
  private String notificationServer = null;
66
  private Logger logMetacat = Logger.getLogger(ForceReplicationHandler.class);
67

  
68
  //constant
69
  public static final String DELETE = "delete";
70

  
71

  
72

  
73
  /**
74
   * Constructor of ForceReplicationHandler
75
   * @param docid the docid to force replicate
76
   * @param the action that is being performed on the document (either
77
   *        INSERT or UPDATE)
78
   * @param xml the docid is a xml document or not (data file)
79
   * @param notificationServer, when a metacat A got forcereplication
80
   * notification from B, then A will update its record. And A will notification
81
   * other metacat in its serverlist to update this docid if A is a hub. But we
82
   * don't want A to notify B again. B is nofitification of A.
83
   */
84
  public ForceReplicationHandler(String docid, String action, boolean xml,
85
                                                   String myNotificationServer)
86
  {
87
    this.docid = docid;
88
    this.action = action;
89
    this.xmlDocument =xml;
90
    // Build a severLists from xml_replication table
91
    this.serverLists = new ReplicationServerList();
92
    // Get sever code for this docid
93
    try
94
    {
95
      this.homeServerCode = MetacatReplication.getHomeServerCodeForDocId(docid);
96
    }//try
97
    catch (Exception e)
98
    {
99
      logMetacat.error("Error in ForceReplicationHandle(): "
100
                                                          +e.getMessage());
101
    }//catch
102
    // Get the notification server
103
    this.notificationServer = myNotificationServer;
104

  
105
    if(this.action.equals(""))
106
    {
107
      dbactionFlag = false;
108
    }
109

  
110
    btThread = new Thread(this);
111
    btThread.setPriority(Thread.MIN_PRIORITY);
112
    btThread.start();
113
  }
114

  
115
  /**
116
   * Use this constructor when the action is implied.
117
   */
118
  public ForceReplicationHandler(String docid, boolean xml,
119
                                                String myNotificationServer )
120
  {
121
    this.docid = docid;
122
    this.xmlDocument = xml;
123
    dbactionFlag = false;
124
    // Build a severLists from xml_replication table
125
    this.serverLists = new ReplicationServerList();
126
    // Get home server code for this doicd
127
    try
128
    {
129
      this.homeServerCode = MetacatReplication.getHomeServerCodeForDocId(docid);
130
    }
131
     catch (Exception e)
132
    {
133
      logMetacat.error("Error in ForceReplicationHandle(): "
134
                                                          +e.getMessage());
135
    }//catch
136
    // Get notification server
137
    this.notificationServer = myNotificationServer;
138
    btThread = new Thread(this);
139
    btThread.setPriority(Thread.MIN_PRIORITY);
140
    btThread.start();
141
  }
142

  
143
  /**
144
   * Method to send force replication command to other server to get
145
   * a new or updated docid
146
   */
147
  public void run()
148
  {
149

  
150
    
151
	    // URL for notifcation
152
	    URL comeAndGetIt = null;
153
		// If no server in xml_replication table, metacat don't need do anything
154
		if (serverLists.isEmpty()) {
155
			return;
156
		}
157

  
158
		// Thread seelping for some seconds to make sure the document was insert
159
		// into the database before we send force replication request
160
		int sleepTime;
161
		try {
162
			sleepTime = Integer.parseInt(PropertyService
163
					.getProperty("replication.forcereplicationwaitingtime"));
164
			Thread.sleep(sleepTime);
165
		} catch (Exception ee) {
166
			logMetacat.error("Couldn't sleep in force replication");
167
		}
168
		logMetacat.info("notification server:" + notificationServer);
169
		// Check every server in the serverlists
170
		for (int i = 0; i < serverLists.size(); i++) {
171
			//Set comeAndGetIt null
172
			comeAndGetIt = null;
173
			// Get ReplicationServer object in index i
174
			ReplicationServer replicationServer = serverLists.serverAt(i);
175
			// Get this ReplicationServer 's name
176
			String server = replicationServer.getServerName();
177
			try {
178

  
179
				// If the server is the notification server, we don't notify it back
180
				// again, if server is null we don't replication it
181
				if (server != null && !server.equals(notificationServer)) {
182

  
183
					if (dbactionFlag) {
184
						// xml documents and server can replicate xml doucment
185
						if (xmlDocument && replicationServer.getReplication()) {
186
							// If this docid's homeserver is localhost, replicate it
187
							if (homeServerCode == 1) {
188
								MetacatReplication.replLog("force xml replicating to "
189
										+ server);
190
								comeAndGetIt = new URL("https://" + server
191
										+ "?action=forcereplicate&server="
192
										+ MetacatUtil.getLocalReplicationServerName()
193
										+ "&docid=" + docid + "&dbaction=" + action);
194
								//over write the url for delete
195
								if (action != null && action.equals(DELETE)) {
196
									comeAndGetIt = new URL("https://" + server
197
											+ "?action="
198
											+ MetacatReplication.FORCEREPLICATEDELETE
199
											+ "&docid=" + docid + "&server="
200
											+ MetacatUtil.getLocalReplicationServerName());
201

  
202
								}
203
							}//if servercode==1
204
							else if (replicationServer.getHub()
205
									|| server.equals(MetacatReplication
206
											.getServerNameForServerCode(homeServerCode))) {
207
								// If the docid's home server is not local host, but local host
208
								// is a hub of this server, replicate the docid too.
209
								// If the server is homeserver of the docid, replication it too
210
								MetacatReplication.replLog("force xml replicating to "
211
										+ server);
212
								comeAndGetIt = new URL("https://" + server
213
										+ "?action=forcereplicate&server="
214
										+ MetacatUtil.getLocalReplicationServerName()
215
										+ "&docid=" + docid + "&dbaction=" + action);
216
								//over write the url for delete
217
								if (action != null && action.equals(DELETE)) {
218
									comeAndGetIt = new URL("https://" + server
219
											+ "?action="
220
											+ MetacatReplication.FORCEREPLICATEDELETE
221
											+ "&docid=" + docid + "&server="
222
											+ MetacatUtil.getLocalReplicationServerName());
223

  
224
								}
225
							}//else
226

  
227
						}//if xmlDocument
228
						//It is data file and configured to handle data replication
229
						else if (replicationServer.getDataReplication()) {
230
							// If the docid's home server is local host, replicate the docid
231
							if (homeServerCode == 1) {
232
								MetacatReplication.replLog("force data replicating to "
233
										+ server);
234
								comeAndGetIt = new URL("https://" + server
235
										+ "?action=forcereplicatedatafile&server="
236
										+ MetacatUtil.getLocalReplicationServerName()
237
										+ "&docid=" + docid + "&dbaction=" + action);
238
								//over write the url for delete
239
								if (action != null && action.equals(DELETE)) {
240
									comeAndGetIt = new URL("https://" + server
241
											+ "?action="
242
											+ MetacatReplication.FORCEREPLICATEDELETE
243
											+ "&docid=" + docid + "&server="
244
											+ MetacatUtil.getLocalReplicationServerName());
245

  
246
								}
247

  
248
							}//if serverCode==1
249
							else if (replicationServer.getHub()
250
									|| server.equals(MetacatReplication
251
											.getServerNameForServerCode(homeServerCode))) {
252
								// If the docid's home server is not local host, but local host
253
								// is a hub of this server, replicate the docid too.
254
								// If the server is homeserver of the docid replication it too
255
								MetacatReplication.replLog("force data replicating to "
256
										+ server);
257
								comeAndGetIt = new URL("https://" + server
258
										+ "?action=forcereplicatedatafile&server="
259
										+ MetacatUtil.getLocalReplicationServerName()
260
										+ "&docid=" + docid + "&dbaction=" + action);
261
								//over write the url for delete
262
								if (action != null && action.equals(DELETE)) {
263
									comeAndGetIt = new URL("https://" + server
264
											+ "?action="
265
											+ MetacatReplication.FORCEREPLICATEDELETE
266
											+ "&docid=" + docid + "&server="
267
											+ MetacatUtil.getLocalReplicationServerName());
268

  
269
								}
270

  
271
							}//else if servercode==1
272
						}//else if data file
273

  
274
					}//if has explicite action
275
					else { // has implicite action
276
						MetacatReplication
277
								.replLog("force replicating (default action) to )"
278
										+ server);
279
						// this docid is xml documents and can replicate xml doucment
280
						if (xmlDocument && replicationServer.getReplication()) {
281
							// If homeserver of this doicd is local, replicate it
282
							if (homeServerCode == 1) {
283
								comeAndGetIt = new URL("https://" + server
284
										+ "?action=forcereplicate&server="
285
										+ MetacatUtil.getLocalReplicationServerName()
286
										+ "&docid=" + docid);
287

  
288
							}//if homeserver ==1
289
							else if (replicationServer.getHub()
290
									|| server.equals(MetacatReplication
291
											.getServerNameForServerCode(homeServerCode))) {
292
								// If home server of this docid is not local host, but local
293
								// host is a hub for this server, replicate this doicd
294
								// If the server is homeserver of the docid, replication it too
295
								comeAndGetIt = new URL("https://" + server
296
										+ "?action=forcereplicate&server="
297
										+ MetacatUtil.getLocalReplicationServerName()
298
										+ "&docid=" + docid);
299

  
300
							}//else if
301

  
302
						}//if xmlDoucment
303
						else if (replicationServer.getDataReplication()) { //It is datafile and server is configured to replicate data file
304

  
305
							//if home server is local host, replicate the data file
306
							if (homeServerCode == 1) {
307
								comeAndGetIt = new URL("https://" + server
308
										+ "?action=forcereplicatedatafile&server="
309
										+ MetacatUtil.getLocalReplicationServerName()
310
										+ "&docid=" + docid);
311
							}//if
312
							else if (replicationServer.getHub()
313
									|| server.equals(MetacatReplication
314
											.getServerNameForServerCode(homeServerCode))) {
315
								// If home server is not local host, but the local host is a hub
316
								// For this server, replicate the data file
317
								// If the server is homeserver of the docid, replication it too
318
								comeAndGetIt = new URL("https://" + server
319
										+ "?action=forcereplicatedatafile&server="
320
										+ MetacatUtil.getLocalReplicationServerName()
321
										+ "&docid=" + docid);
322

  
323
							}//else
324
						}//else if
325
					}//else has implicit action
326

  
327
					//Make sure comeAndGetIt is not empty
328
					if (comeAndGetIt != null && !comeAndGetIt.equals("")) {
329
						logMetacat.warn("sending message: " + comeAndGetIt.toString());
330
						String message = MetacatReplication.getURLContent(comeAndGetIt);
331
					}
332
					//send out the url.  message is a dummy variable as the target of
333
					//the URL never directly replies to the request.  this simply
334
					//invoces a read request from the server to this local machine.
335
				}//if notification server
336
			} catch (Exception ee) {
337
				logMetacat.error("error in ForceReplicationHandler.run for server "
338
						+ server + " " + ee.getMessage());
339
				ee.printStackTrace();
340
			}
341
		}//for
342

  
343
		logMetacat.warn("exiting ForceReplicationHandler Thread");
344
	}//run
345
}//ForceReplication class
346 0

  
src/edu/ucsb/nceas/metacat/ReplMessageHandler.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class that handles xml messages passed by the 
4
 *             replication handler
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Chad Berkley
8
 *
9
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27

  
28
package edu.ucsb.nceas.metacat;
29

  
30

  
31
import java.util.Vector;
32

  
33
import org.xml.sax.Attributes;
34
import org.xml.sax.SAXException;
35
import org.xml.sax.helpers.DefaultHandler;
36

  
37
/** 
38
 * A Class implementing callback bethods for the SAX parser to
39
 * call when processing the XML messages from the replication handler
40
 */
41
public class ReplMessageHandler extends DefaultHandler 
42
{
43
  private Vector updates = new Vector();
44
  private Vector indivUpdate = new Vector();
45
  private Vector indivDelete = new Vector();
46
  private Vector indivRevision = new Vector();
47
  private Vector deletes = new Vector();
48
  private Vector revisions = new Vector();
49
  private String server;
50
  private String dataFile;
51
  private boolean update = false;
52
  private boolean delete = false;
53
  private boolean revision = false;
54
  String currentTag = new String();
55
  StringBuffer textBuffer = null;
56
  
57
  public ReplMessageHandler()
58
  {
59
  }
60
  
61
  /**
62
   * This method starts a new vector for each updatedDocument tag.
63
   */
64
  public void startElement(String uri, String localName, String qName, 
65
                           Attributes attributes) throws SAXException
66
  {
67
    textBuffer = new StringBuffer();
68
    currentTag = localName;
69
    if(localName.equals("updatedDocument"))
70
    {
71
      indivUpdate = new Vector();
72
      update = true;
73
    }
74
    else if(localName.equals("deletedDocument"))
75
    {
76
      indivDelete = new Vector();
77
      delete = true;
78
    }
79
    else if (localName.equals("revisionDocument"))
80
    {
81
      indivRevision = new Vector();
82
      revision = true;
83
    }
84
            
85
  }
86
  
87
  /**
88
   * This method write the indivUpdate to updates when it finds the end of
89
   */
90
  public void endElement(String uri, String localName, String qName) 
91
              throws SAXException
92
  {
93
    if(currentTag.equals("docid") && update)
94
    {
95
      indivUpdate.add(textBuffer.toString());
96
    }
97
    else if(currentTag.equals("docid") && delete)
98
    {
99
      indivDelete.add(textBuffer.toString());
100
    }
101
    else if (currentTag.equals("docid") && revision)
102
    {
103
      indivRevision.add(textBuffer.toString());
104
    }
105
    
106
    if(currentTag.equals("rev") && update)
107
    {
108
      indivUpdate.add(textBuffer.toString());
109
      indivUpdate.add(server);
110
    }
111
    else if(currentTag.equals("rev") && delete)
112
    {
113
      indivDelete.add(textBuffer.toString());
114
      indivDelete.add(server);
115
    }
116
    else if(currentTag.equals("rev") && revision)
117
    {
118
      indivRevision.add(textBuffer.toString());
119
      indivRevision.add(server);
120
    }
121
    
122
    if(currentTag.equals("date_updated") && update)
123
    {
124
      indivUpdate.add(textBuffer.toString());
125
      indivUpdate.add(server);
126
    }
127
    else if(currentTag.equals("date_updated") && delete)
128
    {
129
      indivDelete.add(textBuffer.toString());
130
      indivDelete.add(server);
131
    }
132
    else if(currentTag.equals("date_updated") && revision)
133
    {
134
      indivRevision.add(textBuffer.toString());
135
      indivRevision.add(server);
136
    }
137
    
138
    if(currentTag.equals("server"))
139
    {
140
      server = textBuffer.toString();
141
    }
142
    
143
    //Adding data file attribute into indivUpdate vector
144
    if (currentTag.equals("datafile"))
145
    {
146
      dataFile = textBuffer.toString();
147
      if (update)
148
      {
149
        indivUpdate.add(dataFile);
150
      }
151
      else if (revision)
152
      {
153
        indivRevision.add(dataFile);   
154
      }
155
          
156
      
157
    }
158
    
159
    if(localName.equals("updatedDocument"))
160
    {
161
      updates.add(new Vector(indivUpdate));
162
      update = false;
163
    }
164
    else if(localName.equals("deletedDocument"))
165
    {
166
      deletes.add(new Vector(indivDelete));
167
      delete = false;
168
    }
169
    else if (localName.equals("revisionDocument"))
170
    {
171
       revisions.add(new Vector(indivRevision));
172
       revision = false;
173
    }
174
  }
175
  
176
  /**
177
   * Take the data out of the docid and date_updated fields
178
   */
179
  public void characters(char[] ch, int start, int length) throws SAXException
180
  {
181
    textBuffer.append(new String(ch, start,length));
182
  }
183
  
184
  public Vector getUpdatesVect()
185
  {
186
    return updates;
187
  }
188
  
189
  public Vector getDeletesVect()
190
  {
191
    return deletes;
192
  }
193
  
194
  public Vector getRevisionsVect()
195
  {
196
     return revisions;
197
  }
198
  
199
  /**
200
   * Gets the server name
201
   * @return
202
   */
203
  public String getServerName()
204
  {
205
	  return server;
206
  }
207
}
208 0

  
src/edu/ucsb/nceas/metacat/ReplicationServerList.java
1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class represent a replication server list in 
4
               xml_replcation table
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Jing Tao
8
 *
9
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27

  
28
package edu.ucsb.nceas.metacat;
29

  
30
import edu.ucsb.nceas.metacat.service.DatabaseService;
31

  
32
import java.util.Vector;
33
import java.sql.*;
34

  
35
import org.apache.log4j.Logger;
36

  
37
/**
38
 * A class represent a replication server list in xml_replcation table
39
 */
40
 
41
public class ReplicationServerList
42
{
43
  private static Vector serverList = null; //Vector to store server list
44
  private static Logger logMetacat = Logger.getLogger(ReplicationServer.class);
45

  
46
  /**
47
   * constructor of ReplicationServerList
48
   * It will build server list. If only local host exists, ther server list
49
   * will be null
50
   */
51
  public ReplicationServerList()
52
  {
53
    
54
    serverList = new Vector();
55
    //Build serverList
56
    buildServerList();
57
  }//ReplicationServerList
58
  
59
  /**
60
   * Method to create server list from xml_replication table
61
   * If in xml_replication table, only local host exists, server list will be
62
   * empty
63
   */
64
  private void buildServerList()
65
  {
66
    ReplicationServer server = null; //element in server list
67
    DBConnection dbConn = null;//DBConnection
68
    int serialNumber = -1;//DBConnection serial number
69
    PreparedStatement pstmt = null;
70
    ResultSet rs = null;
71
    boolean hasReplication = false;//Replication xml or not
72
    boolean hasDataReplication = false;//Replication data file or not
73
    boolean isHub = false;//local host is the hub for this server or not
74
    
75
    try
76
    {
77
      //Get DBConnection
78
      dbConn=DBConnectionPool.
79
                  getDBConnection("ReplicationHandler.buildServerList");
80
      serialNumber=dbConn.getCheckOutSerialNumber();
81
      //Select fields from xml_replication table
82
      pstmt = dbConn.prepareStatement("select server, last_checked, replicate,"+
83
                    " datareplicate, hub from xml_replication");
84
      //Execute prepare statement
85
      pstmt.execute();
86
      //Get result set
87
      rs = pstmt.getResultSet();
88
      //Iterate over the result set
89
      boolean tableHasRows = rs.next();
90
      while(tableHasRows)
91
      {
92
        //Server name
93
        String serverName = rs.getString(1);
94
        logMetacat.info("ServerName: "+serverName);
95
        //Last check date
96
        String lastChecked = rs.getString(2);
97
        logMetacat.info("Last checked time: "+lastChecked);
98
        //Replication value
99
        int replication = rs.getInt(3);
100
        logMetacat.info("Replication value: "+replication);
101
        //Data replication value
102
        int dataReplication = rs.getInt(4);
103
        logMetacat.info("DataReplication value: "+dataReplication);
104
        //Hub value
105
        int hubValue = rs.getInt(5);
106
        logMetacat.info("Hub value: "+hubValue);
107
        //Get rid of local host
108
        if(!serverName.equals("localhost"))
109
        {
110
          
111
          //create a new object of Replication
112
          server = new ReplicationServer();
113
         
114
          //Set server name
115
          server.setServerName(serverName);
116
     
117
          //Set last check date
118
          server.setLastCheckedDate(lastChecked);
119
          //From replication value to determine hasReplication valuse
120
          if (replication ==1)
121
          {
122
            //If replication equals 1, it can replicate xml documents
123
            hasReplication = true;
124
          }//if
125
          else
126
          {
127
            //if replication is NOT 1, it can't replicate xml documents
128
            hasReplication = false;
129
          }//else
130
          //Set replication value
131
          server.setReplication(hasReplication);
132
           
133
          //From both replication and data replication value to determine
134
          //hasDataReplication value
135
          if (hasReplication && dataReplication ==1)
136
          { 
137
            //Only server can replicate xml (hasRplication == true) and
138
            // dataReplication is 1, local host can replicate data file
139
            hasDataReplication = true;
140
          }//if
141
          else
142
          {
143
            hasDataReplication = false;
144
          }//else
145
          //Set data replciation value
146
          server.setDataReplication(hasDataReplication);
147
          
148
          //Detemine isHub by hubValue
149
          if (hubValue ==1)
150
          {
151
            isHub = true;
152
          }//if
153
          else
154
          {
155
            isHub = false;
156
          }//else
157
          //Set hub value
158
          server.setHub(isHub);
159
          
160
          //Add this server into server list
161
          serverList.add(server);
162
        }//if
163
        //Go to new row      
164
        tableHasRows = rs.next();   
165
      }//while
166
     
167
    }//try
168
    catch(Exception e)
169
    {
170
      logMetacat.error("Error in ReplicationServerList."
171
                                    +"buildServerList(): "+e.getMessage());
172
    }//catch
173
    finally
174
    {
175
      try
176
      {
177
        //close result set
178
        rs.close();
179
        //close prepareed statement
180
        pstmt.close();
181
      }//try
182
      catch (SQLException sqlE)
183
      {
184
        logMetacat.error("Error in ReplicationHandler.buildServerList: "
185
                                +sqlE.getMessage());
186
      }//catch
187
      finally
188
      {
189
        //Return dbconnection too pool
190
        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
191
      }//finally
192
    }//finally
193
  
194
  }//buildServerList
195
  
196
  /**
197
   * Method to determine the server list is empty or not
198
   */
199
  public boolean isEmpty()
200
  {
201
    return serverList.isEmpty();
202
  }//isEmpty
203
  
204
  /**
205
   * Method to get the size of serverList
206
   */
207
  public int size()
208
  {
209
    return serverList.size();
210
  }//size()
211
  
212
  /**
213
   * Method to add a new replciation server object to serverList
214
   * @Param newReplciationServer, the object need to be add
215
   */
216
  private synchronized void addNewReplicationServer
217
                                      (ReplicationServer newReplicationServer)
218
  {
219
    serverList.add(newReplicationServer);
220
  }//addNewReplicationServer
221
  
222
  /**
223
   * Method to get a server object given a index number
224
   * @param index, the given index number
225
   */
226
  public ReplicationServer serverAt(int index)
227
  {
228
    return (ReplicationServer)serverList.elementAt(index);
229
  }//serverAt
230
   
231

  
232
  /**
233
   * Method to determine if a given server in the replication server list
234
   * @param givenServerName, a server name will be check.
235
   */
236
  public boolean isGivenServerInList(String givenServerName)
237
  {
238
    boolean result = false;//Variable store the return value
239
    ReplicationServer server = null; //Element in vetor
240
    int size = 0;//Variable to store the size of vector serverList
241
    //Get the size of vector
242
    size = serverList.size();
243
    
244
    //If server list is empty
245
    if (size == 0||givenServerName == null||givenServerName.equals(""))
246
    {
247
      result = false;
248
      return result;
249
    }
250
    
251
    //Check every element in the vector
252
    for (int i = 0; i < size; i++)
253
    {
254
      //Get the ReplicationServer object indexed i in vector
255
      server = (ReplicationServer) serverList.elementAt(i);
256
      //If given name match a server's name, return true
257
      if ( givenServerName.equalsIgnoreCase(server.getServerName()))
258
      {
259
        result = true;
260
        return result;
261
      }//if
262
      
263
    }//for
264
    
265
    //If reach here, there is no server's name match the given name
266
    //flase will return
267
    return result;
268
  }//isGinvenServerInList
269
  
270
  /**
271
   * Method to determine its index in server list for a given server.
272
   * If couldn't find it, -1 will be returned
273
   * @param givenServerName, a server name will be check.
274
   */
275
  private synchronized int findIndexInServerList(String givenServerName)
276
  {
277
    int index = -1;//Variable store the return value
278
    ReplicationServer server = null; //Element in vetor
279
    int size = 0;//Variable to store the size of vector serverList
280
    //Get the size of vector
281
    size = serverList.size();
282
    
283
    //If server list is empty, -1 will be returned
284
    if (size == 0 || givenServerName ==null ||givenServerName.equals(""))
285
    {
286
      return index;
287
    }
288
    
289
    //Check every element in the vector
290
    for (int i = 0; i < size; i++)
291
    {
292
      //Get the ReplicationServer object indexed i in vector
293
      server = (ReplicationServer) serverList.elementAt(i);
294
      //If given name match a server's name, return true
295
      if ( givenServerName.equalsIgnoreCase(server.getServerName()))
296
      {
297
        index = i;
298
        return index;
299
      }//if
300
      
301
    }//for
302
    
303
    //If reach here, there is no server's name match the given name
304
    //-1 will return
305
    return index;
306
  }//isGinvenServerInList
307
  
308
  /**
309
   * To a given server name, try to get its lastcheck date.
310
   * If couldn't find the server in the server list, null will return
311
   * @param givenServerName, the server's name which we want to get last checked
312
   * out date
313
   */
314
  public synchronized String getLastCheckedDate(String givenServerName)
315
  {
316
    int index = -1;//Variable to store the index
317
    ReplicationServer server = null;//Variable for replication server
318
    
319
    //Get the server's index in server list
320
    index = findIndexInServerList(givenServerName);
321
    //If index = -1, couldn't find this server, null will return
322
    if (index == -1)
323
    {
324
      return null;
325
    }//if
326
    //Get Replication server object
327
    server = (ReplicationServer) serverList.elementAt(index);
328
    //return its lastcheckeddate attributes in this object
329
    return server.getLastCheckedDate();
330
  }//getLastCehckedDate
331
   
332
  /**
333
   * To a given server name, try to get its xml replciation option
334
   * If couldn't find the server in the server list, false will return
335
   * @param givenServerName, the server's name which we want to get replication
336
   * value
337
   */
338
  public synchronized boolean getReplicationValue(String givenServerName)
339
  {
340
    int index = -1;//Variable to store the index
341
    ReplicationServer server = null;//Variable for replication server
342
    
343
    //Get the server's index in server list
344
    index = findIndexInServerList(givenServerName);
345
    //If index = -1, couldn't find this server, null will return
346
    if (index == -1)
347
    {
348
      return false;
349
    }//if
350
    //Get Replication server object
351
    server = (ReplicationServer) serverList.elementAt(index);
352
    //return this object's replication value
353
    return server.getReplication();
354
  }//getReplicationValue
355
  
356
  /**
357
   * To a given server name, try to get its data file replciation option
358
   * If couldn't find the server in the server list, false will return
359
   * @param givenServerName, the server's name which we want to get data file 
360
   * replication value
361
   */
362
  public synchronized boolean getDataReplicationValue(String givenServerName)
363
  {
364
    int index = -1;//Variable to store the index
365
    ReplicationServer server = null;//Variable for replication server
366
    
367
    //Get the server's index in server list
368
    index = findIndexInServerList(givenServerName);
369
    //If index = -1, couldn't find this server, null will return
370
    if (index == -1)
371
    {
372
      return false;
373
    }//if
374
    //Get Replication server object
375
    server = (ReplicationServer) serverList.elementAt(index);
376
    //Return this object's data replication value
377
    return server.getDataReplication();
378
  }//getDataReplicationValue
379

  
380
  /**
381
   * To a given server name, try to get its hub option
382
   * If couldn't find the server in the server list, false will return
383
   * @param givenServerName, the server's name which we want to get hub
384
   */
385
  public synchronized boolean getHubValue(String givenServerName)
386
  {
387
    int index = -1;//Variable to store the index
388
    ReplicationServer server = null;//Variable for replication server
389
    
390
    //Get the server's index in server list
391
    index = findIndexInServerList(givenServerName);
392
    //If index = -1, couldn't find this server, null will return
393
    if (index == -1)
394
    {
395
      return false;
396
    }//if
397
    //Get Replication server object
398
    server = (ReplicationServer) serverList.elementAt(index);
399
    //Return this object's hub value
400
    return server.getHub();
401
  }//getHubValue  
402
  
403
  /**
404
   * To a given server name, to check if it is in the server list.
405
   * If it is not, add it to server list and the xml_replication table
406
   * This method is for a document was replicated by a hub and the document's
407
   * home server is not in the replication table. The value for replicate,
408
   * datareplicate and hub are all false
409
   * @param givenServerName, the server's name which want to check
410
   */
411
  public synchronized void addToServerListIfItIsNot(String givenServerName)
412
  {
413
    // Variable to store the index for the givenServerName
414
    int index = -1;
415
    // Variable to store the new replciation server object
416
    ReplicationServer newServer = null;
417
    // For sql command
418
    PreparedStatement pStmt=null;
419
    // For check out DBConnection
420
    DBConnection dbConn = null;
421
    int serialNumber = -1;
422
    // Field value for xml_replication table
423
    int replicate = 0;
424
    int dataReplicate = 0;
425
    int hub = 0;
426
    
427
    // Get the the index
428
    index = findIndexInServerList(givenServerName);
429
    // if index ==-1, it not in the server list
430
    // Add the server to server list
431
    // Add the server to xml_replication table
432
    if (index ==-1)
433
    {
434
      // Create a new replication server object it's replicate, datareplicate
435
      // and hub values are default - false
436
      newServer = new ReplicationServer();
437
      // Set newServer's name as givenServerName
438
      newServer.setServerName(givenServerName);
439
      // Add newServer to serverList
440
      this.addNewReplicationServer(newServer);
441
      // Add this server to xml_table too
442
     try
443
      {
444
        // Checkout DBConnection     
445
        dbConn=DBConnectionPool.
446
             getDBConnection("ReplicationSErverList.addToServerListIfItIsNot");
447
        serialNumber=dbConn.getCheckOutSerialNumber();
448
        // Inser it into xml_replication table
449
        /*pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
450
                      "(server, last_checked, replicate, datareplicate, hub) "+
451
                       "VALUES ('" + givenServerName + "', to_date(" +
452
                       "'01/01/00', 'MM/DD/YY'), '" +
453
                       replicate +"', '"+dataReplicate+"','"+ hub + "')");*/
454
        pStmt = dbConn.prepareStatement("INSERT INTO xml_replication " +
455
                      "(server, last_checked, replicate, datareplicate, hub) "+
456
                       "VALUES ('" + givenServerName + "', "+
457
                        DatabaseService.getDBAdapter().toDate("01/01/1980","MM/DD/YYYY") + ", '" +
458
                       replicate +"', '"+dataReplicate+"','"+ hub + "')");
459
        pStmt.execute();
460
       
461
        pStmt.close();
462
      }//try
463
      catch (Exception e)
464
      {
465
        logMetacat.error("Error in ReplicationServerList."+
466
                            "addToServerListIfItIsNot: " + e.getMessage());
467
      }//catch
468
      finally
469
      { 
470
        try
471
        {
472
          pStmt.close();
473
        }//try
474
        catch (Exception ee)
475
        { 
476
          logMetacat.error("Error in ReplicationServerList."+
477
                            "addToServerListIfItIsNot: " + ee.getMessage());
478
        }//catch
479
        finally
480
        {
481
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
482
        }//finally
483
      }//finally
484
    }//if
485
  }//addToServerListIfItIsNot
486
  
487
}//ReplicationServerList
488 0

  
src/edu/ucsb/nceas/metacat/ReplicationHandler.java
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$'
9
 *     '$Date$'
10
 * '$Revision$'
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;
28

  
29
import edu.ucsb.nceas.metacat.service.DatabaseService;
30
import edu.ucsb.nceas.metacat.service.PropertyService;
31
import edu.ucsb.nceas.metacat.util.MetacatUtil;
32
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
33

  
34
import java.sql.*;
35
import java.util.*;
36
import java.util.Date;
37
import java.lang.Thread;
38
import java.io.*;
39
import java.net.*;
40
import java.text.*;
41

  
42
import org.apache.log4j.Logger;
43
import org.xml.sax.AttributeList;
44
import org.xml.sax.ContentHandler;
45
import org.xml.sax.DTDHandler;
46
import org.xml.sax.EntityResolver;
47
import org.xml.sax.ErrorHandler;
48
import org.xml.sax.InputSource;
49
import org.xml.sax.XMLReader;
50
import org.xml.sax.SAXException;
51
import org.xml.sax.SAXParseException;
52
import org.xml.sax.helpers.XMLReaderFactory;
53
import org.xml.sax.helpers.DefaultHandler;
54

  
55

  
56

  
57
/**
58
 * This class handles deltaT replication checking.  Whenever this TimerTask
59
 * is fired it checks each server in xml_replication for updates and updates
60
 * the local db as needed.
61
 */
62
public class ReplicationHandler extends TimerTask
63
{
64
  int serverCheckCode = 1;
65
  ReplicationServerList serverList = null;
66
  //PrintWriter out;
67
//  private static final AbstractDatabase dbAdapter = MetacatUtil.dbAdapter;
68
  private static Logger logMetacat = Logger.getLogger(ReplicationHandler.class);
69
  private static int DOCINSERTNUMBER = 1;
70
  private static int DOCERRORNUMBER  = 1;
71
  private static int REVINSERTNUMBER = 1;
72
  private static int REVERRORNUMBER  = 1;
73
  public ReplicationHandler()
74
  {
75
    //this.out = o;
76
    serverList = new ReplicationServerList();
77
  }
78

  
79
  public ReplicationHandler(int serverCheckCode)
80
  {
81
    //this.out = o;
82
    this.serverCheckCode = serverCheckCode;
83
    serverList = new ReplicationServerList();
84
  }
85

  
86
  /**
87
   * Method that implements TimerTask.run().  It runs whenever the timer is
88
   * fired.
89
   */
90
  public void run()
91
  {
92
    //find out the last_checked time of each server in the server list and
93
    //send a query to each server to see if there are any documents in
94
    //xml_documents with an update_date > last_checked
95
    try
96
    {
97
      //if serverList is null, metacat don't need to replication
98
      if (serverList==null||serverList.isEmpty())
99
      {
100
        return;
101
      }
102
      updateCatalog();
103
      update();
104
      //conn.close();
105
    }//try
106
    catch (Exception e)
107
    {
108
      logMetacat.error("Error in replicationHandler.run():"
109
                                                    +e.getMessage());
110
      e.printStackTrace();
111
    }//catch
112
  }
113

  
114
  /**
115
   * Method that uses revision taging for replication instead of update_date.
116
   */
117
  private void update()
118
  {
119
    /*
120
     Pseudo-algorithm
121
     - request a doc list from each server in xml_replication
122
     - check the rev number of each of those documents agains the
123
       documents in the local database
124
     - pull any documents that have a lesser rev number on the local server
125
       from the remote server
126
     - delete any documents that still exist in the local xml_documents but
127
       are in the deletedDocuments tag of the remote host response.
128
     - update last_checked to keep track of the last time it was checked.
129
       (this info is theoretically not needed using this system but probably
130
       should be kept anyway)
131
    */
132

  
133
    ReplicationServer replServer = null; // Variable to store the
134
                                        // ReplicationServer got from
135
                                        // Server list
136
    String server = null; // Variable to store server name
137
    String update;
138
    Vector responses = new Vector();
139
    URL u;
140

  
141

  
142
    
143
    //Check for every server in server list to get updated list and put
144
    // them in to response
145
    for (int i=0; i<serverList.size(); i++)
146
    {
147
        // Get ReplicationServer object from server list
148
        replServer = serverList.serverAt(i);
149
        // Get server name from ReplicationServer object
150
        server = replServer.getServerName().trim();
151
        String result = null;
152
        MetacatReplication.replLog("full update started to: " + server);
153
        // Send command to that server to get updated docid information
154
        try
155
        {
156
          u = new URL("https://" + server + "?server="
157
          +MetacatUtil.getLocalReplicationServerName()+"&action=update");
158
          logMetacat.info("Sending infomation " +u.toString());
159
          result = MetacatReplication.getURLContent(u);
160
        }
161
        catch (Exception e)
162
        {
163
          MetacatReplication.replErrorLog("Failed to get updated doc list "+
164
                          "for server " + server + " because "+e.getMessage());
165
          logMetacat.error( "Failed to get updated doc list "+
166
                       "for server " + server + " because "+e.getMessage());
167
          continue;
168
        }
169

  
170
        logMetacat.info("docid: "+server+" "+result);
171
        //check if result have error or not, if has skip it.
172
        if (result.indexOf("<error>")!=-1 && result.indexOf("</error>")!=-1)
173
        {
174
          MetacatReplication.replErrorLog("Failed to get updated doc list "+
175
                          "for server " + server + " because "+result);
176
          logMetacat.info( "Failed to get updated doc list "+
177
                       "for server " + server + " because "+result);
178
          continue;
179
        }
180
        //Add result to vector
181
        responses.add(result);
182
    }
183

  
184
    //make sure that there is updated file list
185
    //If response is null, metacat don't need do anything
186
    if (responses==null || responses.isEmpty())
187
    {
188
        MetacatReplication.replErrorLog("No updated doc list for "+
189
                           "every server and failed to replicate");
190
        logMetacat.info( "No updated doc list for "+
191
                           "every server and failed to replicate");
192
        return;
193
    }
194

  
195

  
196
    logMetacat.info("Responses from remote metacat about updated "+
197
                   "document information: "+ responses.toString());
198
    // go through response vector(it contains updated vector and delete vector
199
    for(int i=0; i<responses.size(); i++)
200
    {
201
    	XMLReader parser;
202
    	ReplMessageHandler message = new ReplMessageHandler();
203
    	try
204
        {
205
          parser = initParser(message);
206
        }
207
        catch (Exception e)
208
        {
209
          MetacatReplication.replErrorLog("Failed to replicate becaue couldn't "+
210
                                     " initParser for message and" +e.getMessage());
211
          logMetacat.error("Failed to replicate becaue couldn't " +
212
                                " initParser for message and " +e.getMessage());
213
           // stop replication
214
           return;
215
        }
216
    	
217
        try
218
        {
219
          parser.parse(new InputSource(
220
                     new StringReader(
221
                     (String)(responses.elementAt(i)))));
222
        }
223
        catch(Exception e)
224
        {
225
          MetacatReplication.replErrorLog("Couldn't parse one responses "+
226
                           "because "+ e.getMessage());
227
          logMetacat.error("Couldn't parse one responses "+
228
                                   "because "+ e.getMessage());
229
          continue;
230
        }
231
        //v is the list of updated documents
232
        Vector updateList = new Vector(message.getUpdatesVect());
233
        MetacatReplication.replLog("The document list size is "+updateList.size()+ " from "+message.getServerName());
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff