Allow more ports per instance (#381)

This commit is contained in:
Kavindu Bimsara Fernando
2024-06-13 17:05:59 +05:30
committed by GitHub
parent 946b7dae36
commit d258f2ebae
14 changed files with 296 additions and 75 deletions

View File

@@ -33,7 +33,7 @@ namespace conf
* Create config here.
* @return 0 for success. -1 for failure.
*/
int create(std::string_view host_addr, const uint16_t init_peer_port, const uint16_t init_user_port, const uint16_t docker_registry_port,
int create(std::string_view host_addr, const uint16_t init_peer_port, const uint16_t init_user_port,const uint16_t init_gp_tcp_port, const uint16_t init_gp_udp_port, const uint16_t docker_registry_port,
const size_t inst_count, const size_t cpu_us, const size_t ram_kbytes, const size_t swap_kbytes, const size_t disk_kbytes)
{
if (util::is_file_exists(ctx.config_file))
@@ -62,6 +62,8 @@ namespace conf
cfg.hp.host_address = host_addr.empty() ? "127.0.0.1" : std::string(host_addr);
cfg.hp.init_peer_port = !init_peer_port ? 22861 : init_peer_port;
cfg.hp.init_user_port = !init_user_port ? 26201 : init_user_port;
cfg.hp.init_gp_tcp_port = !init_gp_tcp_port ? 36525 : init_gp_tcp_port;
cfg.hp.init_gp_udp_port = !init_gp_udp_port ? 39064 : init_gp_udp_port;
cfg.system.max_instance_count = !inst_count ? 3 : inst_count;
cfg.system.max_mem_kbytes = !ram_kbytes ? 1048576 : ram_kbytes;
@@ -229,6 +231,20 @@ namespace conf
std::cerr << "Configured init user port invalid. Should be greater than 1024\n";
return -1;
}
cfg.hp.init_gp_tcp_port = hp["init_gp_tcp_port"].as<uint16_t>();
if (cfg.hp.init_gp_tcp_port <= 1024)
{
std::cerr << "Configured init general purpose tcp port invalid. Should be greater than 1024\n";
return -1;
}
cfg.hp.init_gp_udp_port = hp["init_gp_udp_port"].as<uint16_t>();
if (cfg.hp.init_gp_udp_port <= 1024)
{
std::cerr << "Configured init general purpose udp port invalid. Should be greater than 1024\n";
return -1;
}
}
catch (const std::exception &e)
{
@@ -324,6 +340,8 @@ namespace conf
hp_config.insert_or_assign("host_address", cfg.hp.host_address);
hp_config.insert_or_assign("init_peer_port", cfg.hp.init_peer_port);
hp_config.insert_or_assign("init_user_port", cfg.hp.init_user_port);
hp_config.insert_or_assign("init_gp_tcp_port", cfg.hp.init_gp_tcp_port);
hp_config.insert_or_assign("init_gp_udp_port", cfg.hp.init_gp_udp_port);
d.insert_or_assign("hp", hp_config);
}

View File

@@ -71,6 +71,8 @@ namespace conf
std::string host_address;
uint16_t init_peer_port = 0;
uint16_t init_user_port = 0;
uint16_t init_gp_tcp_port = 0;
uint16_t init_gp_udp_port = 0;
};
struct system_config
@@ -125,7 +127,7 @@ namespace conf
int init();
int create(std::string_view host_addr, const uint16_t init_peer_port, const uint16_t init_user_port, const uint16_t docker_registry_port,
int create(std::string_view host_addr, const uint16_t init_peer_port, const uint16_t init_user_port,const uint16_t init_gp_tcp_port, const uint16_t init_gp_udp_port, const uint16_t docker_registry_port,
const size_t inst_count, const size_t cpu_us, const size_t ram_kbytes, const size_t swap_kbytes, const size_t disk_kbytes);
void set_dir_paths(std::string exepath, std::string datadir);

View File

@@ -32,7 +32,7 @@ namespace hp
// We keep docker logs at size limit of 10mb, We only need these logs for docker instance failure debugging since all other logs are kept in files.
// For the local log driver compression, minimum max-file should be 2. So we keep two logs each max-size is 5mb
constexpr const char *DOCKER_CREATE = "DOCKER_HOST=unix:///run/user/$(id -u %s)/docker.sock timeout --foreground -v -s SIGINT %ss %s/dockerbin/docker create -t -i --stop-signal=SIGINT --log-driver local \
--log-opt max-size=5m --log-opt max-file=2 --name=%s -p %s:%s -p %s:%s -p %s:%s/udp --restart unless-stopped --mount type=bind,source=%s,target=/contract %s run /contract";
--log-opt max-size=5m --log-opt max-file=2 --name=%s -p %s:%s -p %s:%s -p %s:%s/udp -p %s:%s -p %s:%s -p %s:%s/udp -p %s:%s/udp --restart unless-stopped --mount type=bind,source=%s,target=/contract %s run /contract";
constexpr const char *DOCKER_START = "DOCKER_HOST=unix:///run/user/$(id -u %s)/docker.sock %s/dockerbin/docker start %s";
constexpr const char *DOCKER_STOP = "DOCKER_HOST=unix:///run/user/$(id -u %s)/docker.sock %s/dockerbin/docker stop %s";
constexpr const char *DOCKER_REMOVE = "DOCKER_HOST=unix:///run/user/$(id -u %s)/docker.sock %s/dockerbin/docker rm -f %s";
@@ -88,8 +88,7 @@ namespace hp
}
// Populate the vacant ports vector with vacant ports of destroyed containers.
sqlite::get_vacant_ports(db, vacant_ports);
get_vacant_ports_list(vacant_ports);
// Calculate the resources per instance.
instance_resources.cpu_us = conf::cfg.system.max_cpu_us / conf::cfg.system.max_instance_count;
instance_resources.mem_kbytes = conf::cfg.system.max_mem_kbytes / conf::cfg.system.max_instance_count;
@@ -182,7 +181,7 @@ namespace hp
sqlite::get_max_ports(db, last_assigned_ports);
last_port_assign_from_vacant = false;
}
instance_ports = {(uint16_t)(last_assigned_ports.peer_port + 1), (uint16_t)(last_assigned_ports.user_port + 1)};
instance_ports = {(uint16_t)(last_assigned_ports.peer_port + 1), (uint16_t)(last_assigned_ports.user_port + 1), (uint16_t)(last_assigned_ports.gp_tcp_port_start + 2), (uint16_t)(last_assigned_ports.gp_udp_port_start + 2) };
}
int user_id;
@@ -313,11 +312,23 @@ namespace hp
{
const std::string user_port = std::to_string(assigned_ports.user_port);
const std::string peer_port = std::to_string(assigned_ports.peer_port);
const std::string gp_tcp_port_1 = std::to_string(assigned_ports.gp_tcp_port_start);
const std::string gp_tcp_port_2 = std::to_string(assigned_ports.gp_tcp_port_start + 1 );
const std::string gp_udp_port_1 = std::to_string(assigned_ports.gp_udp_port_start);
const std::string gp_udp_port_2 = std::to_string(assigned_ports.gp_udp_port_start + 1 );
const std::string timeout = std::to_string(DOCKER_CREATE_TIMEOUT_SECS);
const int len = 376 + username.length() + timeout.length() + conf::ctx.exe_dir.length() + container_name.length() + (user_port.length() * 2) + (peer_port.length() * 4) + contract_dir.length() + image_name.length();
const int len = 376 + username.length() + timeout.length() + conf::ctx.exe_dir.length() + container_name.length() + (user_port.length() * 2) + (peer_port.length() * 4) + (gp_tcp_port_1.length() * 2) + (gp_tcp_port_2.length() * 2) + (gp_udp_port_1.length() * 2) + (gp_udp_port_2.length() * 2) + contract_dir.length() + image_name.length();
char command[len];
sprintf(command, DOCKER_CREATE, username.data(), timeout.data(), conf::ctx.exe_dir.data(), container_name.data(),
user_port.data(), user_port.data(), peer_port.data(), peer_port.data(), peer_port.data(), peer_port.data(), contract_dir.data(), image_name.data());
user_port.data(), user_port.data(),
peer_port.data(), peer_port.data(),
peer_port.data(), peer_port.data(),
gp_tcp_port_1.data(), gp_tcp_port_1.data(),
gp_tcp_port_2.data(), gp_tcp_port_2.data(),
gp_udp_port_1.data(), gp_udp_port_1.data(),
gp_udp_port_2.data(), gp_udp_port_2.data(),
contract_dir.data(), image_name.data());
LOG_INFO << "Creating the docker container. name: " << container_name;
if (system(command) != 0)
{
@@ -906,6 +917,9 @@ namespace hp
std::to_string(contract_ugid.gid),
std::to_string(instance_ports.peer_port),
std::to_string(instance_ports.user_port),
std::to_string(instance_ports.gp_tcp_port_start),
std::to_string(instance_ports.gp_udp_port_start),
docker_image,
conf::cfg.docker.registry_address,
outbound_ipv6,
@@ -1019,7 +1033,53 @@ namespace hp
return 0;
}
/**
* Populate the given vector with vacant ports which are not already assigned.
* @param vacant_ports Ports vector to hold port pairs from database.
*/
void get_vacant_ports_list(std::vector<hp::ports> &vacant_ports)
{
const int gp_tcp_port_count=2;
const int gp_udp_port_count=2;
//get all instances
std::vector<hp::instance_info> instances;
get_instance_list(instances);
//no instances
if (instances.empty()) {
return;
}
//Get the max instance
const std::vector<hp::instance_info>::iterator element_max_peer_port = std::max_element(instances.begin(), instances.end(),
[](const hp::instance_info& a, const hp::instance_info& b) {
return (uint16_t)(a.assigned_ports.user_port) < (uint16_t)(b.assigned_ports.user_port);
});
ports init_ports = {(uint16_t)(conf::cfg.hp.init_peer_port), (uint16_t)(conf::cfg.hp.init_user_port), (uint16_t)(conf::cfg.hp.init_gp_tcp_port), (uint16_t)(conf::cfg.hp.init_gp_udp_port)};
//Keep increasing init port (peer port) until it reaches max port
//If init port values did not match with an item in the instances list, add init port values to vacant ports list.
while (init_ports.peer_port < element_max_peer_port->assigned_ports.peer_port)
{
bool is_item_available = std::find_if(instances.begin(),instances.end(),[init_ports](const instance_info& instance){
return instance.assigned_ports.peer_port == init_ports.peer_port;
}) != instances.end();
if(!is_item_available){
vacant_ports.push_back(init_ports);
}
init_ports.peer_port++;
init_ports.user_port++;
init_ports.gp_tcp_port_start+=gp_tcp_port_count;
init_ports.gp_udp_port_start+=gp_udp_port_count;
}
}
/**
* Check whether there's a pending reboot and cgrules service is running and configured.
* @return true if active and configured otherwise false.

View File

@@ -20,15 +20,18 @@ namespace hp
EXITED
};
// Stores port pair assigned to a container.
// Stores ports assigned to a container.
struct ports
{
uint16_t peer_port = 0;
uint16_t user_port = 0;
uint16_t gp_tcp_port_start = 0;
uint16_t gp_udp_port_start = 0;
bool operator==(const ports &other) const
{
return peer_port == other.peer_port && user_port == other.user_port;
return peer_port == other.peer_port && user_port == other.user_port && gp_tcp_port_start == other.gp_tcp_port_start && gp_udp_port_start == other.gp_udp_port_start;
}
};
@@ -109,5 +112,7 @@ namespace hp
bool system_ready();
void get_vacant_ports_list(std::vector<hp::ports> &vacant_ports);
} // namespace hp
#endif

View File

@@ -38,7 +38,7 @@ int parse_cmd(int argc, char **argv)
{
conf::ctx.command = argv[1];
if ((conf::ctx.command == "new" && argc >= 2 && argc <= 12) ||
if ((conf::ctx.command == "new" && argc >= 2 && argc <= 14) ||
(conf::ctx.command == "run" && argc >= 2 && argc <= 3) ||
(conf::ctx.command == "upgrade" && argc >= 2 && argc <= 3) ||
(conf::ctx.command == "version" && argc == 2) ||
@@ -134,18 +134,20 @@ int main(int argc, char **argv)
// This will create a new config.
const std::string host_addr = (argc >= 4) ? argv[3] : "";
uint16_t init_peer_port = 0, init_user_port = 0, docker_registry_port = 0;
uint16_t init_peer_port = 0, init_user_port = 0, init_gp_tcp_port = 0, init_gp_udp_port = 0, docker_registry_port = 0;
size_t inst_count = 0, cpu_us = 0, ram_kbytes = 0, swap_kbytes = 0, disk_kbytes = 0;
if (((argc >= 5) && util::stoul(argv[4], init_peer_port) != 0) ||
((argc >= 6) && util::stoul(argv[5], init_user_port) != 0) ||
((argc >= 7) && util::stoul(argv[6], docker_registry_port) != 0) ||
((argc >= 8) && (util::stoull(argv[7], inst_count) != 0 || inst_count == 0)) ||
((argc >= 9) && (util::stoull(argv[8], cpu_us) != 0 || cpu_us == 0)) ||
((argc >= 10) && (util::stoull(argv[9], ram_kbytes) != 0 || ram_kbytes == 0)) ||
((argc >= 11) && (util::stoull(argv[10], swap_kbytes) != 0 || swap_kbytes == 0)) ||
((argc >= 12) && (util::stoull(argv[11], disk_kbytes) != 0 || disk_kbytes == 0)) ||
conf::create(host_addr, init_peer_port, init_user_port, docker_registry_port, inst_count, cpu_us, ram_kbytes, swap_kbytes, disk_kbytes) != 0)
((argc >= 7) && util::stoul(argv[6], init_gp_tcp_port) != 0) ||
((argc >= 8) && util::stoul(argv[7], init_gp_udp_port) != 0) ||
((argc >= 9) && util::stoul(argv[8], docker_registry_port) != 0) ||
((argc >= 10) && (util::stoull(argv[9], inst_count) != 0 || inst_count == 0)) ||
((argc >= 11) && (util::stoull(argv[10], cpu_us) != 0 || cpu_us == 0)) ||
((argc >= 12) && (util::stoull(argv[11], ram_kbytes) != 0 || ram_kbytes == 0)) ||
((argc >= 13) && (util::stoull(argv[12], swap_kbytes) != 0 || swap_kbytes == 0)) ||
((argc >= 14) && (util::stoull(argv[13], disk_kbytes) != 0 || disk_kbytes == 0)) ||
conf::create(host_addr, init_peer_port, init_user_port, init_gp_tcp_port, init_gp_udp_port, docker_registry_port, inst_count, cpu_us, ram_kbytes, swap_kbytes, disk_kbytes) != 0)
{
std::cerr << "Invalid Sashimono Agent config creation args.\n";
std::cerr << docker_registry_port << ", " << inst_count << ", " << cpu_us << ", " << ram_kbytes << ", "

View File

@@ -709,6 +709,14 @@ namespace msg::json
msg += "user_port";
msg += SEP_COLON;
msg += std::to_string(info.assigned_ports.user_port);
msg += SEP_COMMA;
msg += "gp_tcp_port";
msg += SEP_COLON;
msg += std::to_string(info.assigned_ports.gp_tcp_port_start);
msg += SEP_COMMA;
msg += "gp_udp_port";
msg += SEP_COLON;
msg += std::to_string(info.assigned_ports.gp_udp_port_start);
msg += "\"}";
}
@@ -773,6 +781,14 @@ namespace msg::json
msg += "user_port";
msg += SEP_COLON_NOQUOTE;
msg += std::to_string(instance.assigned_ports.user_port);
msg += SEP_COMMA_NOQUOTE;
msg += "gp_tcp_port";
msg += SEP_COLON_NOQUOTE;
msg += std::to_string(instance.assigned_ports.gp_tcp_port_start);
msg += SEP_COMMA_NOQUOTE;
msg += "gp_udp_port";
msg += SEP_COLON_NOQUOTE;
msg += std::to_string(instance.assigned_ports.gp_udp_port_start);
// Include matching lease information.
const auto lease = std::find_if(leases.begin(), leases.end(), [&](const hp::lease_info &l)

View File

@@ -22,26 +22,26 @@ namespace sqlite
constexpr const char *INSERT_INTO_HP_INSTANCE = "INSERT INTO instances("
"owner_pubkey, time, username, status, name, ip,"
"peer_port, user_port, pubkey, contract_id, image_name"
") VALUES(?,?,?,?,?,?,?,?,?,?,?)";
"peer_port, user_port, init_gp_tcp_port, init_gp_udp_port, pubkey, contract_id, image_name"
") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)";
constexpr const char *GET_VACANT_PORTS_FROM_HP = "SELECT DISTINCT peer_port, user_port FROM "
constexpr const char *GET_VACANT_PORTS_FROM_HP = "SELECT DISTINCT peer_port, user_port, init_gp_tcp_port, init_gp_udp_port FROM "
"instances WHERE status == ? AND user_port NOT IN"
"(SELECT user_port FROM instances WHERE status != ?)";
constexpr const char *GET_MAX_PORTS_FROM_HP = "SELECT max(peer_port), max(user_port) FROM instances WHERE status != ?";
constexpr const char *GET_MAX_PORTS_FROM_HP = "SELECT max(peer_port), max(user_port), max(init_gp_tcp_port), max(init_gp_udp_port) FROM instances WHERE status != ?";
constexpr const char *UPDATE_STATUS_IN_HP = "UPDATE instances SET status = ? WHERE name = ?";
constexpr const char *IS_CONTAINER_EXISTS = "SELECT username, status, peer_port, user_port FROM instances WHERE name = ?";
constexpr const char *IS_CONTAINER_EXISTS = "SELECT username, status, peer_port, user_port, init_gp_tcp_port, init_gp_udp_port FROM instances WHERE name = ?";
constexpr const char *GET_ALOCATED_INSTANCE_COUNT = "SELECT COUNT(name) FROM instances WHERE status != ?";
constexpr const char *GET_RUNNING_INSTANCE_NAMES = "SELECT name FROM instances WHERE status = ?";
constexpr const char *GET_INSTANCE_LIST = "SELECT name, username, user_port, peer_port, status, image_name, contract_id FROM instances WHERE status != ?";
constexpr const char *GET_INSTANCE_LIST = "SELECT name, username, user_port, peer_port, init_gp_tcp_port, init_gp_udp_port, status, image_name, contract_id FROM instances WHERE status != ?";
constexpr const char *GET_INSTANCE = "SELECT name, username, user_port, peer_port, status, image_name FROM instances WHERE name == ? AND status != ?";
constexpr const char *GET_INSTANCE = "SELECT name, username, user_port, peer_port, init_gp_tcp_port, init_gp_udp_port, status, image_name FROM instances WHERE name == ? AND status != ?";
constexpr const char *IS_TABLE_EXISTS = "SELECT * FROM sqlite_master WHERE type='table' AND name = ?";
@@ -303,6 +303,8 @@ namespace sqlite
table_column_info("ip", COLUMN_DATA_TYPE::TEXT),
table_column_info("peer_port", COLUMN_DATA_TYPE::INT),
table_column_info("user_port", COLUMN_DATA_TYPE::INT),
table_column_info("init_gp_tcp_port", COLUMN_DATA_TYPE::INT),
table_column_info("init_gp_udp_port", COLUMN_DATA_TYPE::INT),
table_column_info("pubkey", COLUMN_DATA_TYPE::TEXT),
table_column_info("contract_id", COLUMN_DATA_TYPE::TEXT),
table_column_info("image_name", COLUMN_DATA_TYPE::TEXT)};
@@ -333,9 +335,11 @@ namespace sqlite
sqlite3_bind_text(stmt, 6, info.ip.data(), info.ip.length(), SQLITE_STATIC) == SQLITE_OK &&
sqlite3_bind_int64(stmt, 7, info.assigned_ports.peer_port) == SQLITE_OK &&
sqlite3_bind_int64(stmt, 8, info.assigned_ports.user_port) == SQLITE_OK &&
sqlite3_bind_text(stmt, 9, info.pubkey.data(), info.pubkey.length(), SQLITE_STATIC) == SQLITE_OK &&
sqlite3_bind_text(stmt, 10, info.contract_id.data(), info.contract_id.length(), SQLITE_STATIC) == SQLITE_OK &&
sqlite3_bind_text(stmt, 11, info.image_name.data(), info.image_name.length(), SQLITE_STATIC) == SQLITE_OK &&
sqlite3_bind_int64(stmt, 9, info.assigned_ports.gp_tcp_port_start) == SQLITE_OK &&
sqlite3_bind_int64(stmt, 10, info.assigned_ports.gp_udp_port_start) == SQLITE_OK &&
sqlite3_bind_text(stmt, 11, info.pubkey.data(), info.pubkey.length(), SQLITE_STATIC) == SQLITE_OK &&
sqlite3_bind_text(stmt, 12, info.contract_id.data(), info.contract_id.length(), SQLITE_STATIC) == SQLITE_OK &&
sqlite3_bind_text(stmt, 13, info.image_name.data(), info.image_name.length(), SQLITE_STATIC) == SQLITE_OK &&
sqlite3_step(stmt) == SQLITE_DONE)
{
sqlite3_finalize(stmt);
@@ -366,6 +370,8 @@ namespace sqlite
info.status = std::string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)));
info.assigned_ports.peer_port = sqlite3_column_int64(stmt, 2);
info.assigned_ports.user_port = sqlite3_column_int64(stmt, 3);
info.assigned_ports.gp_tcp_port_start = sqlite3_column_int64(stmt, 4);
info.assigned_ports.gp_udp_port_start = sqlite3_column_int64(stmt, 5);
// Finalize and distroys the statement.
sqlite3_finalize(stmt);
@@ -414,13 +420,15 @@ namespace sqlite
{
const uint16_t peer_port = sqlite3_column_int64(stmt, 0);
const uint16_t user_port = sqlite3_column_int64(stmt, 1);
const uint16_t gp_tcp_port_start = sqlite3_column_int64(stmt, 2);
const uint16_t gp_udp_port_start = sqlite3_column_int64(stmt, 3);
max_ports = {peer_port, user_port};
max_ports = {peer_port, user_port, gp_tcp_port_start, gp_udp_port_start};
}
// Initialize with default config values if either of the ports are zero.
if (max_ports.peer_port == 0 || max_ports.user_port == 0)
if (max_ports.peer_port == 0 || max_ports.user_port == 0 || max_ports.gp_tcp_port_start == 0 || max_ports.gp_udp_port_start == 0)
{
max_ports = {(uint16_t)(conf::cfg.hp.init_peer_port - 1), (uint16_t)(conf::cfg.hp.init_user_port - 1)};
max_ports = {(uint16_t)(conf::cfg.hp.init_peer_port - 1), (uint16_t)(conf::cfg.hp.init_user_port - 1), (uint16_t)(conf::cfg.hp.init_gp_tcp_port - 2), (uint16_t)(conf::cfg.hp.init_gp_udp_port - 2)};
}
// Finalize and distroys the statement.
@@ -446,7 +454,9 @@ namespace sqlite
{
const uint16_t peer_port = sqlite3_column_int64(stmt, 0);
const uint16_t user_port = sqlite3_column_int64(stmt, 1);
vacant_ports.push_back({peer_port, user_port});
const uint16_t gp_tcp_port = sqlite3_column_int64(stmt, 2);
const uint16_t gp_udp_port = sqlite3_column_int64(stmt, 3);
vacant_ports.push_back({peer_port, user_port, gp_tcp_port, gp_udp_port});
}
}
@@ -500,9 +510,11 @@ namespace sqlite
info.username = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1));
info.assigned_ports.user_port = sqlite3_column_int64(stmt, 2);
info.assigned_ports.peer_port = sqlite3_column_int64(stmt, 3);
info.status = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 4));
info.image_name = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 5));
info.contract_id = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 6));
info.assigned_ports.gp_tcp_port_start = sqlite3_column_int64(stmt, 4);
info.assigned_ports.gp_udp_port_start = sqlite3_column_int64(stmt, 5);
info.status = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 6));
info.image_name = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 7));
info.contract_id = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 8));
instances.push_back(info);
}
}
@@ -558,8 +570,10 @@ namespace sqlite
instance.username = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1));
instance.assigned_ports.user_port = sqlite3_column_int64(stmt, 2);
instance.assigned_ports.peer_port = sqlite3_column_int64(stmt, 3);
instance.status = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 4));
instance.image_name = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 5));
instance.assigned_ports.gp_tcp_port_start = sqlite3_column_int64(stmt, 4);
instance.assigned_ports.gp_udp_port_start = sqlite3_column_int64(stmt, 5);
instance.status = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 6));
instance.image_name = reinterpret_cast<const char *>(sqlite3_column_text(stmt, 7));
// Finalize and distroys the statement.
sqlite3_finalize(stmt);