C++ (Korean) insert error (Incorrect string value) - c++

DB is a C ++ in conjunction with student card management program.
Enter your information to receive a student receives a first input your name and ID. The problem is that there is an error in the insert names.
When directly from MS-DOS window insert (visual studio X)
Hangul (korean) is normal.
(Try the workaround that looked out to the Internet.)
when the insert through a C ++, Hangul (Korean) is not.
hakbun int(50) not null primary key,
name char(100) not null
▲ columns of the table, including information
▲ query status
Source Code
#include "stdio.h"
#include "winsock2.h"
#include "mysql.h"
#include "tchar.h"
#include <iostream>
#include <stdio.h>
using namespace std;
#pragma comment (lib, "libmysql.lib")
const char * host = "localhost";
const char * user = "root";
const char * pw = "1234";
const char * db = "point_db";
void DBconnect () {
 MYSQL * connection = NULL, conn;
 MYSQL_RES * sql_result;
 MYSQL_ROW sql_row;
 mysql_init (& conn);
 connection = mysql_real_connect (& conn, host, user, pw, db, 3306, (char *) NULL, 0);
 if (connection == NULL) {
  printf ( "con error");
 }
 // Mysql_query (connection, "set session character_set_connection = utf-8;");
 // Mysql_query (connection, "set session character_set_results = utf-8;");
 // Mysql_query (connection, "set session character_set_client = utf-8;");
}
int _tmain (int argc, _TCHAR * argv []) {
 
 MYSQL * connection = NULL;
 MYSQL conn;
 MYSQL_RES * sql_result;
 MYSQL_ROW sql_row;
 if (mysql_init (& conn) == NULL) {
  printf ( "mysql_init () error!");
 }
 connection = mysql_real_connect (& conn, host, user, pw, db, 3306, (const char *) NULL, 0);
 if (connection == NULL) {
  printf ( "% d Error:% s,% d \ n", mysql_errno (& conn), mysql_error (& conn));
  return 1;
 }
 else {
  DBconnect ();
  int query_stat;
  char query [1024];
  char num;
  while (1) {
   cout << "+ -------------------- +" << endl;
   cout << "| ① create card |" << Endl;
   cout << "+ -------------------- +" << endl;
   cout << "Enter Number (Played: 0)>";
   cin >> num;
   switch (num) {
   case '1':
    int i, hakbun, student;
    char name [100];
    cout << "student number";
    cin >> hakbun;
    cout << "name";
    cin >> name;
    // Insert
    sprintf_s (query, "insert into point (hakbun, name) values ​​( '% d', '% s')", hakbun, name);
    query_stat = mysql_query (connection, query);
    if (query_stat! = 0) {
     printf ( "error:% s", mysql_error (& conn));
     return 1;
    }
    else {
     cout << "you have completed the creation card." << Endl;
    }
   default:
    cout << "to end the program." << Endl;
    exit (0);
   }
  }
 }
}
my.ini file Detail
[mysqld]
basedir = C:/mysql-5.7.15-winx64
datadir = C:/mysql-5.7.15-winx64/data
port = 3306
# server_id = .....
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
#add
character-set-client-handshake = FALSE
init_connect=”SET collation_connection = utf8_general_ci”
init_connect=”SET NAMES utf8″
character-set-server = utf8
[client]
default-character-set = utf8
[mysql]
default-character-set = utf8
[mysqldump]
default-character-set = utf8

Related

Why mysql_init(nullptr) leads to segmentation fault in the following code?

My code is as follow:
main.cc
int main(void){
int port, sqlPort, ConnectionNum, threadNum;
string sqlUser, sqlPwd, DBName;
try{
Config Settings("./config.ini");
Settings.Read("port",port);
Settings.Read("sqlPort",sqlPort);
Settings.Read("sqlUser",sqlUser);
Settings.Read("sqlPwd",sqlPwd);
Settings.Read("DBName",DBName);
Settings.Read("ConnectionNum",ConnectionNum);
Settings.Read("threadNum",threadNum);
}catch(File_Not_Found& e){
cerr << "Cannot Find the Configuration File:" << e.what() << endl;
exit(1);
}catch(Key_Not_Found& e){
cerr << "Cannot Find the Keyword:" << e.what() << endl;
exit(1);
}
WebServer server(port, 5000, sqlPort, sqlUser, sqlPwd,DBName, ConnectionNum, threadNum );
//server.Start();
return 0;
}
WebServer.cc
WebServer::WebServer(int port, int timeoutMS, int sqlPort,
const std::string& sqlUser, const std::string& sqlPwd,
const std::string& dbName, int connPoolNum, int threadNum)
:m_port(port), m_timeoutMS(timeoutMS),
m_epoller(new Epoller()),m_timer(new TimerHeap()){
assert(port < 65535 && port > 1024);
m_srcDir = get_current_dir_name();
assert(m_srcDir);
strncat(m_srcDir, "/resources/", 16);
HttpConn::userCnt = 0;
HttpConn::srcDir = m_srcDir;
connPool->init("localhost", sqlUser, sqlPwd, dbName, sqlPort, connPoolNum);
threadPool->start(threadNum);
m_isRunning = InitSocket();
if(m_isRunning){
LOG_INFO << "===================== Server Init Success =====================";
LOG_INFO << "Port : " << m_port << ", srcDir :" << m_srcDir;
LOG_INFO << "threadNum : " << threadNum << ", ConnectionNum : " << connPoolNum;
}else{
LOG_FATAL << "Socket Init Failure";
}
}
SqlConnectionPool.cc
ConnectionPool *ConnectionPool::GetInstance()
{
static ConnectionPool connPool;
return &connPool;
}
void ConnectionPool::init(string url, string User, string PassWord, string DBName, int Port, int MaxConn)
{
m_url = url;
m_Port = Port;
m_User = User;
m_PassWord = PassWord;
m_DatabaseName = DBName;
for (int i = 0; i < MaxConn; i++)
{
MYSQL *con = NULL;
con = mysql_init(con); //segmentation fault happened!!
if (con == NULL)
{
LOG_FATAL << "MySQL Init Error";
}
con = mysql_real_connect(con, url.c_str(), User.c_str(), PassWord.c_str(), DBName.c_str(), Port, NULL, 0);
if (con == NULL)
{
LOG_FATAL << "MySQL Get Real Connection Error";
}
connList.push_back(con);
++m_FreeConn;
}
m_MaxConn = m_FreeConn;
}
As is shown in the picture above, the pointer con is always nullptr and it leads to segmentation fault. And I write another code to test SqlConnectionPool.cc file, but this time it works perfectly.
SqlConnectionPool_test.cc(part of code)
ConnectionPool* connPool = ConnectionPool::GetInstance();
unordered_map<string, string> users;
vector<thread> thread_pool;
int main(void){
connPool->init("localhost", "root", "123123", "zjwdb", 3306, 8);
{
MYSQL *mysql = NULL;
connectionRAII mysqlcon(&mysql, connPool);
if(mysql_query(mysql, "CREATE TABLE user_test(username VARCHAR(100) NOT NULL,passwd VARCHAR(60) NOT NULL,PRIMARY KEY ( username ));")){
LOG_ERROR << "CREATE TABLE user_test Failed : " << mysql_error(mysql);
}
if(!Register("test1", "test1")){
LOG_ERROR << "INSERT test user Failed";
}
if(!Register("test2", "test2")){
LOG_ERROR << "INSERT test user Failed";
}
if(!Register("test3", "test3")){
LOG_ERROR << "INSERT test user Failed";
}
showUsers(mysql);
}
CountDownLatch latch(4);
thread_pool.emplace_back(login, "test1", "test1");
thread_pool.emplace_back(login, "test5", "test5");
thread_pool.emplace_back(login, "test1", "test");
thread_pool.emplace_back([](CountDownLatch& latch, string const& name, string const& passwd)
{
latch.countDown();
latch.wait();
Register(name, passwd);
login(name, passwd);
}
, std::ref(latch), "test_user1", "123123");
thread_pool.emplace_back([](CountDownLatch& latch, string const& name, string const& passwd)
{
latch.countDown();
latch.wait();
Register(name, passwd);
login(name, passwd);
}
, std::ref(latch), "test_user2", "123123");
thread_pool.emplace_back([](CountDownLatch& latch, string const& name, string const& passwd)
{
latch.countDown();
latch.wait();
Register(name, passwd);
login(name, passwd);
}
, std::ref(latch), "test_user3", "123123");
thread_pool.emplace_back([](CountDownLatch& latch, string const& name, string const& passwd)
{
latch.countDown();
latch.wait();
Register(name, passwd);
login(name, passwd);
}
, std::ref(latch), "test3", "test3");
for(auto& th : thread_pool){
if(th.joinable())
th.join();
}
MYSQL* conn_temp = NULL;
connectionRAII mysqlconn_temp(&conn_temp, connPool);
showUsers(conn_temp);
dropTheTable();
return 0;
}
That really confuse me. Is it a bug of libmysql.lib?? If it is, how should I slove it?
PS:
My Ubuntu version is Ubuntu-16.04 and the lib version is libmysqlclient.so.20.
The SqlConnectionPool_test.cc is running in a multithread envirnment. Reason has it that this test file is more likely to crash becuase mysql_init is not thread-safe. But it can work perfectly.
Please let me know if you need more information, thanks!

TCP server message extra characters c++

I think I am missing something and doesn't make sense.
I am writing pretty simple TCP server, everything works pretty much as expected, but when a message saying "500 LOGIN FAILED" gets send over network, it get interpreted as "$500 LOGIN FAILED".
I am testing my server using telnet on localhost
here is simplified version of my code
recv(c_sockfd, buf, BUFFSIZE, 0))
inBuffer.push_back(buf);
auto messageToSend = checkResponse(parseBuffer(inBuffer.back()));
//get the second thing in the tuple
outBuffer.push_back(std::get<1>(messageToSend));
bzero(buf, sizeof(buf));
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
in the checkResponse func, I am implementing logic to decide what message to send, and somehow when I send ERROR message the extra character is added at the beginning of the message.
EXAMPLE 1:
Connected to localhost.
Escape character is '^]'.
200 LOGIN
Robot345\r\n
201 PASSWORD
674\r\n
202 OK
INFO iasdijasdjiajsdiajdijasidjiansdjsdvhdf dfvsdfsdf\r\n
&501 SYNTAX ERROR
Notice the "&" character
EXAMPLE 2:
Connected to localhost.
Escape character is '^]'.
200 LOGIN
Robot345\r\n
201 PASSWORD
456\r\n
$500 LOGIN FAILED
Notice the "$" character
Does anyone have any idea where the extra characters could be added to the string?
I didn't want to include full code, because the requirement was to have all in one file, which makes it difficult to read. Here it goes tho.
FULL CODE:
#include <iostream>
#include <regex>
#include <iterator>
#include <vector>
#include <sstream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <tuple>
#define MIN_PORT 3000
#define MAX_PORT 3999
#define BUFFSIZE 1000
/**
0 - LOGIN SUCCESSFUL, USERNAME IS IN THE BUFFER
1 - PASSWORD CHECK
2 - PASSWORD OK, COMMUNICATING
*/
int state = 0;
std::string username, password;
/**
CHECKS ENTERED PASSWORD BASES ON THE SUM OF ASCII VALUES OF USERNAME
#return: true on success, false otherwise
*/
bool checkPassword(std::string password){
std::istringstream sst;
sst.str(username);
unsigned char byte = '\0';
int value = 0;
// std::cout << "byte poprve: " << byte << std::endl;
// std::cout << "byte poprve INT: " << (int) byte << std::endl;
while (sst >> byte) {
std::cout << "podruhe: " << byte << std::endl;
std::cout << "podruhe INT: " << (int) byte << std::endl;
std::cout << "Prubezna SUMA: " << (int) value << std::endl;
value += byte;
}
std::cout << "suma: " << value << std::endl;
// Check the entered password
if (password == std::to_string(value)) {
return true;
}
return false;
}
/**
CHECKS MESSAGE SYNTAX BASED ON THE STATE WE ARE IN
CHECKS PASSWORD
CHECKS CHECK SUM
#param response <string type (if available), string message to parse>
#return TRUE on success, FALSE otherwise
*/
bool checkMessage(std::tuple<std::string,std::string> response){
auto messageToParse = std::get<1>(response);
std::string delimeter = "\r\n";
std::string::size_type pos = messageToParse.find(delimeter);
//INITIAL CHECK
if (pos < 1){
return false;
}
//somehow you have to multiply the length by 2
auto parsedMessage = messageToParse.substr(0,pos - 2*delimeter.length());
std::cout << parsedMessage << " : THIS IS YOUR PARSED MESSAGE";
//USERNAME
if (state == 0) {
username = parsedMessage;
return true;
}
//PASSWORD CHECK
if (state == 1 && checkPassword(parsedMessage)) {
password = parsedMessage;
return true;
}
if (state == 2) {
std::string type = std::get<0>(response);
//INFO
if( type == "I" ){
return true;
}
//PHOTO
if ( type == "F") {
return true;
}
}
return false;
}
/**
THIS FUNC WILL CHECK RESPONSE FROM THE ROBOT, AND DECIDE WHAT TO DO BASED ON THE STATE
#return tuple<bool TRUE if everything is right,std::string MESSAGE to send to the robot>
*/
std::tuple<bool,std::string> checkResponse(std::tuple<std::string, std::string> response){
if (state == 0) {
if (checkMessage(response)) {
std::cout << state << " / / state" << std::endl;
return std::make_tuple(true, "201 PASSWORD\r\n");
}
}
if (state == 1) {
// TADY BUDE JESTE PODMINKA, ZE HESLO JE SPRAVNE
if(checkMessage(response)){
std::cout << state << " / / / state" << std::endl;
return std::make_tuple(true, "202 OK\r\n");
}else{
std::cout << state << " / / / / state" << std::endl;
return std::make_tuple(false, "500 LOGIN FAILED\r\n");
}
}
if (state == 2) {
if (checkMessage(response)) {
std::cout << state << " / / / / / state" << std::endl;
return std::make_tuple(true, "202 OK\r\n");
}else{
std::cout << state << " / / / / / / state" << std::endl;
return std::make_tuple(false, "501 SYNTAX ERROR \r\n");
}
}
std::cout << state << " / / / / / / / / state" << std::endl;
return std::make_tuple(false, "unexpected result");
}
/**
This func will parse the incoming buffer
#param buffer incoming buffer
#return tuple <String type of message (U,I,P,F), String actual message>
*/
std::tuple<std::string, std::string> parseBuffer(std::string buffer){
if (state == 0) {
return std::make_tuple("U", buffer);
}
if (state == 1) {
return std::make_tuple("P", buffer);
}else{
std::string delimeter = " ";
std::string::size_type pos = buffer.find(delimeter);
std::string type = buffer.substr(0, pos );
std::string message = buffer.erase(0, pos + delimeter.length());
return std::make_tuple(type, message);
}
}
int main(int argc, char *argv[])
{
char buf[BUFFSIZE];
std::vector<std::string> outBuffer;
std::vector<std::string> inBuffer;
int sockfd, c_sockfd;
sockaddr_in my_addr, rem_addr;
socklen_t rem_addr_length;
int mlen;
const int PORT_NUM = atoi(argv[1]);
if( (PORT_NUM > MAX_PORT) || (PORT_NUM < MIN_PORT)){
perror("Port number is not acceptable");
exit(-1);
}
if ((sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
perror("Socket nelze otevrit");
exit(-1);
}
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT_NUM);
std::cout << PORT_NUM << " PORT NUM" << std::endl;
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1)
{
perror("Chyba v bind");
close(sockfd); exit(1);
}
if (listen(sockfd, SOMAXCONN) == -1)
{
perror("Nelze provest listen");
close(sockfd); exit(1);
}
while (1)
{
rem_addr_length=sizeof(rem_addr);
c_sockfd = accept(sockfd, (struct sockaddr*) &rem_addr, &rem_addr_length);
if ( c_sockfd == -1)
{
perror("Nelze accept");
close(sockfd); exit(1);
}
///FIRST MESSAGE
std::string ok = "200 LOGIN\r\n";
send(c_sockfd, &ok, sizeof(std::string), 0);
if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
perror("Chyba pri cteni");
else{
while (mlen)
{
///---------- MAIN PART--------------
//This is where comunication is happening
inBuffer.push_back(buf);
//Parse the buffer, check the message and
auto messageToSend = checkResponse(parseBuffer(inBuffer.back()));
//get the second thing in the tuple
outBuffer.push_back(std::get<1>(messageToSend));
bzero(buf, sizeof(buf));
///---------- MAIN PART--------------
state++;
std::cout << state << " state num" << std::endl;
if (send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0) == -1)
{
perror("Chyba pri zapisu");
break;
}else{
}
std::cout << inBuffer.back() << std::endl;
if ((mlen = recv(c_sockfd, buf, BUFFSIZE, 0)) == -1)
{
perror("Chyba pri cteni");
break;
}
}
close(c_sockfd);
}
}
}
The problem is with this:
std::vector<std::string> outBuffer;
and this:
send(c_sockfd, &outBuffer.back(), sizeof( outBuffer.back() ), 0)
You can't send std::string objects over the network. You must send the string it contains. Those are two very different things.
For a simple fix, do e.g.
send(c_sockfd, outBuffer.back().c_str(), outBuffer.back().length(), 0)
If you want to send the terminating null then add one to the length to send.
For more details, while implementations of std::string is allowed to optimize small strings to be contained inside the actual object, otherwise a std::string object is really nothing more than a size and a pointer to the actual string (implementations might have other members as well).
A pointer is unique to the currently running process on the host system. You can't transfer a pointer over the network. You can't even save a pointer to a file and then load it again and have it working in a new process (even if it's a process from the same program).
By sending the std::string object, all you're really sending is this pointer. So on the receiving side it have no idea what you're really sending and how it should treat that.

deserialization of pod struct stored in redis fails if key is defined as std::string

Storing of POD struct in redis works fine with const char * but doesn't if std::string is involved.
const char * example
#include <hiredis/hiredis.h>
#include <string.h>
#include <string>
#include <iostream>
using namespace std;
struct Test
{
const uint32_t id;
const char *name;
};
int main() {
redisContext *context = redisConnect("127.0.0.1", 6379);
if (context == NULL || context->err) {
if (context) {
printf("Error: %s\n", context->errstr);
} else {
printf("Can't allocate redis context\n");
}
exit(EXIT_FAILURE);
}
Test obj = {(uint32_t) 123, "foo bar"};
const size_t size = 2 * sizeof(uint32_t) + (strlen(obj.name) + 1);
cout << "object{id: " << obj.id << ", name:' " << obj.name << "'}; size: " << size << endl;
redisReply *reply = 0;
const char *key = strdup("some-key");
reply = (redisReply *) redisCommand(context, "SET %b %b", key, strlen(key), &obj, size);
if (!reply)
return REDIS_ERR;
freeReplyObject(reply);
reply = (redisReply *) redisCommand(context, "GET %s", key);
if (!reply)
return REDIS_ERR;
Test *res = (struct Test*) reply->str;
cout << "result{id: " << res->id << ", name:' " << res->name << "'}; size: " << size << endl;
freeReplyObject(reply);
redisFree(context);
}
If I replace the lines:
const char *key = strdup("some-key");
reply = (redisReply *) redisCommand(context, "SET %b %b", key, strlen(key), &obj, size);
with
std::string key("some-key");
reply = (redisReply *) redisCommand(context, "SET %b %b", key.c_str(), key.size(), &obj, size);
the execution always ends in Segmentation fault.
I can't solve the issue by myself and I would really appreciate any help.
OK, I got it:
replacement of second redisCommand statement
reply = (redisReply *) redisCommand(context, "GET %b", key.c_str(), key.size());
solved the issue.

How to break C++ program into modules

I'm writing a c++ program that has two functions that can run completely independent one from another. So i want to break them into two programs.
The problem is that both of them rely on the same set of functions (that can grow or change). What i want to do is include this set of functions as a header in both programs so i dont have to copy/paste every time i change something (i also hate duplicating functions or anything).
I know is a silly question but i couldn't find any documentation on the matter.
If the code is necessary ask for it and i will post it.
Thanks!
EDIT:
Adding code:
The functions that can run independent are make_video() and delete_video()
Please have in mind that this is far from done.
#include <sys/types.h>
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string>
#include <cstring>
#include <dirent.h>
#include <vector>
#include <time.h>
#include <csignal>
#include <algorithm>
#include <functional>
#include <cctype>
#include <locale>
#include <mysql/mysql.h>
#include <mysql_connection.h>
#include <mysql_driver.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
struct config_t{
std::string sql_host; //mysql host
std::string sql_user; //mysql user
std::string sql_pass; //mysql password
std::string sql_db; //zoneminder database name
std::string sql_ev_zm; //zoneminder events table
std::string sql_ev_vid; //video events table
std::string sql_ev_videxp; //video events expiration table
std::string sql_mon; //zm monitors table
std::string dir_ev; //Zoneminder events directory
std::string dir_vid; //manager videos directory
std::string dir_ram; //Ramfs mount directory
std::string ram_size; //ramfs size
};
int is_dir(const char *pathname){
struct stat info;
if( stat( pathname, &info ) != 0 )
return -1;
else if( info.st_mode & S_IFDIR ) // S_ISDIR() doesn't exist on my windows
return 1;
else
return 0;
}
// trim from start (in place)
static inline void ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
}
// trim from end (in place)
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrimmed(std::string s) {
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrimmed(std::string s) {
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trimmed(std::string s) {
trim(s);
return s;
}
bool DirectoryExists ( const char* path ){
if( path == NULL )return false;
DIR *d;
d = opendir(path);
if (d){
closedir(d);
return true;
}
return false;
}
std::ifstream::pos_type filesize(const char* filename){
std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
return in.tellg();
}
bool mount_ramfs(config_t *conf){
return false;
}
bool make_video(config_t *conf, std::string path = "", int depth = 0){
try{
sql::mysql::MySQL_Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
driver = sql::mysql::get_mysql_driver_instance();
con = driver->connect(conf->sql_host, conf->sql_user, conf->sql_pass);
stmt = con->createStatement();
stmt->execute("USE " + conf->sql_db);
std::string query = "SELECT Id, MonitorId, StartTime, EndTime, Length, Frames FROM " + conf->sql_ev_zm + " WHERE EndTime IS NOT NULL LIMIT 10"; //select a bunch of events for processing, EndTime NOT NULL means that the event is complete and not corrupted
//syslog (LOG_DEBUG, "Mysql Query: %s", query.c_str());
res = stmt->executeQuery(query);
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime < NOW() - INTERVAL 1 DAY ORDER BY Id ASC LIMIT 1
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime LIKE "%2015-11-18%" and MonitorId = 56
// conf.dir_ev + "/" + MonitorId + "/" + todir(StartTime)
while (res->next()) {
int id = res->getInt("Id");
int monitor = res->getInt("MonitorId");
std::string start_time = res->getString("StartTime");
std::string end_time = res->getString("EndTime");
int lenght = res->getInt("Length");
int frames = res->getInt("Frames");
//Get event directory form table data; the dir structure is id/YY/MM/DD/HH/mm/ss/
char sttm[60] = {};
std::strcpy(sttm, start_time.c_str());
char * tkn = (char*)malloc(60);
std::stringstream pathSS;
pathSS << conf->dir_ev << '/' << id << '/'; //prepare the path
tkn = std::strtok (sttm," -:"); //here we tokenize the StartTime field to match the source directory structure
if (tkn != NULL) {
pathSS << tkn[2] << tkn[3] << '/';
tkn = std::strtok (NULL, " -:");
}
while (tkn != NULL) {
pathSS << tkn << '/';
tkn = std::strtok (NULL, " -:");
}
std::string src = pathSS.str();
pathSS.clear();
pathSS << conf->dir_vid << '/' << id << '/'; //prepare the path
std::string dest = pathSS.str();
pathSS.clear();
tkn = std::strtok (sttm," -:"); //here we tokenize the StartTime field to make the destinantion and filename
while (tkn != NULL) {
pathSS << tkn << '_'; //sadly this will always lead to "_.mp4" but its not that bad or important
tkn = std::strtok (NULL, " -:");
}
pathSS << ".mp4";
std::string fname = pathSS.str();
pathSS.clear();
//do event video and
/*std::string cmd = "mkdir -p " + conf->dir_vid + path;
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());
cmd = "tar -zcf " + conf->dir_vid + path + "/" + dirlist[i] +".tar.gz " + conf->dir_ev + path + "/" + dirlist[i];
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());
cmd = "rm -rf " + conf->dir_ev + src + "*";
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());*/
try{
//insert new row in videos table
pathSS << "INSERT INTO " << conf->sql_ev_vid << " (startTime, endTime, monitor, filename) VALUES (\'" << start_time << "\', \'" << end_time << "\', " << monitor << ",\'" << dest << fname << "\')";
stmt->execute(pathSS.str());
pathSS.clear();
//delete non existing event
pathSS << "DELETE FROM " << conf->sql_ev_zm << " WHERE Id = " << id;
stmt->execute(pathSS.str());
pathSS.clear();
}
catch(sql::SQLException &e){
syslog (LOG_ERR, "Mysql Exception: %s, ERRNO %i, MySQL State: %s", e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str());
exit(EXIT_FAILURE);
}
}
delete res;
delete stmt;
delete con;
}
catch(sql::SQLException &e){
syslog (LOG_ERR, "Mysql Exception: %s, ERRNO %i, MySQL State: %s", e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str());
exit(EXIT_FAILURE);
}
return true;
}
bool delete_video(config_t *conf){
try{
sql::mysql::MySQL_Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
sql::ResultSet *subres;
driver = sql::mysql::get_mysql_driver_instance();
con = driver->connect(conf->sql_host, conf->sql_user, conf->sql_pass);
stmt = con->createStatement();
stmt->execute("USE " + conf->sql_db);
std::string query = "SELECT monitor, recording_days FROM " + conf->sql_ev_videxp + " WHERE 1";
//syslog (LOG_DEBUG, "Mysql Query: %s", query.c_str());
res = stmt->executeQuery(query);
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime < NOW() - INTERVAL 1 DAY ORDER BY Id ASC LIMIT 1
// SELECT Id, MonitorId, StartTime FROM Events WHERE StartTime LIKE "%2015-11-18%" and MonitorId = 56
// conf.dir_ev + "/" + MonitorId + "/" + todir(StartTime)
while (res->next()) {
int id = res->getInt("Id");
int r_days = res->getInt("recording_days");
//syslog (LOG_DEBUG, "Id: %i, Recording Days: %i", id, r_days);
std::stringstream subQuerySS;
subQuerySS << "SELECT id, file FROM " << conf->sql_ev_vid << " WHERE date < NOW() - INTERVAL " << r_days << " DAY AND monitor = " << id;
std::string subQuery = subQuerySS.str();
subQuerySS.clear();
//syslog (LOG_DEBUG, "Mysql Query: %s", subQuery.c_str());
subres = stmt->executeQuery(subQuery);
while (subres->next()) {
int subid = subres->getInt("id");
std::string file = subres->getString("file");
std::string cmd = "rm -f " + file;
syslog (LOG_DEBUG, "%s", cmd.c_str());
std::system(cmd.c_str());
std::stringstream delQuerySS;
delQuerySS << "DELETE FROM " << conf->sql_ev_vid << " WHERE id = " << subid;
std::string delQuery = delQuerySS.str();
delQuerySS.clear();
syslog (LOG_DEBUG, "Mysql Query: %s", delQuery.c_str());
stmt->execute(delQuery);
}
}
delete res;
delete subres;
delete stmt;
delete con;
}
catch(sql::SQLException &e){
syslog (LOG_ERR, "Mysql Exception: %s, ERRNO %i, MySQL State: %s", e.what(), e.getErrorCode(), std::string(e.getSQLState()).c_str());
exit(EXIT_FAILURE);
}
return true;
}
void signalHandler( int signum ){
syslog (LOG_NOTICE, "signal received (%i)", signum);
closelog();
exit(signum);
}
int main(void) {
/* Our process ID and Session ID */
pid_t pid, sid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
/* If we got a good PID, then
we can exit the parent process. */
if (pid > 0) {
std::ofstream pid_file;
pid_file.open("evmanager.pid", std::ofstream::trunc);
if( pid_file.is_open()){
pid_file << pid;
pid_file.close();
}
exit(EXIT_SUCCESS);
}
/* Change the file mode mask */
umask(0);
setlogmask (LOG_UPTO (LOG_DEBUG));
openlog ("dt_event_manager", LOG_PID, LOG_DAEMON);
syslog (LOG_NOTICE, "Program started by User %d", getuid ());
/* Create a new SID for the child process */
sid = setsid();
if (sid < 0) {
syslog (LOG_ERR, "SID Creation Failed");
exit(EXIT_FAILURE);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
syslog (LOG_ERR, "Failed while Changing directory to /");
exit(EXIT_FAILURE);
}
/* Read Initial Configuration */
std::ifstream conf_file;
std::string line;
config_t conf;
conf_file.open("/etc/zm/evmanager.conf");
if( conf_file.is_open()){
while( std::getline(conf_file, line) ){
if(line[0] == '#')continue;
std::istringstream is_line(line);
std::string key;
if( std::getline(is_line, key, '=') ){
std::string value;
if( std::getline(is_line, value) ){
trim(key);
trim(value);
if( key == "sql_host" )conf.sql_host = value; //mysql host
else if( key == "sql_user" )conf.sql_user = value; //mysql user
else if( key == "sql_pass" )conf.sql_pass = value; //mysql password
else if( key == "sql_db")conf.sql_db = value; //zoneminder database name
else if( key == "sql_ev_zm" )conf.sql_ev_zm = value; //zoneminder events table
else if( key == "sql_ev_vid" )conf.sql_ev_vid = value; //video events table
else if( key == "sql_ev_videxp" )conf.sql_ev_videxp = value; //Zoneminder videos expiration directory
else if( key == "sql_mon" )conf.sql_mon = value; //Zoneminder Monitors directory
else if( key == "dir_ev" )conf.dir_ev = value; //Zoneminder events directory
else if( key == "dir_vid" )conf.dir_vid = value; //Manager Videos directory
else if( key == "dir_ram" )conf.dir_ram = value; //Ramfs mount dir
else if( key == "ram_size" )conf.ram_size = value; //Ramfs size
else{
syslog (LOG_ERR, "Bad config readout");
exit(EXIT_FAILURE);
}
}
}
}
}
else{
syslog (LOG_ERR, "Failed to open configuration file");
exit(EXIT_FAILURE);
}
/* Close out the standard file descriptors */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* Daemon-specific initialization goes here */
/* The Big Loop */
signal(SIGINT, signalHandler);
syslog (LOG_INFO, "Daemon Started");
while (1) {
make_video();
delete_video();
sleep(10); /* wait 10 seconds */
}
exit(EXIT_SUCCESS);
}
This is a great question. I actually solve this issue a lot with students, as I was a C++ tutor.
As an example, let's say if this was your main:
//main.cpp:
#include <iostream>
#include "add.h" /// This comes in later :)
using namespace std;
int main()
{
cout << "2+3=" << add(2,3) << endl;
return 0;
}
You need to create a header file for the add function, like this:
//add.h
#ifndef ADD_H_INCLUDED
#define ADD_H_INCLUDED
int add(int a, int b);
#endif // ADD_H_INCLUDED
But then you need to actually define what the add function actually does:
//add.cpp
#include "add.h"
int add(int a, int b) {
return a + b;
}
Now you can choose to put multiple functions in a single header file, or each function can have its own header file, but it's your choice :) I hope this helps!
You have a number of options. The simplest is to create several files, perhaps like this:
shared_header.hpp
shared_functionality.cpp
prog_a.cpp
prog_b.cpp
Then program A is compiled with sources prog_a.cpp and shared_functionality.cpp, and program B is compiled with sources prog_b.cpp and shared_functionality.cpp. All source files include the header, and prog_a.cpp and prog_b.cpp define their own main function each.

FileStorage --> mysql

sorry for my english :) Trying to improve my application I want to copy vectors directly into mysql without string, is it even possible?
FileStorage fs( ".yml", FileStorage::WRITE + FileStorage::MEMORY );
Ptr < FaceRecognizer > model0 = createmyfisherRecognizer();
model0->train( images, labels );
model0->save( fs );
void myfisher::save( FileStorage & fs ) const {
static char * host = "localhost"; /* host serwera MySQL */
static char * user = "root"; /* nazwa loginu by polaczyc sie do serwera */
static char * password = ""; /* haslo */
static char * sql_db = "fisher"; /* nazwa bazy */
static unsigned int sql_port = NULL; /* port na jakim odbiera/wysyla serwer mysql */
static char * opt_socket = NULL; /* socket name */
static unsigned int sql_flags = 0;
static MYSQL * sock; /* Wskaznik do polaczenia do MySQL */
sock = mysql_init( NULL );
if( mysql_real_connect( sock, host, user, password, sql_db, sql_port, opt_socket, sql_flags ) )
cout << "Poprawnie polaczyles sie z baza danych" << endl;
else
cout << "Blad w polaczeniu z baza danych" << endl;
fs << "num_components" << _num_components;
fs << "mean" << _mean;
fs << "eigenvalues" << _eigenvalues;
writeFileNodeList( fs, "projections", _projections );
fs << "labels" << _labels;
string buf = fs.releaseAndGetString();
fs.release();
string zapytanie = "insert into baa values (\"" + buf + "\")";
if( !mysql_query( sock, zapytanie.c_str() ) )
cout << "Poprawnie dodano" << endl;
else
cout << "Blad przy zapisywaniu" << endl;
}
Here I posted the code in question. At the moment it works in this way:
everything is saved into fs (FileStorage)
data in fs is converted to string
fs sent to database
It is known that the program would run much faster if it would be directly copied without the string to the database.
i think you can use snprintf for this, unfortunatelly since there are variable types missing i cant give you exact example.
char string[100];
snprintf(string, 100, "printe text %s,\n and integer %i", "printf", 100); //almost same as printf