Skip to content

Commit a29453e

Browse files
author
wangkx
committed
HPCC-12516 WIP
Signed-off-by: wangkx <kevin.wang@lexisnexis.com>
1 parent 77723cd commit a29453e

File tree

3 files changed

+287
-3
lines changed

3 files changed

+287
-3
lines changed

esp/bindings/http/platform/httpbinding.cpp

Lines changed: 245 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,9 +507,253 @@ bool EspHttpBinding::basicAuth(IEspContext* ctx)
507507
ctx->addTraceSummaryTimeStamp(LogMin, "basicAuth");
508508
return authorized;
509509
}
510-
510+
511+
#include <libmemcached/memcached.hpp>
512+
#include <libmemcached/util.h>
513+
514+
#define MEMCACHED_VERSION "memcached plugin 1.0.0"
515+
511516
void EspHttpBinding::handleHttpPost(CHttpRequest *request, CHttpResponse *response)
512517
{
518+
class ESPMemCached : public CInterface
519+
{
520+
memcached_st * connection = nullptr;
521+
memcached_pool_st * pool = nullptr;
522+
StringAttr options;
523+
524+
public :
525+
ESPMemCached(const char * _options)
526+
{
527+
#if (LIBMEMCACHED_VERSION_HEX < 0x01000010)
528+
VStringBuffer msg("Memcached Plugin: libmemcached version '%s' incompatible with min version>=1.0.10", LIBMEMCACHED_VERSION_STRING);
529+
ESPLOG(LogNormal, "%s", msg.str());
530+
#endif
531+
532+
options.set(_options);
533+
pool = memcached_pool(_options, strlen(_options));
534+
assertPool();
535+
536+
setPoolSettings();
537+
connect();
538+
if (connection)
539+
{
540+
DBGLOG("ESPMemCached connection<%d>", memcached_server_count(connection));
541+
/*const char * msg = "'Set' request failed - ";
542+
DBGLOG("20");
543+
char key[1024];
544+
int length= snprintf(key, sizeof(key), "%s%u", "n", 1);
545+
memcached_set(connection, key, length,
546+
NULL, 0, // Zero length values
547+
time_t(0), uint32_t(0));
548+
DBGLOG("21");*/
549+
checkServersUp();
550+
}
551+
}
552+
553+
~ESPMemCached()
554+
{
555+
if (pool)
556+
{
557+
memcached_pool_release(pool, connection);
558+
connection = nullptr;//For safety (from changing this destructor) as not implicit in either the above or below.
559+
memcached_st *memc = memcached_pool_destroy(pool);
560+
if (memc)
561+
memcached_free(memc);
562+
}
563+
else if (connection)//This should never be needed but just in case.
564+
{
565+
memcached_free(connection);
566+
}
567+
};
568+
569+
void setPoolSettings()
570+
{
571+
assertPool();
572+
const char * msg = "memcached_pool_behavior_set failed - ";
573+
assertOnError(memcached_pool_behavior_set(pool, MEMCACHED_BEHAVIOR_KETAMA, 1), msg);//NOTE: alias of MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA amongst others.
574+
memcached_pool_behavior_set(pool, MEMCACHED_BEHAVIOR_USE_UDP, 0); // Note that this fails on early versions of libmemcached, so ignore result
575+
assertOnError(memcached_pool_behavior_set(pool, MEMCACHED_BEHAVIOR_NO_BLOCK, 0), msg);
576+
assertOnError(memcached_pool_behavior_set(pool, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, 1000), msg);//units of ms.
577+
assertOnError(memcached_pool_behavior_set(pool, MEMCACHED_BEHAVIOR_SND_TIMEOUT, 1000000), msg);//units of mu-s.
578+
assertOnError(memcached_pool_behavior_set(pool, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, 1000000), msg);//units of mu-s.
579+
assertOnError(memcached_pool_behavior_set(pool, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 0), msg);
580+
assertOnError(memcached_pool_behavior_set(pool, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1), "memcached_pool_behavior_set failed - ");
581+
}
582+
583+
void connect()
584+
{
585+
assertPool();
586+
if (connection)
587+
#if (LIBMEMCACHED_VERSION_HEX<0x53000)
588+
memcached_pool_push(pool, connection);
589+
#else
590+
memcached_pool_release(pool, connection);
591+
#endif
592+
memcached_return_t rc;
593+
#if (LIBMEMCACHED_VERSION_HEX<0x53000)
594+
connection = memcached_pool_pop(pool, (struct timespec *)0 , &rc);
595+
#else
596+
connection = memcached_pool_fetch(pool, (struct timespec *)0 , &rc);
597+
#endif
598+
assertOnError(rc, "memcached_pool_pop failed - ");
599+
}
600+
601+
//This call does not work here.
602+
void checkServersUp()
603+
{
604+
memcached_return_t rc;
605+
char * args = NULL;
606+
OwnedMalloc<memcached_stat_st> stats;
607+
DBGLOG("Before memcached_stat");
608+
stats.setown(memcached_stat(connection, args, &rc));
609+
DBGLOG("After memcached_stat");
610+
611+
unsigned int numberOfServers = memcached_server_count(connection);
612+
unsigned int numberOfServersDown = 0;
613+
for (unsigned i = 0; i < numberOfServers; ++i)
614+
{
615+
if (stats[i].pid == -1)//perhaps not the best test?
616+
{
617+
numberOfServersDown++;
618+
VStringBuffer msg("Memcached Plugin: Failed connecting to entry %u\nwithin the server list: %s", i+1, options.str());
619+
DBGLOG("%s", msg.str());
620+
}
621+
}
622+
if (numberOfServersDown == numberOfServers)
623+
ESPLOG(LogNormal,"Memcached Plugin: Failed connecting to ALL servers. Check memcached on all servers and \"memcached -B ascii\" not used.");
624+
625+
//check memcached version homogeneity
626+
for (unsigned i = 0; i < numberOfServers-1; ++i)
627+
{
628+
if (!streq(stats[i].version, stats[i+1].version))
629+
DBGLOG("Memcached Plugin: Inhomogeneous versions of memcached across servers.");
630+
}
631+
};
632+
633+
void clear(unsigned when)
634+
{
635+
//NOTE: memcached_flush is the actual cache flush/clear/delete and not an io buffer flush.
636+
assertOnError(memcached_flush(connection, (time_t)(when)), "'Clear' request failed - ");
637+
};
638+
639+
bool exists(const char * key, const char * partitionKey)
640+
{
641+
#if (LIBMEMCACHED_VERSION_HEX<0x53000)
642+
throw makeStringException(0, "memcached_exist not supported in this version of libmemcached");
643+
#else
644+
memcached_return_t rc;
645+
size_t partitionKeyLength = strlen(partitionKey);
646+
if (partitionKeyLength)
647+
rc = memcached_exist_by_key(connection, partitionKey, partitionKeyLength, key, strlen(key));
648+
else
649+
rc = memcached_exist(connection, key, strlen(key));
650+
651+
if (rc == MEMCACHED_NOTFOUND)
652+
return false;
653+
else
654+
{
655+
assertOnError(rc, "'Exists' request failed - ");
656+
return true;
657+
}
658+
#endif
659+
};
660+
661+
char* get(const char * partitionKey, const char * key, size_t & returnLength)
662+
{
663+
uint32_t flag = 0;
664+
memcached_return_t rc;
665+
666+
OwnedMalloc<char> value;
667+
size_t partitionKeyLength = strlen(partitionKey);
668+
if (partitionKeyLength)
669+
value.setown(memcached_get_by_key(connection, partitionKey, partitionKeyLength, key, strlen(key), &returnLength, &flag, &rc));
670+
else
671+
value.setown(memcached_get(connection, key, strlen(key), &returnLength, &flag, &rc));
672+
673+
StringBuffer keyMsg = "'Get<type>' request failed - ";
674+
assertOnError(rc, appendIfKeyNotFoundMsg(rc, key, keyMsg));
675+
676+
//returnValue = reinterpret_cast<type*>(cpy(value, returnLength));
677+
return value;
678+
};
679+
680+
/*void * cpy(const char * src, size_t length)
681+
{
682+
void * value = rtlMalloc(length);
683+
return memcpy(value, src, length);
684+
};*/
685+
686+
void set(const char * partitionKey, const char * key, const char * value, unsigned __int64 expireSec)
687+
{
688+
size_t partitionKeyLength = strlen(partitionKey);
689+
const char * msg = "'Set' request failed - ";
690+
DBGLOG("1");
691+
if (connection)
692+
DBGLOG("2");
693+
if (partitionKeyLength)
694+
assertOnError(memcached_set_by_key(connection, partitionKey, partitionKeyLength, key, strlen(key), value, strlen(value), (time_t)expireSec, 0), msg);
695+
else
696+
assertOnError(memcached_set(connection, key, strlen(key), value, strlen(value), (time_t)expireSec, 0), msg);
697+
DBGLOG("3");
698+
};
699+
700+
void deleteKey(const char * key, const char * partitionKey)
701+
{
702+
memcached_return_t rc;
703+
size_t partitionKeyLength = strlen(partitionKey);
704+
if (partitionKeyLength)
705+
rc = memcached_delete_by_key(connection, partitionKey, partitionKeyLength, key, strlen(key), (time_t)0);
706+
else
707+
rc = memcached_delete(connection, key, strlen(key), (time_t)0);
708+
assertOnError(rc, "'Delete' request failed - ");
709+
};
710+
711+
void assertOnError(memcached_return_t rc, const char * _msg)
712+
{
713+
DBGLOG("assertOnError:1");
714+
if (rc != MEMCACHED_SUCCESS)
715+
{
716+
VStringBuffer msg("Memcached Plugin: %s%s", _msg, memcached_strerror(connection, rc));
717+
ESPLOG(LogNormal, "%s", msg.str());
718+
}
719+
DBGLOG("assertOnError:2");
720+
};
721+
722+
const char * appendIfKeyNotFoundMsg(memcached_return_t rc, const char * key, StringBuffer & target) const
723+
{
724+
if (rc == MEMCACHED_NOTFOUND)
725+
target.append("(key: '").append(key).append("') ");
726+
return target.str();
727+
};
728+
729+
void assertPool()
730+
{
731+
if (!pool)
732+
{
733+
StringBuffer msg = "Memcached Plugin: Failed to instantiate server pool with:";
734+
msg.newline().append(options);
735+
ESPLOG(LogNormal, "%s", msg.str());
736+
}
737+
}
738+
};
739+
StringBuffer testOpt;
740+
// testOpt.set("--SERVER=10.176.152.33 --POOL-MIN=1 --POOL-MAX=32");
741+
//testOpt.set("--SERVER=host10.example.com");
742+
testOpt.set("--SERVER=10.176.152.33");
743+
//testOpt.set("-POOL-MIN=10");
744+
ESPMemCached testCache(testOpt.str());
745+
DBGLOG("Before set");
746+
testCache.set("ESPResponse", "AKey", "AValue", 300);
747+
size_t returnLength1, returnLength2;
748+
char* retV1 = testCache.get("ESPResponse", "AKey", returnLength1);
749+
if (retV1 && *retV1 && (returnLength1 > 0))
750+
DBGLOG("retV1<%s>", retV1);
751+
testCache.clear(0);
752+
char* retV2 = testCache.get("ESPResponse", "AKey", returnLength2);
753+
if (retV2 && *retV2 && (returnLength2 > 0))
754+
DBGLOG("retV2<%s>", retV2);
755+
DBGLOG("Done");
756+
513757
if(request->isSoapMessage())
514758
{
515759
request->queryParameters()->setProp("__wsdl_address", m_wsdlAddress.str());

esp/platform/CMakeLists.txt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ include_directories (
4949
ADD_DEFINITIONS( -D_CONSOLE )
5050

5151
HPCC_ADD_EXECUTABLE ( esp ${SRCS} )
52+
53+
#if(NOT DEFINED LIBMEMCACHED_MINVERSION)
54+
# set(LIBMEMCACHED_MINVERSION "1.0.10")
55+
#endif()
56+
57+
# ADD_PLUGIN(memcached PACKAGES LIBMEMCACHED MINVERSION ${LIBMEMCACHED_MINVERSION})
58+
# find_package(LIBMEMCACHED "1.0.10")
59+
#set(findvar LIBMEMCACHED_VERSION_STRING)
60+
# string(TOUPPER ${findvar} LIBMEMCACHED_VERSION_STRING)
61+
# find_package(LIBMEMCACHED ${PLUGIN_MINVERSION} )
62+
63+
install(CODE "set(ENV{LD_LIBRARY_PATH} \"\$ENV{LD_LIBRARY_PATH}:${PROJECT_BINARY_DIR}:${PROJECT_BINARY_DIR}/libmemcached-${LIBMEMCACHED_VERSION}/libmemcached/.libs\")")
64+
5265
install ( TARGETS esp RUNTIME DESTINATION ${EXEC_DIR} )
5366
target_link_libraries ( esp
5467
jlib
@@ -59,5 +72,6 @@ target_link_libraries ( esp
5972
hrpc
6073
remote
6174
dalibase
62-
environment
75+
environment
76+
# ${LIBMEMCACHED_LIBRARIES}
6377
)

esp/protocols/http/CMakeLists.txt

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,38 @@ include_directories (
6363
./../../services/common
6464
./../../../system/security/shared
6565
./../../../system/security/LdapSecurity
66+
${LIBMEMCACHED_INCLUDE_DIR}
6667
)
6768

6869
ADD_DEFINITIONS( -DESPHTTP_EXPORTS -DESP_TIMING -D_USRDLL -DESP_PLUGIN )
6970

7071
HPCC_ADD_LIBRARY( esphttp SHARED ${SRCS} )
71-
add_dependencies (esphttp espscm )
72+
73+
74+
if(NOT DEFINED LIBMEMCACHED_MINVERSION)
75+
set(LIBMEMCACHED_MINVERSION "1.0.10")
76+
endif()
77+
find_package(LIBMEMCACHED ${LIBMEMCACHED_MINVERSION})
78+
79+
IF (WIN32)
80+
SET (libmemcached_lib "libmemcached")
81+
SET (libmemcachedUtil_lib "libmemcachedutil")
82+
ELSE()
83+
SET (libmemcached_lib "memcached")
84+
SET (libmemcachedUtil_lib "memcachedutil")
85+
ENDIF()
86+
87+
FIND_PATH(LIBMEMCACHED_INCLUDE_DIR libmemcached/memcached.hpp PATHS /usr/include /usr/share/include /usr/local/include PATH_SUFFIXES libmemcached)
88+
FIND_LIBRARY (LIBMEMCACHEDCORE_LIBRARY NAMES ${libmemcached_lib} PATHS /usr/lib usr/lib/libmemcached /usr/share /usr/lib64 /usr/local/lib /usr/local/lib64)
89+
FIND_LIBRARY (LIBMEMCACHEDUTIL_LIBRARY NAMES ${libmemcachedUtil_lib} PATHS /usr/lib /usr/share /usr/lib64 /usr/local/lib /usr/local/lib64)
90+
91+
SET (LIBMEMCACHED_LIBRARIES ${LIBMEMCACHEDCORE_LIBRARY} ${LIBMEMCACHEDUTIL_LIBRARY})
92+
target_link_libraries ( esphttp ${LIBMEMCACHED_LIBRARIES} )
93+
94+
install(CODE "set(ENV{LD_LIBRARY_PATH} \"\$ENV{LD_LIBRARY_PATH}:${PROJECT_BINARY_DIR}:${PROJECT_BINARY_DIR}/libmemcached-${LIBMEMCACHED_VERSION}/libmemcached/.libs\")")
95+
96+
97+
add_dependencies(esphttp espscm)
7298
install ( TARGETS esphttp RUNTIME DESTINATION ${EXEC_DIR} LIBRARY DESTINATION ${LIB_DIR} )
7399
target_link_libraries ( esphttp
74100
${XALAN_LIBRARIES} ${XERCES_LIBRARIES}

0 commit comments

Comments
 (0)