001
014
015 package com.liferay.portal.upgrade.v7_0_0;
016
017 import com.liferay.portal.dao.jdbc.spring.DataSourceFactoryBean;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.upgrade.UpgradeProcess;
021 import com.liferay.portal.kernel.upgrade.util.UpgradeTable;
022 import com.liferay.portal.kernel.upgrade.util.UpgradeTableFactoryUtil;
023 import com.liferay.portal.kernel.util.GetterUtil;
024 import com.liferay.portal.kernel.util.ListUtil;
025 import com.liferay.portal.kernel.util.LoggingTimer;
026 import com.liferay.portal.kernel.util.StringPool;
027 import com.liferay.portal.upgrade.v7_0_0.util.ClassNameTable;
028 import com.liferay.portal.upgrade.v7_0_0.util.ClusterGroupTable;
029 import com.liferay.portal.upgrade.v7_0_0.util.CompanyTable;
030 import com.liferay.portal.upgrade.v7_0_0.util.CounterTable;
031 import com.liferay.portal.upgrade.v7_0_0.util.CountryTable;
032 import com.liferay.portal.upgrade.v7_0_0.util.PortalPreferencesTable;
033 import com.liferay.portal.upgrade.v7_0_0.util.RegionTable;
034 import com.liferay.portal.upgrade.v7_0_0.util.ReleaseTable;
035 import com.liferay.portal.upgrade.v7_0_0.util.ResourceActionTable;
036 import com.liferay.portal.upgrade.v7_0_0.util.ServiceComponentTable;
037 import com.liferay.portal.upgrade.v7_0_0.util.VirtualHostTable;
038 import com.liferay.portal.util.PropsUtil;
039
040 import java.io.IOException;
041
042 import java.sql.Connection;
043 import java.sql.PreparedStatement;
044 import java.sql.ResultSet;
045 import java.sql.SQLException;
046
047 import java.util.ArrayList;
048 import java.util.List;
049
050 import javax.sql.DataSource;
051
052
055 public class UpgradeSharding extends UpgradeProcess {
056
057 protected void copyCompanyTable(
058 Connection sourceConnection, Connection targetConnection,
059 String shardName)
060 throws Exception {
061
062 copyControlTable(
063 sourceConnection, targetConnection, CompanyTable.TABLE_NAME,
064 CompanyTable.TABLE_COLUMNS, CompanyTable.TABLE_SQL_CREATE);
065
066 List<Long> companyIds = getCompanyIds(shardName);
067
068 String companyIdsString = ListUtil.toString(
069 companyIds, StringPool.NULL, StringPool.COMMA);
070
071 runSQL(
072 sourceConnection,
073 "delete from Company where companyId in (" + companyIdsString +
074 ")");
075
076 runSQL(
077 targetConnection,
078 "delete from Company where companyId not in (" + companyIdsString +
079 ")");
080 }
081
082 protected void copyControlTable(
083 Connection sourceConnection, Connection targetConnection,
084 String tableName, Object[][] columns, String createSQL)
085 throws Exception {
086
087 try {
088 if (hasRows(targetConnection, tableName)) {
089 if (_log.isWarnEnabled()) {
090 _log.warn(
091 "Control table " + tableName + " should not contain " +
092 "data in a nondefault shard");
093 }
094 }
095
096 dropTable(targetConnection, tableName);
097 }
098 catch (SQLException sqle) {
099 if (_log.isInfoEnabled()) {
100 _log.info(
101 "Unable to drop control table " + tableName +
102 " because it does not exist in the target shard");
103 }
104 }
105
106 UpgradeTable upgradeTable = UpgradeTableFactoryUtil.getUpgradeTable(
107 tableName, columns);
108
109 upgradeTable.setCreateSQL(createSQL);
110
111 upgradeTable.copyTable(sourceConnection, targetConnection);
112 }
113
114 protected void copyControlTables(List<String> shardNames) throws Exception {
115 try (LoggingTimer loggingTimer = new LoggingTimer()) {
116 List<String> uniqueShardNames = ListUtil.unique(shardNames);
117
118 if (uniqueShardNames.size() == 1) {
119 if (_log.isInfoEnabled()) {
120 _log.info(
121 "Skip copying of control tables because all " +
122 "companies are located in the same shard");
123 }
124
125 return;
126 }
127
128 String defaultShardName = GetterUtil.getString(
129 PropsUtil.get("shard.default.name"), "default");
130
131 for (String uniqueShardName : uniqueShardNames) {
132 if (!uniqueShardName.equals(defaultShardName)) {
133 copyControlTables(uniqueShardName);
134 }
135 }
136 }
137 }
138
139 protected void copyControlTables(String shardName) throws Exception {
140 DataSourceFactoryBean dataSourceFactoryBean =
141 new DataSourceFactoryBean();
142
143 dataSourceFactoryBean.setPropertyPrefix("jdbc." + shardName + ".");
144
145 DataSource dataSource = dataSourceFactoryBean.createInstance();
146
147 try (Connection targetConnection = dataSource.getConnection()) {
148 copyCompanyTable(connection, targetConnection, shardName);
149 copyControlTable(
150 connection, targetConnection, ClassNameTable.TABLE_NAME,
151 ClassNameTable.TABLE_COLUMNS, ClassNameTable.TABLE_SQL_CREATE);
152 copyControlTable(
153 connection, targetConnection, ClusterGroupTable.TABLE_NAME,
154 ClusterGroupTable.TABLE_COLUMNS,
155 ClusterGroupTable.TABLE_SQL_CREATE);
156 copyControlTable(
157 connection, targetConnection, CounterTable.TABLE_NAME,
158 CounterTable.TABLE_COLUMNS, CounterTable.TABLE_SQL_CREATE);
159 copyControlTable(
160 connection, targetConnection, CountryTable.TABLE_NAME,
161 CountryTable.TABLE_COLUMNS, CountryTable.TABLE_SQL_CREATE);
162 copyControlTable(
163 connection, targetConnection, PortalPreferencesTable.TABLE_NAME,
164 PortalPreferencesTable.TABLE_COLUMNS,
165 PortalPreferencesTable.TABLE_SQL_CREATE);
166 copyControlTable(
167 connection, targetConnection, RegionTable.TABLE_NAME,
168 RegionTable.TABLE_COLUMNS, RegionTable.TABLE_SQL_CREATE);
169 copyControlTable(
170 connection, targetConnection, ReleaseTable.TABLE_NAME,
171 ReleaseTable.TABLE_COLUMNS, ReleaseTable.TABLE_SQL_CREATE);
172 copyControlTable(
173 connection, targetConnection, ResourceActionTable.TABLE_NAME,
174 ResourceActionTable.TABLE_COLUMNS,
175 ResourceActionTable.TABLE_SQL_CREATE);
176 copyControlTable(
177 connection, targetConnection, ServiceComponentTable.TABLE_NAME,
178 ServiceComponentTable.TABLE_COLUMNS,
179 ServiceComponentTable.TABLE_SQL_CREATE);
180 copyControlTable(
181 connection, targetConnection, VirtualHostTable.TABLE_NAME,
182 VirtualHostTable.TABLE_COLUMNS,
183 VirtualHostTable.TABLE_SQL_CREATE);
184 }
185 catch (Exception e) {
186 _log.error("Unable to copy control tables", e);
187 }
188 }
189
190 @Override
191 protected void doUpgrade() throws Exception {
192 List<String> shardNames = getShardNames();
193
194 if (shardNames.size() <= 1) {
195 return;
196 }
197
198 copyControlTables(shardNames);
199 }
200
201 protected void dropTable(Connection connection, String tableName)
202 throws IOException, SQLException {
203
204 runSQL(connection, "drop table " + tableName);
205
206 if (_log.isDebugEnabled()) {
207 _log.debug("Deleted table " + tableName);
208 }
209 }
210
211 protected List<Long> getCompanyIds(String shardName) throws Exception {
212 try (LoggingTimer loggingTimer = new LoggingTimer();
213 PreparedStatement ps = connection.prepareStatement(
214 "select classPK from Shard where name = ?")) {
215
216 ps.setString(1, shardName);
217
218 List<Long> companyIds = new ArrayList<>();
219
220 try (ResultSet rs = ps.executeQuery()) {
221 while (rs.next()) {
222 companyIds.add(rs.getLong("classPK"));
223 }
224 }
225
226 return companyIds;
227 }
228 }
229
230 protected List<String> getShardNames() throws Exception {
231 try (LoggingTimer loggingTimer = new LoggingTimer();
232 PreparedStatement ps = connection.prepareStatement(
233 "select name from Shard");
234 ResultSet rs = ps.executeQuery()) {
235
236 List<String> shardNames = new ArrayList<>();
237
238 while (rs.next()) {
239 shardNames.add(rs.getString("name"));
240 }
241
242 return shardNames;
243 }
244 }
245
246 private static final Log _log = LogFactoryUtil.getLog(
247 UpgradeSharding.class);
248
249 }