Project

General

Profile

Download (6.3 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2009 EDIT
4
* European Distributed Institute of Taxonomy 
5
* http://www.e-taxonomy.eu
6
* 
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.database.update;
11

    
12
import java.sql.ResultSet;
13

    
14
import org.apache.log4j.Logger;
15

    
16
import eu.etaxonomy.cdm.common.monitor.DefaultProgressMonitor;
17
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
18
import eu.etaxonomy.cdm.database.CdmDataSource;
19
import eu.etaxonomy.cdm.database.ICdmDataSource;
20
import eu.etaxonomy.cdm.database.update.v31_33.SchemaUpdater_31_33;
21
import eu.etaxonomy.cdm.database.update.v31_33.TermUpdater_31_33;
22

    
23
/**
24
 * @author a.mueller
25
 * @date 10.09.2010
26
 *
27
 */
28
public class CdmUpdater {
29
	private static final Logger logger = Logger.getLogger(CdmUpdater.class);
30
	
31
	public static CdmUpdater NewInstance(){
32
		return new CdmUpdater();
33
	}
34
	
35
	/**
36
	 * @param datasource
37
	 * @param monitor may be <code>null</code>
38
	 * @return
39
	 */
40
	public boolean updateToCurrentVersion(ICdmDataSource datasource, IProgressMonitor monitor){
41
		boolean result = true;
42
		if (monitor == null){
43
			monitor = DefaultProgressMonitor.NewInstance();
44
		}
45
		
46
		ISchemaUpdater currentSchemaUpdater = getCurrentSchemaUpdater();
47
		// TODO do we really always update the terms??
48
		ITermUpdater currentTermUpdater = getCurrentTermUpdater();
49
		
50
		int steps = currentSchemaUpdater.countSteps(datasource, monitor);
51
		steps += currentTermUpdater.countSteps(datasource, monitor);
52
		steps++;  //for hibernate_sequences update
53
		
54
		String taskName = "Update to schema version " + currentSchemaUpdater.getTargetVersion() + " and to term version " + currentTermUpdater.getTargetVersion(); //+ currentSchemaUpdater.getVersion();
55
		monitor.beginTask(taskName, steps);
56
		
57
		try {
58
			datasource.startTransaction();
59
			result &= currentSchemaUpdater.invoke(datasource, monitor);
60
			if (result == true){
61
				result &= currentTermUpdater.invoke(datasource, monitor);
62
				updateHibernateSequence(datasource, monitor);
63
			}
64
			if (result == false){
65
				datasource.rollback();
66
			}else{
67
				datasource.commitTransaction();
68
			}
69
			
70
		} catch (Exception e) {
71
			result = false;
72
			monitor.warning("Stopped schema updater");
73
		} finally {
74
			String message = "Update finished " + (result ? "successfully" : "with ERRORS");
75
			monitor.subTask(message);
76
			if (!result){
77
				monitor.warning(message);
78
				monitor.setCanceled(true);
79
			}else{
80
				monitor.done();
81
			}
82
			logger.info(message);
83
		}
84
		
85
		return result;
86
	}
87
	
88

    
89
	/**
90
	 * Updating terms often inserts new terms, vocabularies and representations.
91
	 * Therefore the counter in hibernate_sequences must be increased.
92
	 * We do this once at the end of term updating.
93
	 * @return true if update was successful, false otherwise
94
	 */
95
	private boolean updateHibernateSequence(ICdmDataSource datasource, IProgressMonitor monitor) {
96
		boolean result = true;
97
		monitor.subTask("Update hibernate sequences");
98
		try {
99
			String sql = "SELECT * FROM hibernate_sequences ";
100
			ResultSet rs = datasource.executeQuery(sql);
101
			while (rs.next()){
102
				String table = rs.getString("sequence_name");
103
				Integer val = rs.getInt("next_val");
104
				result &= updateSingleValue(datasource,monitor, table, val);
105
			}
106
		} catch (Exception e) {
107
			String message = "Exception occurred when trying to update hibernate_sequences table: " + e.getMessage();
108
			monitor.warning(message, e);
109
			logger.error(message);
110
			result = false;
111
		}finally{
112
			monitor.worked(1);
113
		}
114
		return result;
115
	}
116
	
117
	/**
118
	 * 
119
	 * @param datasource
120
	 * @param monitor
121
	 * @param table
122
	 * @param oldVal
123
	 * @return
124
	 */
125
	private boolean updateSingleValue(ICdmDataSource datasource, IProgressMonitor monitor, String table, Integer oldVal){
126
		try {
127
			Integer newVal;
128
			try {
129
				String sql = " SELECT max(id) FROM %s ";
130
				newVal = (Integer)datasource.getSingleValue(String.format(sql, table));
131
			} catch (Exception e) {
132
				String message = "Could not retrieve max value for table '%s'. Will not update hibernate_sequence for this table. Usually this will not cause problems, however, if new data has been added to this table by the update script one may encounter 'unique identifier' exceptions when trying to add further data.";
133
				monitor.warning(message, e);
134
				//TODO
135
				return true;
136
			}
137
			
138
			//This is how {@link PooledOptimizer#generate(org.hibernate.id.enhanced.AccessCallback)} works
139
			//it substracts the increment size from the value in hibernate_sequences to get the initial value.
140
			//Haven't checked why.
141
			//For the correct increment size see eu.etaxonomy.cdm.model.common.package-info.java
142
			int incrementSize = 10;
143
			newVal = newVal + incrementSize;
144
			if (newVal != null && newVal >= oldVal){
145
				String sql = " UPDATE hibernate_sequences " +
146
						" SET next_val = %d " +
147
						" WHERE sequence_name = '%s' ";
148
				datasource.executeUpdate(String.format(sql, newVal + 1 , table) );
149
			}
150
			return true;
151
		} catch (Exception e) {
152
			String message = "Exception occurred when trying to read or update hibernate_sequences table for value " + table + ": " + e.getMessage();
153
			monitor.warning(message, e);
154
			logger.error(message);
155
			return false;
156
		}
157
		
158
	}
159
	
160
	
161
	private ITermUpdater getCurrentTermUpdater() {
162
		return TermUpdater_31_33.NewInstance();
163
	}
164

    
165
	/**
166
	 * Returns the current CDM updater
167
	 * @return
168
	 */
169
	private ISchemaUpdater getCurrentSchemaUpdater() {
170
		return SchemaUpdater_31_33.NewInstance();
171
	}
172

    
173
	/**
174
	 * @param args
175
	 */
176
	public static void main(String[] args) {
177
		logger.warn("main method not yet fully implemented (only works with mysql!!!)");
178
		if(args.length < 2){
179
			logger.error("Arguments missing: server database [username [password]]");
180
		}
181
		//TODO better implementation
182
		CdmUpdater myUpdater = new CdmUpdater();
183
		String server = args[0];
184
		String database  = args[1];
185
		String username = args.length > 2 ? args[2] : null;
186
		String password  = args.length > 3 ? args[3] : null;
187
		
188
		ICdmDataSource dataSource = CdmDataSource.NewMySqlInstance(server, database, username, password);
189
		boolean success = myUpdater.updateToCurrentVersion(dataSource, null);
190
		System.out.println("DONE " + (success ? "successfully" : "with ERRORS"));
191
	}
192

    
193
}
(2-2/29)