I'm developing a simple assignment using Apache Thrift and the C++ POCO library. The assignment requires me to make a benchmark by creating multiple concurrent threads make the same request to the Thrift TThreadPoolServer.

This is my client-side code, where I creates 10 concurrent threads, all of them make the same GET request (request info from only one user D) to the server:

// define a MyWorker class which inherits Runnable
class MyWorker : public Runnable {
    public:

    MyWorker(int k = -1) : Runnable(), n(k) {
    }

    void run() {
        // create connection
        boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
        boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
        boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
        APIsClient client(protocol);
        try {
            transport->open();
            int res = -1;
            // make the request
            res = client.get("D"); 
            printf("Thread %d, res = %d \n", n, res);
            transport->close();
        } catch (TException te) {
            cout << te.what() << endl;
        }
    }
private:
    int n;
};

void handleBenchmarkTest(const std::string& name, const std::string& value) {
        //TODO!
        const int N = 10;
        MyWorker w[N];
        for (int i = 0; i < N; i++) w[i] = MyWorker(i);
        Thread t[N];
        for (int i = 0; i < N; i++) t[i].start(w[i]);
        for (int i = 0; i < N; i++) t[i].join(); // wait for all threads to end

        cout << endl << "Threads joined" << endl;
    }

I implemented my server using TThreadPoolServer. This is the the handler function when the server receive a GET request:

   // this function make use of POCO::Data   
int getRequest(const std::string& _username) {
            int res = -1;
            Statement select(*mySQLsession);
            std::string match("'" + _username + "'");
            select << "SELECT counter FROM view_count_info WHERE username = " + match + " LIMIT 1;", into(res);
            select.execute();
            return res;
        }

Above are all of my codes. When I run the client-side benchmark app, this is what returned:

MySQL // from the try-catch block above
MySQL // from the try-catch block above
Thread 2, res = -1 // expected result
MySQL // from the try-catch block above
Thrift: Fri Jun 26 15:54:05 2015 TSocket::read() recv() <Host: localhost Port: 9090>Connection reset by peer
No more data to read.
THRIFT_ECONNRESET
No more data to read.
No more data to read.
Thrift: Fri Jun 26 15:54:05 2015 TSocket::read() recv() <Host: localhost Port: 9090>Connection reset by peer
THRIFT_ECONNRESET
Thrift: Fri Jun 26 15:54:05 2015 TSocket::read() recv() <Host: localhost Port: 9090>Connection reset by peer
THRIFT_ECONNRESET

Threads joined

In the server, the result is:

2015-06-26 08:54:00 : > Server is running
2015-06-26 08:54:05 : handle GET request
D
2015-06-26 08:54:05 : handle GET request
D
2015-06-26 08:54:05 : handle GET request
D
-1
2015-06-26 08:54:05 : handle GET request
2015-06-26 08:54:05 : handle GET request
D
2015-06-26 08:54:05 : handle GET request
D
2015-06-26 08:54:05 : handle GET request
D
D

RUN FINISHED; Segmentation fault; core dumped; real time: 5s; user: 0ms; system: 0ms

I don't know why this happened. One more thing, when I try to change to not use MySQL request in the server side (instead I just return a random integer for each request), the app runs well without any errors or warning. So I guess the problem here is with the MySQL database. It does work if I only make 1 request at a time, but something goes wrong when there are multiple, concurrent GET requests are made.

1

There are 1 answers

0
sonlexqt On BEST ANSWER

Thanks to @JensG, I found out that the problem here is because I used a global variable mySQLsession to handle all the MySQL database requests, which causes threads conflict. Thanks you all again !