Project

General

Profile

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: daigle $'
13
 *     '$Date: 2009-08-24 14:34:17 -0700 (Mon, 24 Aug 2009) $'
14
 * '$Revision: 5030 $'
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.replication;
32

    
33
import java.io.IOException;
34
import java.net.*;
35

    
36
import org.apache.log4j.Logger;
37

    
38
import edu.ucsb.nceas.metacat.properties.PropertyService;
39
import edu.ucsb.nceas.metacat.shared.ServiceException;
40
import edu.ucsb.nceas.metacat.util.MetacatUtil;
41
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
42

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

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

    
70

    
71

    
72
  /**
73
   * Constructor of ForceReplicationHandler
74
   * @param docid the docid to force replicate
75
   * @param the action that is being performed on the document (either
76
   *        INSERT or UPDATE)
77
   * @param xml the docid is a xml document or not (data file)
78
   * @param notificationServer, when a metacat A got forcereplication
79
   * notification from B, then A will update its record. And A will notification
80
   * other metacat in its serverlist to update this docid if A is a hub. But we
81
   * don't want A to notify B again. B is nofitification of A.
82
   */
83
  public ForceReplicationHandler(String docid, String action, boolean xml,
84
                                                   String myNotificationServer)
85
  {
86
    this.docid = docid;
87
    this.action = action;
88
    this.xmlDocument =xml;
89
    // Build a severLists from xml_replication table
90
    this.serverLists = new ReplicationServerList();
91
    // Get sever code for this docid
92
    try
93
    {
94
      this.homeServerCode = ReplicationService.getHomeServerCodeForDocId(docid);
95
    }//try
96
    catch (ServiceException se)
97
    {
98
    	logMetacat.error("ForceReplicationHandler() - " + ReplicationService.METACAT_REPL_ERROR_MSG);
99
    	logReplication.error("ForceReplicationHandler() - Service issue in constructor: " 
100
    			+ se.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 = ReplicationService.getHomeServerCodeForDocId(docid);
130
    }
131
     catch (ServiceException se)
132
    {
133
      logMetacat.error("ForceReplicationHandler() - " + ReplicationService.METACAT_REPL_ERROR_MSG);
134
      logReplication.error("ForceReplicationHandler()- Service issue in constructor: " 
135
    			+ se.getMessage());
136
    }//catch
137
    // Get notification server
138
    this.notificationServer = myNotificationServer;
139
    btThread = new Thread(this);
140
    btThread.setPriority(Thread.MIN_PRIORITY);
141
    btThread.start();
142
  }
143

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

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

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

    
183
				// If the server is the notification server, we don't notify it back
184
				// again, if server is null we don't replication it
185
				if (server != null && !server.equals(notificationServer)) {
186

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

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

    
228
								}
229
							}//else
230

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

    
250
								}
251

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

    
273
								}
274

    
275
							}//else if servercode==1
276
						}//else if data file
277

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

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

    
303
							}//else if
304

    
305
						}//if xmlDoucment
306
						else if (replicationServer.getDataReplication()) { //It is datafile and server is configured to replicate data file
307

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

    
326
							}//else
327
						}//else if
328
					}//else has implicit action
329

    
330
					//Make sure comeAndGetIt is not empty
331
					if (comeAndGetIt != null && !comeAndGetIt.equals("")) {
332
						logReplication.warn("ForceReplicationHandler.run - sending message: " + comeAndGetIt.toString());
333
						String message = ReplicationService.getURLContent(comeAndGetIt);
334
					}
335
					//send out the url.  message is a dummy variable as the target of
336
					//the URL never directly replies to the request.  this simply
337
					//invoces a read request from the server to this local machine.
338
				}//if notification server
339
			} catch (MalformedURLException mue) {
340
		    	logMetacat.error("ForceReplicationHandler.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);
341
				logReplication.error("ForceReplicationHandler.run - URL error in ForceReplicationHandler.run for server "
342
						+ server + " : " + mue.getMessage());
343
//				mue.printStackTrace();
344
			} catch (IOException io) {
345
		    	logMetacat.error("ForceReplicationHandler.run - " + ReplicationService.METACAT_REPL_ERROR_MSG);
346
				logReplication.error("ForceReplicationHandler.run - I/O error in ForceReplicationHandler.run for server "
347
						+ server + " : " + io.getMessage());
348
			}
349
		}//for
350

    
351
		logReplication.warn("ForceReplicationHandler.run - exiting ForceReplicationHandler Thread");
352
	}//run
353
}//ForceReplication class
(1-1/7)