Project

General

Profile

« Previous | Next » 

Revision 7506

class for removing failed/invalid replicas from target nodes that previously held replicated content (KNB/LTER/PISCO/etc). https://redmine.dataone.org/issues/3539

View differences:

src/edu/ucsb/nceas/metacat/admin/upgrade/RemoveInvalidReplicas.java
1
package edu.ucsb.nceas.metacat.admin.upgrade;
2
/**
3
 *  '$RCSfile$'
4
 *    Purpose: A Class for upgrading the database to version 1.5
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Saurabh Garg
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

  
29
import java.sql.Connection;
30
import java.sql.Driver;
31
import java.sql.DriverManager;
32
import java.sql.PreparedStatement;
33
import java.sql.ResultSet;
34
import java.sql.SQLException;
35
import java.util.ArrayList;
36
import java.util.List;
37

  
38
import org.apache.commons.logging.Log;
39
import org.apache.commons.logging.LogFactory;
40
import org.apache.wicket.protocol.http.MockHttpServletRequest;
41
import org.dataone.service.types.v1.Event;
42
import org.dataone.service.types.v1.Identifier;
43
import org.dataone.service.types.v1.Session;
44
import org.dataone.service.types.v1.Subject;
45

  
46
import edu.ucsb.nceas.metacat.IdentifierManager;
47
import edu.ucsb.nceas.metacat.admin.AdminException;
48
import edu.ucsb.nceas.metacat.dataone.MNodeService;
49
import edu.ucsb.nceas.metacat.dataone.hazelcast.HazelcastService;
50
import edu.ucsb.nceas.metacat.properties.PropertyService;
51
import edu.ucsb.nceas.utilities.SortedProperties;
52

  
53
/**
54
 * Used for forcibly removing invalid replicas from a target node.
55
 * These replicas exist from legacy Metacat replication that may have introduced 
56
 * whitespace differences and entity escaping in the XML representations.
57
 * Removing these replicas is considered 'safe' because the source node[s] house the 
58
 * original content that should be re-replicated (by DataONE).
59
 * @see https://redmine.dataone.org/issues/3539
60
 * @author leinfelder
61
 *
62
 */
63
public class RemoveInvalidReplicas implements UpgradeUtilityInterface {
64

  
65
	protected static Log log = LogFactory.getLog(RemoveInvalidReplicas.class);
66
	
67
    private String driver = null;
68
    private String url = null;
69
    private String user = null;
70
    private String password = null;
71
    
72
    private boolean dryRun = false;
73

  
74
    public boolean upgrade() throws AdminException {
75
        
76
    	boolean success = true;	
77
    	
78
        Connection sqlca = null;
79
        PreparedStatement pstmt = null;
80
        
81
        try {
82
        	
83
			log.debug("dryRun: " + dryRun);
84

  
85
        	
86
        	// get the properties
87
    		driver = PropertyService.getProperty("database.driver");
88
    	    url = PropertyService.getProperty("database.connectionURI");
89
    	    user = PropertyService.getProperty("database.user");
90
    	    password = PropertyService.getProperty("database.password");
91
    	    
92
	        // Create a JDBC connection to the database    
93
	        Driver d = (Driver) Class.forName(driver).newInstance();
94
	        DriverManager.registerDriver(d);
95
	        sqlca = DriverManager.getConnection(url, user, password);
96
	        sqlca.setAutoCommit(true);       
97
	        
98
	        // find the replicas that failed to synch
99
			List<String> invalidReplicas = new ArrayList<String>();
100
			pstmt = sqlca.prepareStatement(
101
					"SELECT guid " +
102
					"FROM identifier id, xml_documents xml, access_log log " +
103
					"WHERE id.docid = xml.docid " +
104
					"AND id.rev = xml.rev " +
105
					"AND log.docid = id.docid || '.' || id.rev " +
106
					"AND xml.server_location != '1' " +
107
					"AND log.event = ?");
108
			pstmt.setString(1, Event.SYNCHRONIZATION_FAILED.xmlValue());
109
			log.debug("Finding invalid (failed replicas with SQL: " + pstmt.toString());
110
			ResultSet rs = pstmt.executeQuery();
111
			while (rs.next()) {
112
				invalidReplicas.add(rs.getString(1));
113
			}
114

  
115
			log.debug("invalidReplicas count: " + invalidReplicas.size());
116

  
117
			// prepare statement for removing from identifier table
118
			pstmt = sqlca.prepareStatement("DELETE FROM identifier WHERE guid = ? ");
119

  
120
			// for using the MN API as the MN itself
121
			MockHttpServletRequest request = new MockHttpServletRequest(null, null, null);
122
			Session session = new Session();
123
	        Subject subject = MNodeService.getInstance(request).getCapabilities().getSubject(0);
124
	        session.setSubject(subject);
125
	        
126
			// remove them from the system in two steps
127
			for (String identifier: invalidReplicas) {
128
				
129
				log.debug("Removing invalid replica: " + identifier);
130
						
131
				// using the MN.delete() method first
132
				Identifier pid = new Identifier();
133
				pid.setValue(identifier);
134
				try {
135
					if (!dryRun) {
136
						MNodeService.getInstance(request).delete(session, pid);
137
					}
138
				} catch (Exception e) {
139
					log.error("Could not delete invalid replica: " + identifier, e);
140
					continue;
141
				}
142
				
143
				
144
				if (!dryRun) {
145
					// remove SM
146
					IdentifierManager.getInstance().deleteSystemMetadata(identifier);
147
					
148
					// remove the identifier
149
					if (IdentifierManager.getInstance().mappingExists(identifier)) {
150
						String localId = IdentifierManager.getInstance().getLocalId(identifier);
151
						IdentifierManager.getInstance().removeMapping(identifier, localId );
152
					}
153

  
154
					// purge from Hz
155
					HazelcastService.getInstance().getSystemMetadataMap().evict(pid);
156
				}
157

  
158
		        // remove from the identifier table
159
				pstmt.setString(1, identifier);
160
				if (!dryRun) {
161
					int count = pstmt.executeUpdate();
162
					// warn if we saw something unexpected
163
					if (count <= 0) {
164
						log.warn("Delete returned unexpected count for pid: " + identifier);
165
					}
166
				}
167
			}
168
			
169
        } catch (Exception e) {
170
        	// TODO Auto-generated catch block
171
			e.printStackTrace();
172
        	success = false;
173
		} finally {
174
			// clean up
175
			if (sqlca != null) {
176
				try {
177
					sqlca.close();
178
				} catch (SQLException e) {
179
					// TODO Auto-generated catch block
180
					e.printStackTrace();
181
				}
182
			}
183
		}
184
            	
185
		log.debug("Done removing failed/invalid replicas");
186

  
187
    	return success;
188
    }
189

  
190
    public static void main(String [] ags){
191

  
192
        try {
193
        	// set up the properties based on the test/deployed configuration of the workspace
194
        	SortedProperties testProperties = 
195
				new SortedProperties("test/test.properties");
196
			testProperties.load();
197
			String metacatContextDir = testProperties.getProperty("metacat.contextDir");
198
			PropertyService.getInstance(metacatContextDir + "/WEB-INF");
199
			// now run it
200
            RemoveInvalidReplicas upgrader = new RemoveInvalidReplicas();
201
            //upgrader.dryRun = true;
202
	        upgrader.upgrade();
203
            
204
        } catch (Exception ex) {
205
            System.out.println("Exception:" + ex.getMessage());
206
            ex.printStackTrace();
207
        }
208
    }
209
}
0 210

  

Also available in: Unified diff