// Path: src/main/java/com/hyd/ssdb/protocol/Request.java
// public class Request {
// 
//     private Charset charset = AbstractClient.DEFAULT_CHARSET;
// 
//     private Block header;
// 
//     private Server forceServer;     // 强制指定请求的发送地址
// 
//     private final List<Block> blocks = new ArrayList<Block>();
// 
//     public Request(String command) {
//         String[] tokens = command.split("\\s+");
//         readTokens(tokens);
//     }
// 
//     public Request(Object... tokens) {
//         if (tokens.length == 0) {
//             throw new SsdbException("command is empty");
//         }
// 
//         readTokens(tokens);
//     }
// 
//     public Server getForceServer() {
//         return forceServer;
//     }
// 
//     public void setForceServer(Server forceServer) {
//         this.forceServer = forceServer;
//     }
// 
//     public Charset getCharset() {
//         return charset;
//     }
// 
//     public void setCharset(Charset charset) {
//         this.charset = charset;
//     }
// 
//     private void readTokens(Object[] tokens) {
// 
//         // 一个命令至少有 command 和 key 两个部分，然后可能有后面其他参数
//         if (isKeyRequired(tokens) && tokens.length < 2) {
//             throw new SsdbException("Command '" + tokens[0] + "' has no parameters or not supported.");
//         }
// 
//         this.header = new Block(tokens[0].toString().getBytes(charset));
// 
//         for (int i = 1; i < tokens.length; i++) {
//             Object token = tokens[i];
//             Block block;
//             if (token instanceof byte[]) {
//                 block = new Block((byte[]) token);
//             } else {
//                 block = new Block(token.toString().getBytes(charset));
//             }
//             this.blocks.add(block);
//         }
//     }
// 
//     private boolean isKeyRequired(Object[] tokens) {
//         if (tokens.length == 0) {
//             return true;
//         }
// 
//         return !(tokens[0].equals("dbsize") || tokens[0].equals("info"));
//     }
// 
//     public Block getHeader() {
//         return header;
//     }
// 
//     public List<Block> getBlocks() {
//         return blocks;
//     }
// 
//     public String getKey() {
//         return blocks.isEmpty() ? null : blocks.get(0).toString();    // 第一个参数一定是 key，用来决定其放在哪台服务器上
//     }
// 
//     @Override
//     public String toString() {
//         StringBuilder sb = new StringBuilder(header.toString()).append(' ');
// 
//         for (Block block : blocks) {
//             sb.append(block.toString()).append(' ');
//         }
// 
//         sb.deleteCharAt(sb.length() - 1);
//         return sb.toString();
//     }
// 
//     public byte[] toBytes() {
//         byte[][] byteArrays = new byte[blocks.size() + 2][];
// 
//         byteArrays[0] = header.toBytes();
//         for (int i = 0; i < blocks.size(); i++) {
//             byteArrays[i + 1] = blocks.get(i).toBytes();
//         }
//         byteArrays[byteArrays.length - 1] = new byte[]{'\n'};
// 
//         return Bytes.concat(byteArrays);
//     }
// }
// 
// Path: src/main/java/com/hyd/ssdb/protocol/WriteRequest.java
// public class WriteRequest extends Request {
// 
//     public WriteRequest(String command) {
//         super(command);
//     }
// 
//     public WriteRequest(Object... tokens) {
//         super(tokens);
//     }
// }


import com.hyd.ssdb.*;
import com.hyd.ssdb.conf.*;
import com.hyd.ssdb.protocol.Request;
import com.hyd.ssdb.protocol.WriteRequest;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

package com.hyd.ssdb.conn;


/**
 * NetworkManager 有两个职责：
 * 1、管理网络的拓扑结构（通过 Sharding 类），决定请求发送到哪个 SSDB 服务器；
 * 2、当请求发送失败时，自动更新失效的服务器列表，并尝试重新发送请求到同一
 * Cluster 的其他服务器，直到没有服务器可用，才抛出异常。
 *
 * @author Yiding
 */
public class ConnectionPoolManager {

    private static final Logger LOG = LoggerFactory.getLogger(ConnectionPoolManager.class);

    private Sharding sharding;  // 负载均衡拓扑结构

    private Map<Server, ConnectionPool> connectionPoolMap = new ConcurrentHashMap<Server, ConnectionPool>();


// Path: src/main/java/com/hyd/ssdb/protocol/Request.java
// public class Request {
// 
//     private Charset charset = AbstractClient.DEFAULT_CHARSET;
// 
//     private Block header;
// 
//     private Server forceServer;     // 强制指定请求的发送地址
// 
//     private final List<Block> blocks = new ArrayList<Block>();
// 
//     public Request(String command) {
//         String[] tokens = command.split("\\s+");
//         readTokens(tokens);
//     }
// 
//     public Request(Object... tokens) {
//         if (tokens.length == 0) {
//             throw new SsdbException("command is empty");
//         }
// 
//         readTokens(tokens);
//     }
// 
//     public Server getForceServer() {
//         return forceServer;
//     }
// 
//     public void setForceServer(Server forceServer) {
//         this.forceServer = forceServer;
//     }
// 
//     public Charset getCharset() {
//         return charset;
//     }
// 
//     public void setCharset(Charset charset) {
//         this.charset = charset;
//     }
// 
//     private void readTokens(Object[] tokens) {
// 
//         // 一个命令至少有 command 和 key 两个部分，然后可能有后面其他参数
//         if (isKeyRequired(tokens) && tokens.length < 2) {
//             throw new SsdbException("Command '" + tokens[0] + "' has no parameters or not supported.");
//         }
// 
//         this.header = new Block(tokens[0].toString().getBytes(charset));
// 
//         for (int i = 1; i < tokens.length; i++) {
//             Object token = tokens[i];
//             Block block;
//             if (token instanceof byte[]) {
//                 block = new Block((byte[]) token);
//             } else {
//                 block = new Block(token.toString().getBytes(charset));
//             }
//             this.blocks.add(block);
//         }
//     }
// 
//     private boolean isKeyRequired(Object[] tokens) {
//         if (tokens.length == 0) {
//             return true;
//         }
// 
//         return !(tokens[0].equals("dbsize") || tokens[0].equals("info"));
//     }
// 
//     public Block getHeader() {
//         return header;
//     }
// 
//     public List<Block> getBlocks() {
//         return blocks;
//     }
// 
//     public String getKey() {
//         return blocks.isEmpty() ? null : blocks.get(0).toString();    // 第一个参数一定是 key，用来决定其放在哪台服务器上
//     }
// 
//     @Override
//     public String toString() {
//         StringBuilder sb = new StringBuilder(header.toString()).append(' ');
// 
//         for (Block block : blocks) {
//             sb.append(block.toString()).append(' ');
//         }
// 
//         sb.deleteCharAt(sb.length() - 1);
//         return sb.toString();
//     }
// 
//     public byte[] toBytes() {
//         byte[][] byteArrays = new byte[blocks.size() + 2][];
// 
//         byteArrays[0] = header.toBytes();
//         for (int i = 0; i < blocks.size(); i++) {
//             byteArrays[i + 1] = blocks.get(i).toBytes();
//         }
//         byteArrays[byteArrays.length - 1] = new byte[]{'\n'};
// 
//         return Bytes.concat(byteArrays);
//     }
// }
// 
// Path: src/main/java/com/hyd/ssdb/protocol/WriteRequest.java
// public class WriteRequest extends Request {
// 
//     public WriteRequest(String command) {
//         super(command);
//     }
// 
//     public WriteRequest(Object... tokens) {
//         super(tokens);
//     }
// }


// Path: src/main/java/com/hyd/ssdb/conn/ConnectionPoolManager.java
import com.hyd.ssdb.*;
import com.hyd.ssdb.conf.*;
import com.hyd.ssdb.protocol.Request;
import com.hyd.ssdb.protocol.WriteRequest;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

package com.hyd.ssdb.conn;


/**
 * NetworkManager 有两个职责：
 * 1、管理网络的拓扑结构（通过 Sharding 类），决定请求发送到哪个 SSDB 服务器；
 * 2、当请求发送失败时，自动更新失效的服务器列表，并尝试重新发送请求到同一
 * Cluster 的其他服务器，直到没有服务器可用，才抛出异常。
 *
 * @author Yiding
 */
public class ConnectionPoolManager {

    private static final Logger LOG = LoggerFactory.getLogger(ConnectionPoolManager.class);

    private Sharding sharding;  // 负载均衡拓扑结构

    private Map<Server, ConnectionPool> connectionPoolMap = new ConcurrentHashMap<Server, ConnectionPool>();


    public ConnectionPoolManager(Sharding sharding) {
