美文网首页
MySQL C 客户端例子(使用Siren)

MySQL C 客户端例子(使用Siren)

作者: splendor2000 | 来源:发表于2017-02-27 18:06 被阅读0次

    启动MySQL服务器

    docker run --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql
    

    初始化数据库

    docker exec -it mysql mysql -uroot -p123456
    
    CREATE DATABASE test CHARACTER SET utf8 COLLATE utf8_general_ci;
    use test
    
    CREATE TABLE pairs (
        k VARCHAR(20) NOT NULL,
        v VARCHAR(20) NOT NULL
    ) ENGINE = InnoDB;
    
    INSERT INTO pairs (k, v) VALUES ("foo", "bar");
    quit
    

    客户端代码(mysql_client.cc)

    #include <cstdio>
    #include <exception>
    #include <string>
    #include <vector>
    
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netdb.h>
    #include <sys/poll.h>
    
    #include <my_global.h>
    #include <mysql.h>
    
    #include <siren/async.h>
    #include <siren/c_library.h>
    #include <siren/elf_hook.h>
    #include <siren/loop.h>
    #include <siren/scope_guard.h>
    #include <siren/utility.h>
    
    
    #define MYSQLCLIENT_DL_FILE_NAME "libmysqlclient.so"
    
    
    extern siren::Loop *siren_loop;
    extern siren::Async *siren_async;
    
    namespace {
    
    auto elf_hooks = std::make_tuple(
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "open", siren_open),
        siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "read", maybe_siren_read),
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "write", maybe_siren_write),
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "readv", maybe_siren_readv),
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "writev", maybe_siren_writev),
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "lseek", siren_lseek),
        siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "close", maybe_siren_close),
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "usleep", siren_usleep),
        siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "socket", siren_socket),
        siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "getsockopt", siren_getsockopt),
        siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "setsockopt", siren_setsockopt),
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "accept", siren_accept),
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "accept4", siren_accept4),
        siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "connect", siren_connect),
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "recv", siren_recv),
        siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "send", siren_send),
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "recvfrom", siren_recvfrom),
        // siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "sendto", siren_sendto),
        siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "getaddrinfo", siren_getaddrinfo),
        siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "getnameinfo", siren_getnameinfo),
        siren::MakeELFHook(MYSQLCLIENT_DL_FILE_NAME, "poll", siren_poll)
    );
    
    
    class MySQLError
      : public std::exception
    {
    public:
        explicit MySQLError(MYSQL *mysql) {
            description_ = "MySQLError: ";
            description_ += mysql_error(mysql);
        }
    
        const char *what() const noexcept override {
            return description_.c_str();
        }
    
    private:
        std::string description_;
    };
    
    }
    
    
    int
    real_main(int fiberID)
    {
        char buf[1024];
        MYSQL mysql;
        mysql_init(&mysql);
    
        if (mysql_real_connect(&mysql, "192.168.11.101", "root", "123456", "test", 0, nullptr, 0)
            == nullptr) {
            throw MySQLError(&mysql);
        }
    
        int result = 1;
    
        auto scopeGuard = siren::MakeScopeGuard([&] () -> void {
            // 事务支持
            // if (result == 0) {
            //     mysql_commit(&mysql);
            // } else {
            //     mysql_rollback(&mysql);
            // }
    
            mysql_close(&mysql);
        });
    
        // 事务支持
        // if (mysql_autocommit(&mysql, 0)) {
        //     throw MySQLError(&mysql);
        // }
    
        auto query = [&] (const char *tag) -> void {
            // 查
            if (mysql_query(&mysql, "SELECT * FROM pairs")) {
                throw MySQLError(&mysql);
            }
    
            MYSQL_RES *result = mysql_store_result(&mysql);
    
            if (result == nullptr) {
                throw MySQLError(&mysql);
            }
    
            std::printf("[%d] %s: ", fiberID, tag);
            unsigned int numberOfFields = mysql_num_fields(result);
    
            for (;;) {
                MYSQL_ROW row = mysql_fetch_row(result);
    
                if (row == nullptr) {
                    break;
                }
    
                for (unsigned int i = 0; i < numberOfFields; ++i) {
                    std::printf("%s ", row[i]);
                }
    
                std::printf("| ");
            }
    
            std::putchar('\n');
        };
    
        // 增
        std::snprintf(buf, sizeof(buf), "INSERT INTO pairs (k, v) VALUES ('hello', 'world%d')", fiberID);
        if (mysql_query(&mysql, buf)) {
            throw MySQLError(&mysql);
        }
    
        query("AFTER INSERT");
    
        // 改
        std::snprintf(buf, sizeof(buf), "UPDATE pairs SET v = 'kitty%d' WHERE k = 'hello'", fiberID);
        if (mysql_query(&mysql, buf)) {
            throw MySQLError(&mysql);
        }
    
        query("AFTER UPDATE");
    
        // 删
        std::snprintf(buf, sizeof(buf), "DELETE FROM pairs WHERE k = 'hello'");
        if (mysql_query(&mysql, buf)) {
            throw MySQLError(&mysql);
        }
    
        query("AFTER DELETE");
        result = 0;
        return result;
    }
    
    
    int
    main()
    {
        siren::IterateTuple(elf_hooks, [] (auto &&elf_hook) { elf_hook.toggle(); });
        siren::Loop loop(16 * 1024);
        siren::Async async(&loop);
        siren_loop = &loop;
        siren_async = &async;
        int result;
    
        for (int i = 0; i < 10; ++i) {
            loop.createFiber([&, i(i)] () {
                result = real_main(i);
            });
        }
    
        try {
            loop.run();
        } catch (const std::exception &exception) {
            std::fprintf(stderr, "%s\n", exception.what());
            return 1;
        }
    
        return result;
    }
    

    编译运行

    g++ -std=c++14 -DUSE_VALGRIND mysql_client.cc -lsiren -pthread -lmysqlclient -ldl && ./a.out
    

    相关文章

      网友评论

          本文标题:MySQL C 客户端例子(使用Siren)

          本文链接:https://www.haomeiwen.com/subject/fmzzwttx.html