Creating an Apache module

Discussion in 'C Programming' started by mydancake@googlemail.com, Feb 6, 2009.

  1. Guest

    I need to create an apache module which simply connects to a mysql
    database, does some processing and returns some data to the users
    browser.

    I bet your wondering why I want to use an apache module rather than
    PHP or Perl. I did some tests and PHP can handle around 30-40 requests
    per second where as an apache module

    it can handle 200+.

    The code below is just a simple and crude test. I've had some some
    trouble with the mysql part, for example, if I try to use
    mysql_real_query I get undefined symbol:

    mysql_real_query.

    Also what would be the best way to handle connections to a mysql
    database and where should I connect and close connections. Obviously I
    don't want to connect on each request

    received. Any example code would be appreciated.

    Please be gentle, I'm fairly new to C.

    #include <httpd.h>
    #include <http_protocol.h>
    #include <http_config.h>
    #include <mysql.h>

    static int mytest_handler(request_rec* r)
    {
    if (!r->handler || strcmp(r->handler, "mytest"))
    return DECLINED;

    if (r->method_number != M_GET)
    return HTTP_METHOD_NOT_ALLOWED;

    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;

    char *server = "localhost";
    char *user = "root";
    char *password = "";
    char *database = "mydatabase";

    if (!mysql_real_connect(conn, server, user, password, database, 0,
    NULL, 0)) {
    fprintf(stderr, "%s\n", mysql_error(conn));
    }

    ap_set_content_type(r, "text/html;charset=ascii");

    /* send SQL query */
    if (mysql_real_query(conn, "SELECT * FROM mytable LIMIT 0, 10", 39))
    {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(0);
    }

    res = mysql_use_result(conn);

    while ((row = mysql_fetch_row(res)) != NULL) {
    ap_rputs("Got a row", r);
    }

    /* Release memory used to store results and close connection */
    mysql_free_result(res);
    mysql_close(conn);

    return OK;
    }

    static void register_hooks(apr_pool_t* pool)
    {
    ap_hook_handler(mytest_handler, NULL, NULL, APR_HOOK_MIDDLE);
    }

    module AP_MODULE_DECLARE_DATA mytest_module = {
    STANDARD20_MODULE_STUFF,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    register_hooks
    };
     
    , Feb 6, 2009
    #1
    1. Advertising

  2. Guest Guest

    wrote:
    > I need to create an apache module which simply connects to a mysql
    > database, does some processing and returns some data to the users
    > browser.
    >
    > I bet your wondering why I want to use an apache module rather than
    > PHP or Perl. I did some tests and PHP can handle around 30-40 requests
    > per second where as an apache module
    >
    > it can handle 200+.
    >
    > The code below is just a simple and crude test. I've had some some
    > trouble with the mysql part, for example, if I try to use
    > mysql_real_query I get undefined symbol:
    >
    > mysql_real_query.
    >
    > Also what would be the best way to handle connections to a mysql
    > database and where should I connect and close connections. Obviously I
    > don't want to connect on each request
    >
    > received. Any example code would be appreciated.
    >
    > Please be gentle, I'm fairly new to C.
    >


    I think this is mostly a question for Apache or MySQL newsgroups.
    Anyway, have you tried compiling your source linking libmysqlclient? On
    gcc you should use -lmysqlclient option, on other systems or compilers
    you may have to manually link libmysqlclient.a, libmysqlclient.so,
    libmysqlclient.dll or something like that.

    --
    -----BEGIN GEEK CODE BLOCK-----
    GCS/CM/CC/E/IT/LS/M d-(--) C++++$ UBL++++$ P++++ L+++++$ E--- W+++ w--
    PS+++ PE-- Y++ PGP+++ R++ tv-- b++>+++ D+ G>+++ e++>+++++ h* r++ z+++
    ------END GEEK CODE BLOCK------
     
    Guest, Feb 7, 2009
    #2
    1. Advertising

  3. On Fri, 6 Feb 2009 15:37:18 -0800 (PST),
    wrote:

    >I need to create an apache module which simply connects to a mysql
    >database, does some processing and returns some data to the users
    >browser.
    >
    >I bet your wondering why I want to use an apache module rather than
    >PHP or Perl. I did some tests and PHP can handle around 30-40 requests
    >per second where as an apache module
    >
    > it can handle 200+.
    >
    >The code below is just a simple and crude test. I've had some some
    >trouble with the mysql part, for example, if I try to use
    >mysql_real_query I get undefined symbol:
    >
    >mysql_real_query.
    >
    >Also what would be the best way to handle connections to a mysql
    >database and where should I connect and close connections. Obviously I
    >don't want to connect on each request
    >
    >received. Any example code would be appreciated.
    >
    >Please be gentle, I'm fairly new to C.


    Your sql or apache questions will get better responses in a newsgroup
    that deals with those products. However, you have some C problems
    also which this group can help with.

    >
    >#include <httpd.h>
    >#include <http_protocol.h>
    >#include <http_config.h>
    >#include <mysql.h>
    >
    >static int mytest_handler(request_rec* r)
    >{
    > if (!r->handler || strcmp(r->handler, "mytest"))
    > return DECLINED;
    >
    > if (r->method_number != M_GET)
    > return HTTP_METHOD_NOT_ALLOWED;
    >
    > MYSQL *conn;


    Unless you have C99, you need your declarations to appear before your
    statements.

    > MYSQL_RES *res;
    > MYSQL_ROW row;
    >
    > char *server = "localhost";
    > char *user = "root";
    > char *password = "";
    > char *database = "mydatabase";
    >
    > if (!mysql_real_connect(conn, server, user, password, database, 0,
    >NULL, 0)) {


    conn was never assigned a value. This statement invokes undefined
    behavior by trying to pass that (non-existent) value to the function.

    > fprintf(stderr, "%s\n", mysql_error(conn));


    You need to include stdio.h to use fprintf.

    > }
    >
    > ap_set_content_type(r, "text/html;charset=ascii");
    >
    > /* send SQL query */
    > if (mysql_real_query(conn, "SELECT * FROM mytable LIMIT 0, 10", 39))
    >{
    > fprintf(stderr, "%s\n", mysql_error(conn));
    > exit(0);
    > }
    >
    > res = mysql_use_result(conn);
    >
    > while ((row = mysql_fetch_row(res)) != NULL) {


    Is row (type MYSQL_ROW) really a pointer. If not, use 0 instead of
    NULL.

    > ap_rputs("Got a row", r);
    > }
    >
    > /* Release memory used to store results and close connection */
    > mysql_free_result(res);
    > mysql_close(conn);
    >
    > return OK;
    >}
    >
    >static void register_hooks(apr_pool_t* pool)
    >{
    > ap_hook_handler(mytest_handler, NULL, NULL, APR_HOOK_MIDDLE);


    Shouldn't this function use the parameter in some way?

    >}
    >
    >module AP_MODULE_DECLARE_DATA mytest_module = {
    > STANDARD20_MODULE_STUFF,
    > NULL,
    > NULL,
    > NULL,
    > NULL,
    > NULL,
    > register_hooks
    >};


    Is there a reason this file scope object appears at the end of your
    source?

    --
    Remove del for email
     
    Barry Schwarz, Feb 7, 2009
    #3
  4. On 7 Feb 2009 at 1:30, Barry Schwarz wrote:
    > On Fri, 6 Feb 2009 15:37:18 -0800 (PST),
    > wrote:
    >> if (!mysql_real_connect(conn, server, user, password, database, 0,
    >>NULL, 0)) {

    >
    > conn was never assigned a value. This statement invokes undefined
    > behavior by trying to pass that (non-existent) value to the function.


    As the OP described himself as "fairly new to C", it's probably worth
    unpacking that rather cryptic statement written in standardese, as this
    is a very common setup in C APIs.

    Very frequently, libraries need to work with compound data structures -
    what in other languages would be classes. Of course, C doesn't have
    constructors, destructors, methods and the rest, so a very common way of
    "doing OO programming in C" is for the library to deal in struct
    pointers.

    The relevant struct, let's say struct foo, will be defined in the header
    file you #include to use the library. Then in your code, you'll create a
    struct foo variable, say myfoo (statically, on the stack, or got from
    malloc() at your choice). The library then provides a function with a
    name like foo_init(), which is effectively the constructor. You call it
    like

    foo_init(&myfoo); /* maybe you need to pass some parameters too */

    The library then fills in the fields in the struct pointed to by myfoo,
    allocates any resources it needs, and generally does everything you'd
    expect a class ctor to do.

    And from then on, you can pass the address of myfoo to the other library
    functions to manipulate it as you want:

    foo_work_magic(&myfoo, 42); /* morally, this is myfoo->work_magic(42); */
    foo_print_answer(&myfoo, stdout);
    etc.

    Finally, you call a function like foo_clear(), which is the destructor
    that frees any memory that foo_init() allocated, etc.

    It's the fact that your program clearly violates this paradigm by
    defining a pointer to MYSQL directly, rather than having an actual MYSQL
    and taking its address, that rang alarm bells for Barry.

    >>static void register_hooks(apr_pool_t* pool)
    >>{
    >> ap_hook_handler(mytest_handler, NULL, NULL, APR_HOOK_MIDDLE);

    >
    > Shouldn't this function use the parameter in some way?


    I don't know about this particular function, but it's very common in
    general for event handling functions to ignore some of their parameters,
    so it's probably OK.

    I agree with the suggestion that your direct problem (symbol not found)
    is likely to be a linking problem caused by not linking with the
    appropriate mysql library.
     
    Antoninus Twink, Feb 7, 2009
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page