Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

C++ Thread worker and mysql connections

Ostatnio zmodyfikowano 2017-10-17 15:43
Autor Wiadomość
Breakermind
Temat założony przez niniejszego użytkownika
C++ Thread worker and mysql connections
» 2017-10-11 13:42:49
Dzień dobry, jaka może być przyczyna zatrzymania się tredów w programie?

Mam trzy tredy odpalane na początku programu nastepnie mam petlę while wyświetlającą tekst (while(1){cout << "main text";}).
Po jakimś czasie (kilku minut) pętle z tread workerów przestają działać,
gdzie szukać przyczyny (w tredworkerach wszystko jest w petli while(1){ cout << "tekst tread"; } i nie ma breaków).
Dodałem dodatkowo fork() w tred worker lecz nie poprawiło to sytuacji.

Pozdrawiam
P-165645
Breakermind
Temat założony przez niniejszego użytkownika
» 2017-10-11 20:29:15
Witam, wyskakuje jakiś error:

*** Error in `./start': free(): invalid pointer: 0x00007f32e1fb4eb8 ***

Kompiluję:
g++ -o start main.cpp -std=c++11 -pthread -L/usr/include/mysql -lmysqlclient -I/usr/include/mysql

Gdzie coś pomieszałem?

C/C++
// thread example
// g++ main.cpp  -std=c++11 -pthread
// mysql
// apt-get install libmysql++
// apt-get install libmysql++-dev
// compile
// g++ -o start main.cpp -std=c++11 -pthread -L/usr/include/mysql -lmysqlclient -I/usr/include/mysql
//
#include <iostream>       // std::cout
#include <thread>         // std::thread
// sleep
#include <unistd.h>
// mysql
#include <mysql.h>
// vector
#include <vector>

using namespace std;

vector < vector < string >> select() {
    MYSQL * connect, mysql;
    MYSQL_RES * result;
    int query_state;
    // init mysql
    connect = mysql_init( NULL );
    if( !connect ) {
        cout << "MySQL Initialization failed";
        //return 1;
    }
    connect = mysql_real_connect( connect, "localhost", "root", "toor", "SMTP", 3306, NULL, 0 );
    if( connect ) {
        cout << "connection Succeeded\n";
    } else {
        cout << "connection failed";
    }
   
    // select
    MYSQL_RES * res_set;
    MYSQL_ROW row;
    MYSQL_FIELD * field;
    mysql_query( connect, "select id,email_to,resendtime,send from messages;" );
    unsigned int i = 0;
    res_set = mysql_store_result( connect );
    unsigned int numrows = mysql_num_rows( res_set );
    int num_fields = mysql_num_fields( res_set );
    try {
        while((( row = mysql_fetch_row( res_set ) ) != NULL ) ) {
            cout << "Row " << row[ i ] << " " << row[ i + 1 ] << " " << row[ i + 2 ] << endl;
        }
    } catch( std::exception & e ) {
        cout << "Error pointer " << endl;
    }
    mysql_free_result( res_set );
    mysql_close( connect );
}

void foo()
{
    while( 1 ) {
        cout << "Hello from thread" << endl;
        sleep( 1 );
        // select from thread !!!!!!!
        select();
    }
}

void bar( int x )
{
    while( 1 ) {
        cout << "Hello from thread " << x << endl;
        sleep( 1 );
    }
}

int main()
{
    std::thread t1( foo ); // spawn new thread that calls foo()
    std::thread t2( bar, 0 ); // spawn new thread that calls bar(0)
   
    std::cout << "main, foo and bar now execute concurrently...\n" << endl;
   
    // synchronize threads:
    //t1.join();                // pauses until first finishes
    //t2.join();               // pauses until second finishes
   
    while( 1 ) {
        std::cout << "Main thread looooop \n";
        sleep( 1 );
        // select from main
        //    select();
    }
   
    return 0;
}

Chodzi mi o pobieranie danych z tabelki z bazy danych w osobnym threadzie?

P-165655
Monika90
» 2017-10-11 20:33:57
W funkcji select zapomniałeś o instrukcji return.
P-165656
Breakermind
Temat założony przez niniejszego użytkownika
» 2017-10-11 20:42:29
Dzięki! Hehehehe ale banał :). A już miałem pół serwera wyrzucać :D.

Gdzie jakiś dobre ide do c++ na linuxa co by mi te wszystkie "debilizmy" wyświetlało i żebym nie musiał jak "moron" z konsoli szukać (jakiś movie najlepiej :) z youtu.be)?

Naprawiona część:
C/C++
vector < vector < string >> select( std::string txt ) {
    MYSQL * connect, mysql;
    MYSQL_RES * result;
    int query_state;
    // init mysql
    connect = mysql_init( NULL );
    if( !connect ) {
        cout << "MySQL Initialization failed";
        //return 1;
    }
    connect = mysql_real_connect( connect, "localhost", "root", "toor", "BreakermindSMTP", 3306, NULL, 0 );
    if( connect ) {
        cout << "connection Succeeded\n";
    } else {
        cout << "connection failed";
    }
   
    // vector
    vector < vector < string >> messages;
   
   
    // select
    MYSQL_RES * res_set;
    MYSQL_ROW row;
    MYSQL_FIELD * field;
    mysql_query( connect, "select id,email_to,resendtime,send from messages;" );
    unsigned int i = 0;
    res_set = mysql_store_result( connect );
    unsigned int numrows = mysql_num_rows( res_set );
    int num_fields = mysql_num_fields( res_set );
    try {
        while((( row = mysql_fetch_row( res_set ) ) != NULL ) ) {
            cout << txt << " " << row[ i ] << " " << row[ i + 1 ] << " " << row[ i + 2 ] << endl;
            // add single row to vector string
            vector < string > msg;
            msg.push_back( row[ i ] );
            msg.push_back( row[ i + 1 ] );
            msg.push_back( row[ i + 2 ] );
            // add to messages
            messages.push_back( msg );
        }
    } catch( std::exception & e ) {
        cout << "Error pointer " << endl;
    }
    mysql_free_result( res_set );
    mysql_close( connect );
    // return messages
    return messages;
}
P-165658
mokrowski
» 2017-10-11 21:16:28
To nie jest kwestia IDE. Dodaj do wywołania kompilatora:

-Wall -Wextra -pedantic

.. i w dowolnym IDE takie błędy będziesz miał zgłaszane.
P-165660
Breakermind
Temat założony przez niniejszego użytkownika
» 2017-10-12 09:40:33
Dzięki, działał całą noc ten programik z tredami i się nie wysypał (o dziwo, dodam resztę i zobaczę co dalej).
Na Qt mi się wyświetlają błędy w netbean i eclipse zresztą też ;).
Trochę tylko bez sensu że warningi wysypują program po kompilacji (Segmentation fault).
Pozdrawiam
P-165663
Breakermind
Temat założony przez niniejszego użytkownika
» 2017-10-12 11:20:44
Jak pobrać z osobnych tredów z tabeli(baza danych) rekordy nie powtarzając ich tzn. jeżeli pierwszy thread odczytał rekord(1) i go zaktualizował to inny tread powinien już pobrać rekord następny i dokonać aktualizacji)?

Używam obecnie transakcji lecz niestety tredy pobierają czasami ten sam rekord, dlaczego się tak dzieje
(Ustawiony mam silnik InnoDB na bazie danych mariadb)?

A kiedyś czytałem że InnoDB blokuje poszczególne rekordy (linje) tabeli, czyli nie powinno się tak dziać.

Można gdzieś pozmieniać priorytety wykonywanych zapytań lub ustawić kolejkowanie zapytań na bazie danych, jeżeli tak to gdzie i jak to zrobić?

Klasa wygląda tak (może gdzieś coś poprawić trzeba):
plik db.cpp
C/C++
#include "db.h"

DB::DB() { }

bool DB::Connect( string host = "localhost", string user = "root", string pass = "toor", string db = "BreakermindSMTP", int port = 3306 ) {
    // init mysql
    connect = mysql_init( NULL );
    if( !connect ) {
        cout << "MySQL Initialization failed";
        return 0;
    }
    connect = mysql_real_connect( connect, host.c_str(), user.c_str(), pass.c_str(), db.c_str(), port, NULL, 0 );
    if( connect ) {
        cout << "Connection Succeeded\n";
        return 1;
    } else {
        cout << "Connection failed";
        return 0;
    }
}

vector < vector < string >> DB::Select( string txt = "Row " ) {
    // vectors
    vector < vector < string >> messages;
    // select
    MYSQL_RES * res_set;
    MYSQL_ROW row;
    mysql_autocommit( connect, false );
    //mysql_query (connect,"BEGIN;");
    // lock tables
    mysql_query( connect, "LOCK TABLES messages WRITE;" );
    unsigned long trID =( unsigned long ) mysql_thread_id( connect );
    cout << "MySQL Thread ID " << trID << endl;
    int err = mysql_query( connect, "SELECT id,email_to,send,resendtime,email_subject FROM messages WHERE send > 0 AND send < 100 AND resendtime < NOW() LIMIT 2;" );
    if( err ) {
        fprintf( stderr, "%s\n", mysql_error( connect ) );
        // mysql_close(con);
        // exit(1);
    }
    unsigned int i = 0;
    res_set = mysql_store_result( connect );
    // unsigned int numrows = mysql_num_rows(res_set);
    // int num_fields = mysql_num_fields(res_set);
    try {
        while((( row = mysql_fetch_row( res_set ) ) != NULL ) ) {
            cout << txt << " " << row[ i ] << " " << row[ i + 1 ] << " " << row[ i + 2 ] << " " << row[ i + 3 ] << " " << row[ i + 4 ] << endl;
           
            char query[ 500 ];
            sprintf( query, "UPDATE messages SET send=send+1,resendtime=DATE_ADD(NOW(), INTERVAL 5 MINUTE) WHERE id=%i;", atoi( row[ i ] ) );
            cout << "Query: " << query << endl;
            int err = mysql_query( connect, query );
            if( err ) {
                fprintf( stderr, "%s\n", mysql_error( connect ) );
                // mysql_close(con);
                // exit(1);
            }
            // add single row to vector string
            vector < string > msg;
            msg.push_back( row[ i ] );
            msg.push_back( row[ i + 1 ] );
            msg.push_back( row[ i + 2 ] );
            // add to messages
            messages.push_back( msg );
        }
    } catch( std::exception & e ) {
        cout << "Error pointer " << endl;
    }
    // lock tables end
    mysql_query( connect, "UNLOCK TABLES;" );
    //mysql_query (connect,"COMMIT;");
    mysql_free_result( res_set );
    mysql_close( connect );
    // return messages
    return messages;
}

plik db.h
C/C++
#ifndef DB_H
#define DB_H

// #include <stdlib.h>
#include <iostream>
#include <vector>
#include <string>
// mysql
#include "mysql.h"
// #include "mysql_driver.h"
// #include "mysql_error.h"

using namespace std;

class DB
{
public:
    MYSQL * connect;
    DB();
    bool Connect( string host, string user, string pass, string db, int port );
    vector < vector < string >> Select( string txt );
};

#endif

UPDATE: Doczytałem i po testowałem i dodałem:

C/C++
mysql_query( connect, "LOCK TABLES messages WRITE;" );
....
mysql_query( connect, "UNLOCK TABLES;" );

Zamiast transakcji i działa.
P-165666
Breakermind
Temat założony przez niniejszego użytkownika
» 2017-10-12 11:34:45
Jak przechwycić z c++ mysql error?

Np. gdy ustawię na bazie danych za małą liczbę możliwych połączeń to powyższy program
się zatrzymuje z błędem (Segmentation fault)?

C/C++
int err = mysql_query( connect, "SELECT id,email_to,send,resendtime,email_subject FROM messages WHERE send > 0 AND send < 100 AND resendtime < NOW() LIMIT 1;" );
if( err ) {
    fprintf( stderr, "%s\n", mysql_error( connect ) );
    // mysql_close(con);
    // exit(1);
}

Lub jak zmusić program do ciągłego wykonywania się i nie zwracania uwagi na błędy?

C/C++
while( 1 ) {
    try {
        ....
       
    } catch( std::exception & e ) {
        cout << "# ERR: SQLException in " << __FILE__;
        cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
        cout << "# ERR: " << e.what();
    }
}
P-165667
« 1 » 2 3
  Strona 1 z 3 Następna strona