001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.dao.jdbc.DataAccess;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.upgrade.UpgradeProcess;
022    import com.liferay.portal.kernel.upgrade.util.UpgradeTable;
023    import com.liferay.portal.kernel.upgrade.util.UpgradeTableFactoryUtil;
024    import com.liferay.portal.kernel.util.ListUtil;
025    import com.liferay.portal.kernel.util.StringUtil;
026    import com.liferay.portal.kernel.util.Validator;
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.CounterTable;
030    import com.liferay.portal.upgrade.v7_0_0.util.CountryTable;
031    import com.liferay.portal.upgrade.v7_0_0.util.PortalPreferencesTable;
032    import com.liferay.portal.upgrade.v7_0_0.util.RegionTable;
033    import com.liferay.portal.upgrade.v7_0_0.util.ReleaseTable;
034    import com.liferay.portal.upgrade.v7_0_0.util.ResourceActionTable;
035    import com.liferay.portal.upgrade.v7_0_0.util.ServiceComponentTable;
036    import com.liferay.portal.upgrade.v7_0_0.util.VirtualHostTable;
037    import com.liferay.portal.util.PropsUtil;
038    
039    import java.sql.Connection;
040    import java.sql.PreparedStatement;
041    import java.sql.ResultSet;
042    
043    import java.util.ArrayList;
044    import java.util.List;
045    
046    import javax.sql.DataSource;
047    
048    /**
049     * @author Manuel de la Peña
050     */
051    public class UpgradeSharding extends UpgradeProcess {
052    
053            protected void copyControlTable(
054                            Connection sourceConnection, Connection targetConnection,
055                            String tableName, Object[][] columns, String createSQL)
056                    throws Exception {
057    
058                    UpgradeTable upgradeTable = UpgradeTableFactoryUtil.getUpgradeTable(
059                            tableName, columns);
060    
061                    upgradeTable.setCreateSQL(createSQL);
062    
063                    upgradeTable.copyTable(sourceConnection, targetConnection);
064            }
065    
066            protected void copyControlTables(List<String> shardNames) throws Exception {
067                    boolean defaultPartitioningEnabled = false;
068    
069                    List<String> uniqueShardNames = ListUtil.unique(shardNames);
070    
071                    if (uniqueShardNames.size() < shardNames.size()) {
072                            defaultPartitioningEnabled = true;
073                    }
074    
075                    String defaultShardName = PropsUtil.get("shard.default.name");
076    
077                    if (!defaultPartitioningEnabled && Validator.isNull(defaultShardName)) {
078                            throw new RuntimeException(
079                                    "The property \"shard.default.name\" is not set in " +
080                                            "portal.properties. Please specify a default shard name " +
081                                                    "from: " + StringUtil.merge(shardNames, ", ") + ".");
082                    }
083    
084                    for (String uniqueShardName : uniqueShardNames) {
085                            if (!uniqueShardName.equals(defaultShardName)) {
086                                    copyControlTables(uniqueShardName);
087                            }
088                    }
089            }
090    
091            protected void copyControlTables(String shardName) throws Exception {
092                    Connection sourceConnection =
093                            DataAccess.getUpgradeOptimizedConnection();
094    
095                    DataSourceFactoryBean dataSourceFactoryBean =
096                            new DataSourceFactoryBean();
097    
098                    dataSourceFactoryBean.setPropertyPrefix("jdbc." + shardName + ".");
099    
100                    DataSource dataSource = dataSourceFactoryBean.createInstance();
101    
102                    Connection targetConnection = dataSource.getConnection();
103    
104                    try {
105                            copyControlTable(
106                                    sourceConnection, targetConnection, ClassNameTable.TABLE_NAME,
107                                    ClassNameTable.TABLE_COLUMNS, ClassNameTable.TABLE_SQL_CREATE);
108                            copyControlTable(
109                                    sourceConnection, targetConnection,
110                                    ClusterGroupTable.TABLE_NAME, ClusterGroupTable.TABLE_COLUMNS,
111                                    ClusterGroupTable.TABLE_SQL_CREATE);
112                            copyControlTable(
113                                    sourceConnection, targetConnection, CounterTable.TABLE_NAME,
114                                    CounterTable.TABLE_COLUMNS, CounterTable.TABLE_SQL_CREATE);
115                            copyControlTable(
116                                    sourceConnection, targetConnection, CountryTable.TABLE_NAME,
117                                    CountryTable.TABLE_COLUMNS, CountryTable.TABLE_SQL_CREATE);
118                            copyControlTable(
119                                    sourceConnection, targetConnection,
120                                    PortalPreferencesTable.TABLE_NAME,
121                                    PortalPreferencesTable.TABLE_COLUMNS,
122                                    PortalPreferencesTable.TABLE_SQL_CREATE);
123                            copyControlTable(
124                                    sourceConnection, targetConnection, RegionTable.TABLE_NAME,
125                                    RegionTable.TABLE_COLUMNS, RegionTable.TABLE_SQL_CREATE);
126                            copyControlTable(
127                                    sourceConnection, targetConnection, ReleaseTable.TABLE_NAME,
128                                    ReleaseTable.TABLE_COLUMNS, ReleaseTable.TABLE_SQL_CREATE);
129                            copyControlTable(
130                                    sourceConnection, targetConnection,
131                                    ResourceActionTable.TABLE_NAME,
132                                    ResourceActionTable.TABLE_COLUMNS,
133                                    ResourceActionTable.TABLE_SQL_CREATE);
134                            copyControlTable(
135                                    sourceConnection, targetConnection,
136                                    ServiceComponentTable.TABLE_NAME,
137                                    ServiceComponentTable.TABLE_COLUMNS,
138                                    ServiceComponentTable.TABLE_SQL_CREATE);
139                            copyControlTable(
140                                    sourceConnection, targetConnection, VirtualHostTable.TABLE_NAME,
141                                    VirtualHostTable.TABLE_COLUMNS,
142                                    VirtualHostTable.TABLE_SQL_CREATE);
143                    }
144                    catch (Exception e) {
145                            _log.error("Unable to copy control tables", e);
146                    }
147                    finally {
148                            DataAccess.cleanUp(sourceConnection);
149    
150                            DataAccess.cleanUp(targetConnection);
151                    }
152            }
153    
154            @Override
155            protected void doUpgrade() throws Exception {
156                    List<String> shardNames = getShardNames();
157    
158                    if (shardNames.size() <= 1) {
159                            return;
160                    }
161    
162                    copyControlTables(shardNames);
163            }
164    
165            protected List<String> getShardNames() throws Exception {
166                    PreparedStatement ps = null;
167                    ResultSet rs = null;
168    
169                    List<String> shardNames = new ArrayList<>();
170    
171                    try {
172                            ps = connection.prepareStatement("select name from Shard");
173    
174                            rs = ps.executeQuery();
175    
176                            while (rs.next()) {
177                                    shardNames.add(rs.getString("name"));
178                            }
179                    }
180                    finally {
181                            DataAccess.cleanUp(ps, rs);
182                    }
183    
184                    return shardNames;
185            }
186    
187            private static final Log _log = LogFactoryUtil.getLog(
188                    UpgradeSharding.class);
189    
190    }