使用mysql_udf與curl庫完成http_post通訊模組示例

piny發表於2021-09-09

使用mysql_udf與curl庫完成http_post通訊模組(mysql_udf,multi_curl,http,post)

這個模組其目前主要用於xoyo江湖的sns與kingsoft_xoyo自主研發的TCSQL資料庫做資料同步,當有feed插入sns資料庫,使用觸 發器呼叫該模組,向tcsql資料庫傳送同步資料。也可以使用該模組與其它使用socket介面的資料庫或程式做轉發與同步。
http_post模組主要使用mysql_udf介面,與curl庫兩部分技術。
mysql_udf是mysql為c語言提供的一個介面,透過這個介面,使用者可以自定義mysql的函式,透過呼叫這些mysql函式,呼叫相應的c語言 模組來執行特定功能,實現mysql資料與外部應用的互動。curl庫是一個比較常用的應用層網路協議庫,主要用到的是其中的curl_multi非同步通 信api,用來進行網路傳輸。
首先參考mysql官方提供的udf_example.c檔案,建立3個主要的介面函式,分別是初始化函式,執行函式與解構函式。


複製程式碼 程式碼如下:
//args是sql語句傳回的引數,message是返回出錯資訊使用這些都是規定好的。
my_bool http_post_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
//主函式體
longlong http_post(UDF_INIT *initid, UDF_ARGS *args, char *is_null,char *error);
//解構函式體
void http_post_deinit(UDF_INIT *initid);
//args是sql語句傳回的引數,message是返回出錯資訊,使用這些都是規定好的。
//初始化函式體 my_bool http_post_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
//主函式體 longlong http_post(UDF_INIT *initid, UDF_ARGS *args, char *is_null,char *error);
//解構函式體 void http_post_deinit(UDF_INIT *initid);


在mysql_udf介面中,主函式體中是不允許使用new或malloc動態分配記憶體,所以如果需要申請記憶體空間,必須用xxxx_init()函式申 請並將申請的地址賦給initid->ptr指標,然後在主函式體中使用,並在xxxx_deinit解構函式體中釋放。另外對於 mysql_udf介面的呼叫好像當併發量超過一定程度,如果是使用動態分配記憶體,會出現double free的錯誤,為了避免這個錯誤,所以在我的程式裡使用靜態空間與動態申請空間相結合的方式,這樣如果資料較小,併發量較大,不會出現double free錯誤。對於靜態申請空間,最大約在160000~170000byte左右,我這裡使用的160000,當mysql傳送的資料大於這個數的時 候,才動態申請記憶體。初始化函式體如下:


複製程式碼 程式碼如下:
my_bool http_post_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
    {
      if (args->arg_count != 2)
      {
        strcpy(message,"Wrong arguments to http_post; ");
        return 1;
      } 


      if(args->arg_count == 2 && args->args[1]!=NULL)
      {
            int flexibleLength = strlen(args->args[1]); 

        if(flexibleLength > 160000)
        {
            int allocLength = 200 + flexibleLength;
            if (!(initid->ptr=(char*) malloc(allocLength) ) )
            {
                    strcpy(message,"Couldn't allocate memory in http_post_init");
                    return 1;
            }
            return 0;
        }
        else
        {
            initid->ptr=NULL;
        } 

      }
       return 0; 

    }


其中http_post_init需要返回my_bool型。這個函式目的是給使用者提供一個方式,檢驗由mysql引數傳進來的資料是否正確,如果正確則 返回0,則mysql會自動呼叫定義的主函式,如果返回1,則mysql列印message資訊退出,不會呼叫主函式。所以在設定返回值的時候一定注意。


主函式如下:


複製程式碼 程式碼如下:
longlong http_post( UDF_INIT *initid, UDF_ARGS *args,
                char *is_null __attribute__((unused)),
                char *error __attribute__((unused)))
{
    char* sendBuffer=NULL;
    CURL *curl;
    CURLM *multi_handle;
    int still_running;
    int times=0;//try times if select false
        int TRY_TIMES=25;
    struct timeval timeout;//set a suitable timeout to play around with
    timeout.tv_sec = 0;
    timeout.tv_usec = 100000; 


    char sendArray[160000] = "

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3034/viewspace-2804376/,如需轉載,請註明出處,否則將追究法律責任。

相關文章