solr-connection.c revision 53ec1ff2231d477db3103c51987fa9cb6033bc16
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen/* curl: 7.16.0 curl_multi_timeout */
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen const unsigned char *data;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainencurl_output_func(void *data, size_t element_size, size_t nmemb, void *context)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen /* @UNSAFE */
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic int solr_xml_parse(struct solr_connection *conn,
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen if (XML_Parse(conn->xml_parser, data, size, done))
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen line = XML_GetCurrentLineNumber(conn->xml_parser);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_error("fts_solr: Invalid XML input at line %d: %s",
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainencurl_input_func(void *data, size_t element_size, size_t nmemb, void *context)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen (void)solr_xml_parse(conn, data, size, FALSE);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainencurl_header_func(void *data, size_t element_size, size_t nmemb, void *context)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen const unsigned char *p;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen if (p[i] == ' ') {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen conn->http_failure = i_strndup(p + i, size - i);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenstruct solr_connection *solr_connection_init(const char *url, bool debug)
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen if (conn->curl == NULL || conn->curlm == NULL) {
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen "fts_solr: Failed to allocate curl");
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen /* set global curl options */
0a0cd45a633112a2ae6aad801c1e6afe53ab95deTimo Sirainen curl_easy_setopt(conn->curl, CURLOPT_ERRORBUFFER, conn->curl_errorbuf);
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_VERBOSE, 1L);
2524ef7b34965a1b1895d6140fd8296bf57c78d2Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_NOPROGRESS, 1L);
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_NOSIGNAL, 1L);
e4c81823af1fc43ca3f2ce9eb4af7fc8f57b13a5Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_READFUNCTION, curl_output_func);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_WRITEFUNCTION, curl_input_func);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_WRITEDATA, conn);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HEADERFUNCTION, curl_header_func);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HEADERDATA, conn);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen conn->headers = curl_slist_append(NULL, "Content-Type: text/xml");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen conn->headers_post = curl_slist_append(NULL, "Content-Type: text/xml");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen conn->headers_post = curl_slist_append(conn->headers_post,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen "Transfer-Encoding: chunked");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen conn->headers_post = curl_slist_append(conn->headers_post,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HTTPHEADER, conn->headers);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen "fts_solr: Failed to allocate XML parser");
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenvoid solr_connection_deinit(struct solr_connection *conn)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenvoid solr_connection_quote_str(struct solr_connection *conn, string_t *dest,
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen const char *str)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen encoded = curl_easy_escape(conn->curl, str_escape(str), 0);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic const char *attrs_get_name(const char **attrs)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainensolr_lookup_xml_start(void *context, const char *name, const char **attrs)
20344c0e814139e3c365fbb9287478f91512089eTimo Sirainen struct solr_lookup_xml_context *ctx = context;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen /* skipping over unwanted elements */
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen /* response -> result -> doc */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_UID;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_SCORE;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainenstatic void solr_lookup_xml_end(void *context, const char *name ATTR_UNUSED)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct solr_lookup_xml_context *ctx = context;
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen ctx->content_state = SOLR_XML_CONTENT_STATE_NONE;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstatic void solr_lookup_xml_data(void *context, const char *str, int len)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct solr_lookup_xml_context *ctx = context;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenint solr_connection_select(struct solr_connection *conn, const char *query,
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen struct solr_lookup_xml_context solr_lookup_context;
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen memset(&solr_lookup_context, 0, sizeof(solr_lookup_context));
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen XML_SetCharacterDataHandler(conn->xml_parser, solr_lookup_xml_data);
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen XML_SetUserData(conn->xml_parser, &solr_lookup_context);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_URL, str_c(str));
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen curl_easy_getinfo(conn->curl, CURLINFO_RESPONSE_CODE, &httpret);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen i_error("fts_solr: Lookup failed: %s", conn->http_failure);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainensolr_connection_post_begin(struct solr_connection *conn)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_READDATA, post);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen merr = curl_multi_add_handle(conn->curlm, conn->curl);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen i_error("fts_solr: curl_multi_add_handle() failed: %s",
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_URL, str_c(str));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HTTPHEADER,
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_POST, (long)1);
0611067f385a37773800225256dcd5cf6aa34212Timo Sirainenvoid solr_connection_post_more(struct solr_connection_post *post,
1036ad17ac837a451f6b045cac504d3efa2edb8eTimo Sirainen merr = curl_multi_perform(post->conn->curlm, &handles);
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainen i_error("fts_solr: curl_multi_perform() failed: %s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if ((post->pos == post->size && post->size != 0) ||
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* everything sent successfully */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* everything wasn't sent - wait. just use select,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen since libcurl interface is easiest with it. */
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen merr = curl_multi_fdset(post->conn->curlm, &fdread, &fdwrite,
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen i_error("fts_solr: curl_multi_fdset() failed: %s",
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen merr = curl_multi_timeout(post->conn->curlm, &timeout);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_error("fts_solr: curl_multi_timeout() failed: %s",
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ret = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout_tv);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainenint solr_connection_post_end(struct solr_connection_post *post)
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen curl_easy_getinfo(conn->curl, CURLINFO_RESPONSE_CODE, &httpret);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen i_error("fts_solr: Indexing failed: %s", conn->http_failure);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_READDATA, NULL);
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_POST, (long)0);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen curl_easy_setopt(conn->curl, CURLOPT_HTTPHEADER, conn->headers);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen (void)curl_multi_remove_handle(conn->curlm, conn->curl);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenint solr_connection_post(struct solr_connection *conn, const char *cmd)
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen solr_connection_post_more(post, (const unsigned char *)cmd,