shikeying
2024-01-11 3b67e947e36133e2a40eb2737b15ea375e157ea0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package com.walker.store.strategy;
 
import com.walker.connector.Address;
import com.walker.dbmeta.util.DatabaseUtils;
 
import java.util.List;
 
/**
 * 默认的多库单表存储策略。</p>
 * 该策略适用于:
 * <pre>
 * 1、输入表不区分业务,只有一批,如:100个表
 * 2、想把这些表存储到多个数据库中,便于维护
 * </pre>
 * @author shikeying
 * @date 2015年12月18日
 *
 */
public class OnlyMultiDatabaseStrategy extends DatabaseStoreStrategy {
 
    private int maxTablesInDatabase = 512;
    
    private int maxDatabaseInHost = 16;
    
    /**
     * 返回每个主机能存放数据库的最大数量
     * @return
     */
    public int getMaxDatabaseInHost() {
        return maxDatabaseInHost;
    }
 
    public void setMaxDatabaseInHost(int maxDatabaseInHost) {
        this.maxDatabaseInHost = maxDatabaseInHost;
    }
 
    /**
     * 返回系统设置的每个库存放表的最大值
     * @return
     */
    public int getMaxTablesInDatabase() {
        return maxTablesInDatabase;
    }
 
    public void setMaxTablesInDatabase(int maxTablesInDatabase) {
        this.maxTablesInDatabase = maxTablesInDatabase;
    }
 
    @Override
    protected Address doQueryAddress(String storeId, List<Address> addresses, Object parameter) {
        // 从现有的库中选择一个,
        if(this.getDefineAddressSize() > 1){
            logger.debug("多库策略:存在多个地址库,查询表数量未超过的库");
            Address usingAddr = this.getMetaDataEngine().getUsingAddress(getStoreId());
            if(usingAddr == null){
                usingAddr = this.getDefineAddressList().get(0);
                logger.debug("还没有使用任何库,需要选择第一个: " + usingAddr);
                return createFirstAddress(usingAddr);
            } else {
                logger.debug("已经使用了数据库:" + usingAddr);
                int tableSize = this.getMetaDataEngine().getTableSize(usingAddr);
                if(tableSize >= getMaxTablesInDatabase()){
                    logger.debug("表超过数量,准备切换数据库,tableSize = " + tableSize);
                    // 如果存在多个主机,还要确定使用那个服务器
                    if(this.getMetaDataEngine().getDatabaseSize(usingAddr) >= getMaxDatabaseInHost()){
                        return switchHostServer(usingAddr);
                    } else {
                        return DatabaseUtils.copyAddress(usingAddr, true, usingAddr.getSuffixIndex()+1, this.defineDbName);
                    }
                } else {
                    return usingAddr;
                }
            }
            
        } else {
            logger.debug("MultiDbSingleTableStrategy:只有一个地址库");
            Address usingAddr = this.getMetaDataEngine().getUsingAddress(getStoreId());
            if(usingAddr == null){
                logger.debug("还没有使用任何库,需要选择第一个");
                usingAddr = this.getDefineAddressList().get(0);
                return createFirstAddress(usingAddr);
            } else {
                logger.debug("已经使用了数据库:" + usingAddr);
                int tableSize = this.getMetaDataEngine().getTableSize(usingAddr);
                logger.debug("数据库 '" + usingAddr.getServiceName() + "' 表数量 = " + tableSize);
                if(tableSize >= getMaxTablesInDatabase()){
                    Address changedAddr = DatabaseUtils.copyAddress(usingAddr, true, usingAddr.getSuffixIndex()+1, this.defineDbName);
                    logger.info("表数量超过最大值,更换数据库:" + changedAddr);
                    return changedAddr;
                } else {
                    return usingAddr;
                }
            }
        }
    }
    
    private Address createFirstAddress(Address addr){
        return DatabaseUtils.copyAddress(addr, true, 1, this.defineDbName);
    }
    
    private Address switchHostServer(Address using){
        for(Address a : this.getDefineAddressList()){
            if(!using.getUrl().equals(a.getUrl()) 
                    || using.getPort() != a.getPort()){
                return DatabaseUtils.copyAddress(a, false, using.getSuffixIndex()+1, this.defineDbName);
            }
        }
        logger.warn("无法切换数据库,还使用目前的。请检查List<Address>配置");
        return DatabaseUtils.copyAddress(using, true, using.getSuffixIndex()+1, this.defineDbName);
    }
 
    @Override
    protected String doQueryTableName(Address address, String srcTable, Object parameter) {
        return srcTable;
    }
 
}