git subrepo clone (merge) --branch=v3.6.1 https://github.com/nats-io/nats.c.git deps/nats.c
subrepo: subdir: "deps/nats.c" merged: "66cec7f" upstream: origin: "https://github.com/nats-io/nats.c.git" branch: "v3.6.1" commit: "66cec7f" git-subrepo: version: "0.4.6" commit: "b8b46501e"
This commit is contained in:
89
deps/nats.c/examples/CMakeLists.txt
vendored
Normal file
89
deps/nats.c/examples/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
if(NOT NATS_BUILD_EXAMPLES)
|
||||
return()
|
||||
endif()
|
||||
if(NOT NATS_BUILD_STATIC_EXAMPLES AND NOT NATS_BUILD_LIB_SHARED)
|
||||
MESSAGE(FATAL_ERROR
|
||||
"Building examples require shared library, or run CMake with -DNATS_BUILD_STATIC_EXAMPLES=ON")
|
||||
endif()
|
||||
|
||||
# We need this directory to build the examples
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/examples)
|
||||
|
||||
if(NATS_BUILD_LIBUV_EXAMPLE AND LIBUV_DIR)
|
||||
include_directories(${LIBUV_DIR}/include)
|
||||
endif()
|
||||
|
||||
if(NATS_BUILD_LIBEVENT_EXAMPLE AND LIBEVENT_DIR)
|
||||
include_directories(${LIBEVENT_DIR}/include)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(LIB_SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
else()
|
||||
if(NATS_BUILD_STATIC_EXAMPLES)
|
||||
set(LIB_SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
else()
|
||||
set(LIB_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Get all the .c files in the examples directory
|
||||
file(GLOB EXAMPLES_SOURCES RELATIVE ${PROJECT_SOURCE_DIR}/examples *.c)
|
||||
|
||||
if(NOT NATS_BUILD_STATIC_EXAMPLES)
|
||||
add_definitions(-Dnats_IMPORTS)
|
||||
endif()
|
||||
|
||||
# For each file...
|
||||
foreach(examples_src ${EXAMPLES_SOURCES})
|
||||
|
||||
# Remove the suffix so that it becomes the executable name
|
||||
string(REPLACE ".c" "" examplename ${examples_src})
|
||||
set(exampleexe "nats-${examplename}")
|
||||
|
||||
set(buildExample OFF)
|
||||
set(NATS_ASYNC_IO_LIB "")
|
||||
|
||||
if(examplename MATCHES "libuv")
|
||||
if(NATS_BUILD_LIBUV_EXAMPLE)
|
||||
set(buildExample ON)
|
||||
if(LIBUV_DIR)
|
||||
set(NATS_ASYNC_IO_LIB ${LIBUV_DIR}/lib/libuv${LIB_SUFFIX})
|
||||
else()
|
||||
set(NATS_ASYNC_IO_LIB uv)
|
||||
endif()
|
||||
endif()
|
||||
elseif(examplename MATCHES "libevent")
|
||||
if(NATS_BUILD_LIBEVENT_EXAMPLE)
|
||||
set(buildExample ON)
|
||||
if(LIBEVENT_DIR)
|
||||
if(WIN32)
|
||||
set(NATS_ASYNC_IO_LIB ${LIBEVENT_DIR}/lib/event${LIB_SUFFIX})
|
||||
else()
|
||||
set(NATS_ASYNC_IO_LIB ${LIBEVENT_DIR}/lib/libevent${LIB_SUFFIX} ${LIBEVENT_DIR}/lib/libevent_pthreads${LIB_SUFFIX})
|
||||
endif()
|
||||
else()
|
||||
set(NATS_ASYNC_IO_LIB event)
|
||||
if(UNIX)
|
||||
list(APPEND NATS_ASYNC_IO_LIB event_pthreads)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(buildExample ON)
|
||||
endif()
|
||||
|
||||
if(buildExample)
|
||||
# Build the executable
|
||||
add_executable(${exampleexe} ${PROJECT_SOURCE_DIR}/examples/${examples_src})
|
||||
|
||||
# Link
|
||||
if(NATS_BUILD_STATIC_EXAMPLES)
|
||||
target_link_libraries(${exampleexe} nats_static ${NATS_EXTRA_LIB} ${NATS_ASYNC_IO_LIB})
|
||||
else()
|
||||
target_link_libraries(${exampleexe} nats ${NATS_EXTRA_LIB} ${NATS_ASYNC_IO_LIB})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
endforeach()
|
94
deps/nats.c/examples/asynctimeout.c
vendored
Normal file
94
deps/nats.c/examples/asynctimeout.c
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright 2015-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-gd use global message delivery thread pool\n" \
|
||||
"-queue use a queue subscriber with this name\n" \
|
||||
"-timeout <ms> timeout in milliseconds (default is 10sec)\n" \
|
||||
"-count number of expected messages\n";
|
||||
|
||||
static volatile bool done = false;
|
||||
|
||||
static void
|
||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||
{
|
||||
// This callback will be invoked with a NULL message when the
|
||||
// subscription times out.
|
||||
if (print && (msg != NULL))
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
// We should be using a mutex to protect those variables since
|
||||
// they are used from the subscription's delivery and the main
|
||||
// threads. For demo purposes, this is fine.
|
||||
if ((msg == NULL) || (++count == total))
|
||||
{
|
||||
printf("%s, destroying subscription\n",
|
||||
(msg == NULL ? "Subscription timed-out" : "All messages received"));
|
||||
|
||||
natsSubscription_Destroy(sub);
|
||||
done = true;
|
||||
}
|
||||
|
||||
// It is safe to call natsMsg_Destroy() with a NULL message.
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsStatus s;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Listening asynchronously on '%s' with a timeout of %d ms.\n",
|
||||
subj, (int) timeout);
|
||||
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (name != NULL)
|
||||
s = natsConnection_QueueSubscribeTimeout(&sub, conn, subj, name,
|
||||
timeout, onMsg, NULL);
|
||||
else
|
||||
s = natsConnection_SubscribeTimeout(&sub, conn, subj,
|
||||
timeout, onMsg, NULL);
|
||||
}
|
||||
// Check every half a second for end of test.
|
||||
while ((s == NATS_OK) && !done)
|
||||
{
|
||||
nats_Sleep(500);
|
||||
}
|
||||
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
printf("Error: %u - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
// Do not destroy subscription since it is done in the callback
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
171
deps/nats.c/examples/connect.c
vendored
Normal file
171
deps/nats.c/examples/connect.c
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
// Copyright 2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
static void
|
||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||
{
|
||||
if (print)
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
// We should be using a mutex to protect those variables since
|
||||
// they are used from the subscription's delivery and the main
|
||||
// threads. For demo purposes, this is fine.
|
||||
count++;
|
||||
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
|
||||
static void
|
||||
connectedCB(natsConnection *nc, void *closure)
|
||||
{
|
||||
char url[256];
|
||||
|
||||
natsConnection_GetConnectedUrl(nc, url, sizeof(url));
|
||||
printf("Connected to %s\n", url);
|
||||
}
|
||||
|
||||
static void
|
||||
closedCB(natsConnection *nc, void *closure)
|
||||
{
|
||||
bool *closed = (bool*)closure;
|
||||
const char *err = NULL;
|
||||
|
||||
natsConnection_GetLastError(nc, &err);
|
||||
printf("Connect failed: %s\n", err);
|
||||
*closed = true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
bool closed = false;
|
||||
natsStatus s;
|
||||
|
||||
opts = parseArgs(argc, argv, "");
|
||||
|
||||
// Set a max (re)connect attempts of 50 with a delay of 100 msec.
|
||||
// Total time will then be around 5 seconds.
|
||||
|
||||
s = natsOptions_SetMaxReconnect(opts, 50);
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetReconnectWait(opts, 100);
|
||||
|
||||
// Instruct the library to block the connect call for that
|
||||
// long until it can get a connection or fails.
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetRetryOnFailedConnect(opts, true, NULL, NULL);
|
||||
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
printf("Error: %u - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Ensure no server is running, attempt to connect...\n");
|
||||
|
||||
// If the server is not running, this will block for about 5 seconds.
|
||||
start = nats_Now();
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
elapsed = nats_Now() - start;
|
||||
|
||||
printf("natsConnection_Connect call took %" PRId64 " ms and returned: %s\n", elapsed, natsStatus_GetText(s));
|
||||
|
||||
// Close/destroy the connection in case you had a server running...
|
||||
natsConnection_Destroy(conn);
|
||||
conn = NULL;
|
||||
|
||||
// Now reduce the count, set a connected callback to allow
|
||||
// connect to be done asynchronously and a closed callback
|
||||
// to show that if connect fails, the callback is invoked.
|
||||
s = natsOptions_SetMaxReconnect(opts, 10);
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetRetryOnFailedConnect(opts, true, connectedCB, NULL);
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetClosedCB(opts, closedCB, (void*)&closed);
|
||||
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
printf("Error: %u - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("\n\n");
|
||||
printf("Ensure no server is running, attempt to connect with async connect...\n");
|
||||
|
||||
// Start the connect. If no server is running, it should return
|
||||
// NATS_NOT_YET_CONNECTED.
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
printf("natsConnection_Connect call returned: %s\n", natsStatus_GetText(s));
|
||||
|
||||
// Wait for the closed callback to be invoked
|
||||
while (!closed)
|
||||
nats_Sleep(100);
|
||||
|
||||
// Destroy the connection object
|
||||
natsConnection_Destroy(conn);
|
||||
conn = NULL;
|
||||
|
||||
|
||||
// Now change the options to increase the attempts again.
|
||||
s = natsOptions_SetMaxReconnect(opts, 10);
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetReconnectWait(opts, 1000);
|
||||
// Remove the closed CB for this test
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetClosedCB(opts, NULL, NULL);
|
||||
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
printf("Error: %u - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("\n\n");
|
||||
printf("Ensure no server is running, attempt to connect with async connect...\n");
|
||||
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
printf("Connect returned: %s\n", natsStatus_GetText(s));
|
||||
|
||||
// Create a subscription and send a message...
|
||||
s = natsConnection_Subscribe(&sub, conn, subj, onMsg, NULL);
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Publish(conn, "foo", (const void*)"hello", 5);
|
||||
|
||||
printf("\nStart a server now...\n\n");
|
||||
|
||||
// Wait for the connect to succeed and message to be received.
|
||||
while ((s == NATS_OK) && (count != 1))
|
||||
nats_Sleep(100);
|
||||
|
||||
printf("Received %d message\n", (int) count);
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
433
deps/nats.c/examples/examples.h
vendored
Normal file
433
deps/nats.c/examples/examples.h
vendored
Normal file
@@ -0,0 +1,433 @@
|
||||
// Copyright 2015-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef EXAMPLES_H_
|
||||
#define EXAMPLES_H_
|
||||
|
||||
#include <nats.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strcasecmp _stricmp
|
||||
#define strdup _strdup
|
||||
#else
|
||||
#include <strings.h>
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#define STATS_IN 0x1
|
||||
#define STATS_OUT 0x2
|
||||
#define STATS_COUNT 0x4
|
||||
|
||||
#define MAX_SERVERS (10)
|
||||
|
||||
bool async = true;
|
||||
const char *subj = "foo";
|
||||
const char *payload= "hello";
|
||||
const char *name = "worker";
|
||||
int64_t total = 1000000;
|
||||
|
||||
volatile int64_t count = 0;
|
||||
volatile int64_t dropped = 0;
|
||||
int64_t start = 0;
|
||||
volatile int64_t elapsed = 0;
|
||||
bool print = false;
|
||||
int64_t timeout = 10000; // 10 seconds.
|
||||
|
||||
natsOptions *opts = NULL;
|
||||
|
||||
const char *certFile = NULL;
|
||||
const char *keyFile = NULL;
|
||||
|
||||
const char *cluster = "test-cluster";
|
||||
const char *clientID = "client";
|
||||
const char *qgroup = NULL;
|
||||
const char *durable = NULL;
|
||||
bool deliverAll = false;
|
||||
bool deliverLast = true;
|
||||
uint64_t deliverSeq = 0;
|
||||
bool unsubscribe = false;
|
||||
|
||||
const char *stream = NULL;
|
||||
bool pull = false;
|
||||
bool flowctrl = false;
|
||||
|
||||
static natsStatus
|
||||
printStats(int mode, natsConnection *conn, natsSubscription *sub,
|
||||
natsStatistics *stats)
|
||||
{
|
||||
natsStatus s = NATS_OK;
|
||||
uint64_t inMsgs = 0;
|
||||
uint64_t inBytes = 0;
|
||||
uint64_t outMsgs = 0;
|
||||
uint64_t outBytes = 0;
|
||||
uint64_t reconnected = 0;
|
||||
int pending = 0;
|
||||
int64_t delivered = 0;
|
||||
int64_t sdropped = 0;
|
||||
|
||||
s = natsConnection_GetStats(conn, stats);
|
||||
if (s == NATS_OK)
|
||||
s = natsStatistics_GetCounts(stats, &inMsgs, &inBytes,
|
||||
&outMsgs, &outBytes, &reconnected);
|
||||
if ((s == NATS_OK) && (sub != NULL))
|
||||
{
|
||||
s = natsSubscription_GetStats(sub, &pending, NULL, NULL, NULL,
|
||||
&delivered, &sdropped);
|
||||
|
||||
// Since we use AutoUnsubscribe(), when the max has been reached,
|
||||
// the subscription is automatically closed, so this call would
|
||||
// return "Invalid Subscription". Ignore this error.
|
||||
if (s == NATS_INVALID_SUBSCRIPTION)
|
||||
{
|
||||
s = NATS_OK;
|
||||
pending = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (mode & STATS_IN)
|
||||
{
|
||||
printf("In Msgs: %9" PRIu64 " - "\
|
||||
"In Bytes: %9" PRIu64 " - ", inMsgs, inBytes);
|
||||
}
|
||||
if (mode & STATS_OUT)
|
||||
{
|
||||
printf("Out Msgs: %9" PRIu64 " - "\
|
||||
"Out Bytes: %9" PRIu64 " - ", outMsgs, outBytes);
|
||||
}
|
||||
if (mode & STATS_COUNT)
|
||||
{
|
||||
printf("Delivered: %9" PRId64 " - ", delivered);
|
||||
printf("Pending: %5d - ", pending);
|
||||
printf("Dropped: %5" PRId64 " - ", sdropped);
|
||||
}
|
||||
printf("Reconnected: %3" PRIu64 "\n", reconnected);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static void
|
||||
printPerf(const char *perfTxt)
|
||||
{
|
||||
if ((start > 0) && (elapsed == 0))
|
||||
elapsed = nats_Now() - start;
|
||||
|
||||
if (elapsed <= 0)
|
||||
printf("\nNot enough messages or too fast to report performance!\n");
|
||||
else
|
||||
printf("\n%s %" PRId64 " messages in "\
|
||||
"%" PRId64 " milliseconds (%d msgs/sec)\n",
|
||||
perfTxt, count, elapsed, (int)((count * 1000) / elapsed));
|
||||
}
|
||||
|
||||
static void
|
||||
printUsageAndExit(const char *progName, const char *usage)
|
||||
{
|
||||
printf("\nUsage: %s [options]\n\nThe options are:\n\n"\
|
||||
"-h prints the usage\n" \
|
||||
"-s server url(s) (list of comma separated nats urls)\n" \
|
||||
"-tls use secure (SSL/TLS) connection\n" \
|
||||
"-tlscacert trusted certificates file\n" \
|
||||
"-tlscert client certificate (PEM format only)\n" \
|
||||
"-tlskey client private key file (PEM format only)\n" \
|
||||
"-tlsciphers ciphers suite\n"
|
||||
"-tlshost server certificate's expected hostname\n" \
|
||||
"-tlsskip skip server certificate verification\n" \
|
||||
"-creds user credentials chained file\n" \
|
||||
"-subj subject (default is 'foo')\n" \
|
||||
"-print for consumers, print received messages (default is false)\n" \
|
||||
"-wd write deadline in milliseconds\n" \
|
||||
"%s\n",
|
||||
progName, usage);
|
||||
|
||||
natsOptions_Destroy(opts);
|
||||
nats_Close();
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static natsStatus
|
||||
parseUrls(const char *urls, natsOptions *gopts)
|
||||
{
|
||||
char *serverUrls[MAX_SERVERS];
|
||||
int num = 0;
|
||||
natsStatus s = NATS_OK;
|
||||
char *urlsCopy = NULL;
|
||||
char *commaPos = NULL;
|
||||
char *ptr = NULL;
|
||||
|
||||
urlsCopy = strdup(urls);
|
||||
if (urlsCopy == NULL)
|
||||
return NATS_NO_MEMORY;
|
||||
|
||||
memset(serverUrls, 0, sizeof(serverUrls));
|
||||
|
||||
ptr = urlsCopy;
|
||||
|
||||
do
|
||||
{
|
||||
if (num == MAX_SERVERS)
|
||||
{
|
||||
s = NATS_INSUFFICIENT_BUFFER;
|
||||
break;
|
||||
}
|
||||
|
||||
serverUrls[num++] = ptr;
|
||||
commaPos = strchr(ptr, ',');
|
||||
if (commaPos != NULL)
|
||||
{
|
||||
ptr = (char*)(commaPos + 1);
|
||||
*(commaPos) = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = NULL;
|
||||
}
|
||||
} while (ptr != NULL);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetServers(gopts, (const char**) serverUrls, num);
|
||||
|
||||
free(urlsCopy);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static natsOptions*
|
||||
parseArgs(int argc, char **argv, const char *usage)
|
||||
{
|
||||
natsStatus s = NATS_OK;
|
||||
bool urlsSet = false;
|
||||
int i;
|
||||
|
||||
if (natsOptions_Create(&opts) != NATS_OK)
|
||||
s = NATS_NO_MEMORY;
|
||||
|
||||
for (i=1; (i<argc) && (s == NATS_OK); i++)
|
||||
{
|
||||
if ((strcasecmp(argv[i], "-h") == 0)
|
||||
|| (strcasecmp(argv[i], "-help") == 0))
|
||||
{
|
||||
printUsageAndExit(argv[0], usage);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-s") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
s = parseUrls(argv[++i], opts);
|
||||
if (s == NATS_OK)
|
||||
urlsSet = true;
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-tls") == 0)
|
||||
{
|
||||
s = natsOptions_SetSecure(opts, true);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-tlscacert") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
s = natsOptions_LoadCATrustedCertificates(opts, argv[++i]);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-tlscert") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
certFile = argv[++i];
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-tlskey") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
keyFile = argv[++i];
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-tlsciphers") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
s = natsOptions_SetCiphers(opts, argv[++i]);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-tlshost") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
s = natsOptions_SetExpectedHostname(opts, argv[++i]);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-tlsskip") == 0)
|
||||
{
|
||||
s = natsOptions_SkipServerVerification(opts, true);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-sync") == 0)
|
||||
{
|
||||
async = false;
|
||||
pull = false;
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-subj") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
subj = argv[++i];
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-print") == 0)
|
||||
{
|
||||
print = true;
|
||||
}
|
||||
else if ((strcasecmp(argv[i], "-name") == 0) ||
|
||||
(strcasecmp(argv[i], "-queue") == 0))
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
name = argv[++i];
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-count") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
total = atol(argv[++i]);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-txt") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
payload = argv[++i];
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-timeout") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
timeout = atol(argv[++i]);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-gd") == 0)
|
||||
{
|
||||
s = natsOptions_UseGlobalMessageDelivery(opts, true);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-c") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
cluster = argv[++i];
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-id") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
clientID = argv[++i];
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-last") == 0)
|
||||
{
|
||||
deliverLast = true;
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-all") == 0)
|
||||
{
|
||||
deliverAll = true;
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-seq") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
deliverSeq = atol(argv[++i]);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-durable") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
durable = argv[++i];
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-qgroup") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
qgroup = argv[++i];
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-unsubscribe") == 0)
|
||||
{
|
||||
unsubscribe = true;
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-creds") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
s = natsOptions_SetUserCredentialsFromFiles(opts, argv[++i], NULL);
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-wd") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
s = natsOptions_SetWriteDeadline(opts, atol(argv[++i]));
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-stream") == 0)
|
||||
{
|
||||
if (i + 1 == argc)
|
||||
printUsageAndExit(argv[0], usage);
|
||||
|
||||
stream = argv[++i];
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-pull") == 0)
|
||||
{
|
||||
async = false;
|
||||
pull = true;
|
||||
}
|
||||
else if (strcasecmp(argv[i], "-fc") == 0)
|
||||
{
|
||||
flowctrl = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Unknown option: '%s'\n", argv[i]);
|
||||
printUsageAndExit(argv[0], usage);
|
||||
}
|
||||
}
|
||||
|
||||
if ((s == NATS_OK) && ((certFile != NULL) || (keyFile != NULL)))
|
||||
s = natsOptions_LoadCertificatesChain(opts, certFile, keyFile);
|
||||
|
||||
if ((s == NATS_OK) && !urlsSet)
|
||||
s = parseUrls(NATS_DEFAULT_URL, opts);
|
||||
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
printf("Error parsing arguments: %u - %s\n",
|
||||
s, natsStatus_GetText(s));
|
||||
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
|
||||
natsOptions_Destroy(opts);
|
||||
nats_Close();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
#endif /* EXAMPLES_H_ */
|
33
deps/nats.c/examples/getstarted/CMakeLists.txt
vendored
Normal file
33
deps/nats.c/examples/getstarted/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
if(NOT NATS_BUILD_EXAMPLES)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# We need this directory to build the examples
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/examples/getstarted)
|
||||
|
||||
# Get all the .c files in the examples directory
|
||||
file(GLOB EXAMPLES_SOURCES RELATIVE ${PROJECT_SOURCE_DIR}/examples/getstarted *.c)
|
||||
|
||||
if(NOT NATS_BUILD_STATIC_EXAMPLES)
|
||||
add_definitions(-Dnats_IMPORTS)
|
||||
endif()
|
||||
|
||||
# For each file...
|
||||
foreach(examples_src ${EXAMPLES_SOURCES})
|
||||
|
||||
# Remove the suffix so that it becomes the executable name
|
||||
string(REPLACE ".c" "" examplename ${examples_src})
|
||||
set(exampleexe "${examplename}")
|
||||
|
||||
# Build the executable
|
||||
add_executable(${exampleexe} ${PROJECT_SOURCE_DIR}/examples/getstarted/${examples_src})
|
||||
|
||||
# Link
|
||||
if(NATS_BUILD_STATIC_EXAMPLES)
|
||||
target_link_libraries(${exampleexe} nats_static ${NATS_EXTRA_LIB})
|
||||
else()
|
||||
target_link_libraries(${exampleexe} nats ${NATS_EXTRA_LIB})
|
||||
endif()
|
||||
|
||||
endforeach()
|
69
deps/nats.c/examples/getstarted/asyncsub.c
vendored
Normal file
69
deps/nats.c/examples/getstarted/asyncsub.c
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2017-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <nats.h>
|
||||
|
||||
static void
|
||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||
{
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
// Need to destroy the message!
|
||||
natsMsg_Destroy(msg);
|
||||
|
||||
// Notify the main thread that we are done.
|
||||
*(bool *)(closure) = true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsStatus s;
|
||||
volatile bool done = false;
|
||||
|
||||
printf("Listening on subject 'foo'\n");
|
||||
|
||||
// Creates a connection to the default NATS URL
|
||||
s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
// Creates an asynchronous subscription on subject "foo".
|
||||
// When a message is sent on subject "foo", the callback
|
||||
// onMsg() will be invoked by the client library.
|
||||
// You can pass a closure as the last argument.
|
||||
s = natsConnection_Subscribe(&sub, conn, "foo", onMsg, (void*) &done);
|
||||
}
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
for (;!done;) {
|
||||
nats_Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
// Anything that is created need to be destroyed
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
|
||||
// If there was an error, print a stack trace and exit
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
135
deps/nats.c/examples/getstarted/headers.c
vendored
Normal file
135
deps/nats.c/examples/getstarted/headers.c
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
// Copyright 2020-2021 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <nats.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsMsg *msg = NULL;
|
||||
natsMsg *rmsg = NULL;
|
||||
natsStatus s;
|
||||
|
||||
// Creates a connection to the default NATS URL
|
||||
s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL);
|
||||
|
||||
// Create a message
|
||||
if (s == NATS_OK)
|
||||
s = natsMsg_Create(&msg, "foo", NULL, "body", 4);
|
||||
|
||||
// Create a header by setting a key/value
|
||||
if (s == NATS_OK)
|
||||
s = natsMsgHeader_Set(msg, "My-Key1", "value1");
|
||||
|
||||
// Let's set a new key
|
||||
if (s == NATS_OK)
|
||||
s = natsMsgHeader_Set(msg, "My-Key2", "value2");
|
||||
|
||||
// Here we add a value to the first key
|
||||
if (s == NATS_OK)
|
||||
s = natsMsgHeader_Add(msg, "My-Key1", "value3");
|
||||
|
||||
// Adding yet another key
|
||||
if (s == NATS_OK)
|
||||
s = natsMsgHeader_Set(msg, "My-Key3", "value4");
|
||||
|
||||
// Remove a key
|
||||
if (s == NATS_OK)
|
||||
s = natsMsgHeader_Delete(msg, "My-Key3");
|
||||
|
||||
// Let's print all the keys that are currently set
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
const char* *keys = NULL;
|
||||
int nkeys = 0;
|
||||
int i;
|
||||
|
||||
s = natsMsgHeader_Keys(msg, &keys, &nkeys);
|
||||
for (i=0; (s == NATS_OK) && (i<nkeys); i++)
|
||||
{
|
||||
// To get all values that are associated with a key
|
||||
const char* *values = NULL;
|
||||
int nvalues = 0;
|
||||
int j;
|
||||
|
||||
s = natsMsgHeader_Values(msg, keys[i], &values, &nvalues);
|
||||
|
||||
for (j=0; (s == NATS_OK) && (j < nvalues); j++)
|
||||
printf("Key: '%s' Value: '%s'\n", keys[i], values[j]);
|
||||
|
||||
// We need to free the returned array of pointers.
|
||||
free((void*) values);
|
||||
}
|
||||
// We need to free the returned array of pointers.
|
||||
free((void*) keys);
|
||||
}
|
||||
|
||||
// Create a subscription that we will use to receive this message
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_SubscribeSync(&sub, conn, "foo");
|
||||
|
||||
// Now publish the message
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_PublishMsg(conn, msg);
|
||||
|
||||
// We should receive it
|
||||
if (s == NATS_OK)
|
||||
s = natsSubscription_NextMsg(&rmsg, sub, 1000);
|
||||
|
||||
// Now let's check some headers from the received message
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
const char *val = NULL;
|
||||
|
||||
// Notice that calling natsMsgHeader_Get() on a key that has
|
||||
// several values will return the first entry.
|
||||
s = natsMsgHeader_Get(rmsg, "My-Key1", &val);
|
||||
if (s == NATS_OK)
|
||||
printf("For key 'My-Key1', got value: '%s'\n", val);
|
||||
|
||||
// If we lookup for a key that does not exist, we get NATS_NOT_FOUND.
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
s = natsMsgHeader_Get(rmsg, "key-does-not-exist", &val);
|
||||
if (s == NATS_NOT_FOUND)
|
||||
s = NATS_OK;
|
||||
else
|
||||
printf("Should not have found that key!\n");
|
||||
}
|
||||
// Same for delete
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
s = natsMsgHeader_Delete(rmsg, "key-does-not-exist");
|
||||
if (s == NATS_NOT_FOUND)
|
||||
s = NATS_OK;
|
||||
else
|
||||
printf("Should not have found that key!\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Anything that is created need to be destroyed
|
||||
natsMsg_Destroy(msg);
|
||||
natsMsg_Destroy(rmsg);
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
|
||||
// If there was an error, print a stack trace and exit
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
48
deps/nats.c/examples/getstarted/pubbytes.c
vendored
Normal file
48
deps/nats.c/examples/getstarted/pubbytes.c
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright 2017-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <nats.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsStatus s;
|
||||
|
||||
printf("Publishes a message on subject 'foo'\n");
|
||||
|
||||
// Creates a connection to the default NATS URL
|
||||
s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
const char data[] = {104, 101, 108, 108, 111, 33};
|
||||
|
||||
// Publishes the sequence of bytes on subject "foo".
|
||||
s = natsConnection_Publish(conn, "foo", data, sizeof(data));
|
||||
}
|
||||
|
||||
// Anything that is created need to be destroyed
|
||||
natsConnection_Destroy(conn);
|
||||
|
||||
// If there was an error, print a stack trace and exit
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
56
deps/nats.c/examples/getstarted/pubmsg.c
vendored
Normal file
56
deps/nats.c/examples/getstarted/pubmsg.c
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2017-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <nats.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsMsg *msg = NULL;
|
||||
natsStatus s;
|
||||
|
||||
printf("Publishes a message on subject 'foo'\n");
|
||||
|
||||
// Creates a connection to the default NATS URL
|
||||
s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
const char data[] = {104, 101, 108, 108, 111, 33};
|
||||
|
||||
// Creates a message for subject "foo", no reply, and
|
||||
// with the given payload.
|
||||
s = natsMsg_Create(&msg, "foo", NULL, data, sizeof(data));
|
||||
}
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
// Publishes the message on subject "foo".
|
||||
s = natsConnection_PublishMsg(conn, msg);
|
||||
}
|
||||
|
||||
// Anything that is created need to be destroyed
|
||||
natsMsg_Destroy(msg);
|
||||
natsConnection_Destroy(conn);
|
||||
|
||||
// If there was an error, print a stack trace and exit
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
47
deps/nats.c/examples/getstarted/pubstr.c
vendored
Normal file
47
deps/nats.c/examples/getstarted/pubstr.c
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright 2017-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <nats.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsStatus s;
|
||||
|
||||
printf("Publishes a message on subject 'foo'\n");
|
||||
|
||||
// Creates a connection to the default NATS URL
|
||||
s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
// This is a convenient function to send a message on "foo"
|
||||
// as a string.
|
||||
s = natsConnection_PublishString(conn, "foo", "hello!");
|
||||
}
|
||||
|
||||
// Anything that is created need to be destroyed
|
||||
natsConnection_Destroy(conn);
|
||||
|
||||
// If there was an error, print a stack trace and exit
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
76
deps/nats.c/examples/getstarted/replier.c
vendored
Normal file
76
deps/nats.c/examples/getstarted/replier.c
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright 2017-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <nats.h>
|
||||
|
||||
static void
|
||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||
{
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
// Sends a reply
|
||||
if (natsMsg_GetReply(msg) != NULL)
|
||||
{
|
||||
natsConnection_PublishString(nc, natsMsg_GetReply(msg),
|
||||
"here's some help");
|
||||
}
|
||||
|
||||
// Need to destroy the message!
|
||||
natsMsg_Destroy(msg);
|
||||
|
||||
// Notify the main thread that we are done.
|
||||
*(bool *)(closure) = true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsStatus s;
|
||||
volatile bool done = false;
|
||||
|
||||
printf("Listening for requests on subject 'help'\n");
|
||||
|
||||
// Creates a connection to the default NATS URL
|
||||
s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
// Creates an asynchronous subscription on subject "help",
|
||||
// waiting for a request. If a message arrives on this
|
||||
// subject, the callback onMsg() will be invoked and it
|
||||
// will send a reply.
|
||||
s = natsConnection_Subscribe(&sub, conn, "help", onMsg, (void*) &done);
|
||||
}
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
for (;!done;) {
|
||||
nats_Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
// Anything that is created need to be destroyed
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
|
||||
// If there was an error, print a stack trace and exit
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
60
deps/nats.c/examples/getstarted/requestor.c
vendored
Normal file
60
deps/nats.c/examples/getstarted/requestor.c
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2017-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <nats.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsMsg *reply= NULL;
|
||||
natsStatus s;
|
||||
|
||||
printf("Publishes a message on subject 'help'\n");
|
||||
|
||||
// Creates a connection to the default NATS URL
|
||||
s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
// Sends a request on "help" and expects a reply.
|
||||
// Will wait only for a given number of milliseconds,
|
||||
// say for 5 seconds in this example.
|
||||
s = natsConnection_RequestString(&reply, conn, "help",
|
||||
"really need some", 5000);
|
||||
}
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
// If we are here, we should have received the reply
|
||||
printf("Received reply: %.*s\n",
|
||||
natsMsg_GetDataLength(reply),
|
||||
natsMsg_GetData(reply));
|
||||
|
||||
// Need to destroy the message!
|
||||
natsMsg_Destroy(reply);
|
||||
}
|
||||
|
||||
// Anything that is created need to be destroyed
|
||||
natsConnection_Destroy(conn);
|
||||
|
||||
// If there was an error, print a stack trace and exit
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
64
deps/nats.c/examples/getstarted/syncsub.c
vendored
Normal file
64
deps/nats.c/examples/getstarted/syncsub.c
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright 2017-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <nats.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsMsg *msg = NULL;
|
||||
natsStatus s;
|
||||
|
||||
printf("Listening on subject 'foo'\n");
|
||||
|
||||
// Creates a connection to the default NATS URL
|
||||
s = natsConnection_ConnectTo(&conn, NATS_DEFAULT_URL);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
// Creates an synchronous subscription on subject "foo".
|
||||
s = natsConnection_SubscribeSync(&sub, conn, "foo");
|
||||
}
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
// With synchronous subscriptions, one need to poll
|
||||
// using this function. A timeout is used to instruct
|
||||
// how long we are willing to wait. The wait is in milliseconds.
|
||||
// So here, we are going to wait for 5 seconds.
|
||||
s = natsSubscription_NextMsg(&msg, sub, 5000);
|
||||
}
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
// If we are here, we should have received a message.
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
// Need to destroy the message!
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
|
||||
// Anything that is created need to be destroyed
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
|
||||
// If there was an error, print a stack trace and exit
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
201
deps/nats.c/examples/js-pub.c
vendored
Normal file
201
deps/nats.c/examples/js-pub.c
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
// Copyright 2021 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-stream stream name (default is 'foo')\n" \
|
||||
"-txt text to send (default is 'hello')\n" \
|
||||
"-count number of messages to send\n" \
|
||||
"-sync publish synchronously (default is async)\n";
|
||||
|
||||
static void
|
||||
_jsPubErr(jsCtx *js, jsPubAckErr *pae, void *closure)
|
||||
{
|
||||
int *errors = (int*) closure;
|
||||
|
||||
printf("Error: %u - Code: %u - Text: %s\n", pae->Err, pae->ErrCode, pae->ErrText);
|
||||
printf("Original message: %.*s\n", natsMsg_GetDataLength(pae->Msg), natsMsg_GetData(pae->Msg));
|
||||
|
||||
*errors = (*errors + 1);
|
||||
|
||||
// If we wanted to resend the original message, we would do something like that:
|
||||
//
|
||||
// js_PublishMsgAsync(js, &(pae->Msg), NULL);
|
||||
//
|
||||
// Note that we use `&(pae->Msg)` so that the library set it to NULL if it takes
|
||||
// ownership, and the library will not destroy the message when this callback returns.
|
||||
|
||||
// No need to destroy anything, everything is handled by the library.
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsStatistics *stats = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
jsCtx *js = NULL;
|
||||
jsOptions jsOpts;
|
||||
jsErrCode jerr = 0;
|
||||
natsStatus s;
|
||||
int dataLen=0;
|
||||
volatile int errors = 0;
|
||||
bool delStream = false;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
dataLen = (int) strlen(payload);
|
||||
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = jsOptions_Init(&jsOpts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (async)
|
||||
{
|
||||
jsOpts.PublishAsync.ErrHandler = _jsPubErr;
|
||||
jsOpts.PublishAsync.ErrHandlerClosure = (void*) &errors;
|
||||
}
|
||||
s = natsConnection_JetStream(&js, conn, &jsOpts);
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
jsStreamInfo *si = NULL;
|
||||
|
||||
// First check if the stream already exists.
|
||||
s = js_GetStreamInfo(&si, js, stream, NULL, &jerr);
|
||||
if (s == NATS_NOT_FOUND)
|
||||
{
|
||||
jsStreamConfig cfg;
|
||||
|
||||
// Since we are the one creating this stream, we can delete at the end.
|
||||
delStream = true;
|
||||
|
||||
// Initialize the configuration structure.
|
||||
jsStreamConfig_Init(&cfg);
|
||||
cfg.Name = stream;
|
||||
// Set the subject
|
||||
cfg.Subjects = (const char*[1]){subj};
|
||||
cfg.SubjectsLen = 1;
|
||||
// Make it a memory stream.
|
||||
cfg.Storage = js_MemoryStorage;
|
||||
// Add the stream,
|
||||
s = js_AddStream(&si, js, &cfg, NULL, &jerr);
|
||||
}
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printf("Stream %s has %" PRIu64 " messages (%" PRIu64 " bytes)\n",
|
||||
si->Config->Name, si->State.Msgs, si->State.Bytes);
|
||||
|
||||
// Need to destroy the returned stream object.
|
||||
jsStreamInfo_Destroy(si);
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsStatistics_Create(&stats);
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printf("\nSending %" PRId64 " messages to subject '%s'\n", total, stream);
|
||||
start = nats_Now();
|
||||
}
|
||||
|
||||
for (count = 0; (s == NATS_OK) && (count < total); count++)
|
||||
{
|
||||
if (async)
|
||||
s = js_PublishAsync(js, subj, (const void*) payload, dataLen, NULL);
|
||||
else
|
||||
{
|
||||
jsPubAck *pa = NULL;
|
||||
|
||||
s = js_Publish(&pa, js, subj, (const void*) payload, dataLen, NULL, &jerr);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (pa->Duplicate)
|
||||
printf("Got a duplicate message! Sequence=%" PRIu64 "\n", pa->Sequence);
|
||||
|
||||
jsPubAck_Destroy(pa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((s == NATS_OK) && async)
|
||||
{
|
||||
jsPubOptions jsPubOpts;
|
||||
|
||||
jsPubOptions_Init(&jsPubOpts);
|
||||
// Let's set it to 30 seconds, if getting "Timeout" errors,
|
||||
// this may need to be increased based on the number of messages
|
||||
// being sent.
|
||||
jsPubOpts.MaxWait = 30000;
|
||||
s = js_PublishAsyncComplete(js, &jsPubOpts);
|
||||
if (s == NATS_TIMEOUT)
|
||||
{
|
||||
// Let's get the list of pending messages. We could resend,
|
||||
// etc, but for now, just destroy them.
|
||||
natsMsgList list;
|
||||
|
||||
js_PublishAsyncGetPendingList(&list, js);
|
||||
natsMsgList_Destroy(&list);
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
jsStreamInfo *si = NULL;
|
||||
|
||||
elapsed = nats_Now() - start;
|
||||
printStats(STATS_OUT, conn, NULL, stats);
|
||||
printPerf("Sent");
|
||||
|
||||
if (errors != 0)
|
||||
printf("There were %d asynchronous errors\n", errors);
|
||||
|
||||
// Let's report some stats after the run
|
||||
s = js_GetStreamInfo(&si, js, stream, NULL, &jerr);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printf("\nStream %s has %" PRIu64 " messages (%" PRIu64 " bytes)\n",
|
||||
si->Config->Name, si->State.Msgs, si->State.Bytes);
|
||||
|
||||
jsStreamInfo_Destroy(si);
|
||||
}
|
||||
}
|
||||
if (delStream && (js != NULL))
|
||||
{
|
||||
printf("\nDeleting stream %s: ", stream);
|
||||
s = js_DeleteStream(js, stream, NULL, &jerr);
|
||||
if (s == NATS_OK)
|
||||
printf("OK!");
|
||||
printf("\n");
|
||||
}
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
printf("Error: %u - %s - jerr=%u\n", s, natsStatus_GetText(s), jerr);
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
jsCtx_Destroy(js);
|
||||
natsStatistics_Destroy(stats);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
236
deps/nats.c/examples/js-sub.c
vendored
Normal file
236
deps/nats.c/examples/js-sub.c
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
// Copyright 2021 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-gd use global message delivery thread pool\n" \
|
||||
"-sync receive synchronously (default is asynchronous)\n" \
|
||||
"-pull use pull subscription\n" \
|
||||
"-fc enable flow control\n" \
|
||||
"-count number of expected messages\n";
|
||||
|
||||
static void
|
||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||
{
|
||||
if (print)
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
// We should be using a mutex to protect those variables since
|
||||
// they are used from the subscription's delivery and the main
|
||||
// threads. For demo purposes, this is fine.
|
||||
if (++count == total)
|
||||
elapsed = nats_Now() - start;
|
||||
|
||||
// Since this is auto-ack callback, we don't need to ack here.
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
|
||||
static void
|
||||
asyncCb(natsConnection *nc, natsSubscription *sub, natsStatus err, void *closure)
|
||||
{
|
||||
printf("Async error: %u - %s\n", err, natsStatus_GetText(err));
|
||||
|
||||
natsSubscription_GetDropped(sub, (int64_t*) &dropped);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsStatistics *stats = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsMsg *msg = NULL;
|
||||
jsCtx *js = NULL;
|
||||
jsErrCode jerr = 0;
|
||||
jsOptions jsOpts;
|
||||
jsSubOptions so;
|
||||
natsStatus s;
|
||||
bool delStream = false;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Created %s subscription on '%s'.\n",
|
||||
(pull ? "pull" : (async ? "asynchronous" : "synchronous")), subj);
|
||||
|
||||
s = natsOptions_SetErrorHandler(opts, asyncCb, NULL);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = jsOptions_Init(&jsOpts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = jsSubOptions_Init(&so);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
so.Stream = stream;
|
||||
so.Consumer = durable;
|
||||
if (flowctrl)
|
||||
{
|
||||
so.Config.FlowControl = true;
|
||||
so.Config.Heartbeat = (int64_t)1E9;
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_JetStream(&js, conn, &jsOpts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
jsStreamInfo *si = NULL;
|
||||
|
||||
// First check if the stream already exists.
|
||||
s = js_GetStreamInfo(&si, js, stream, NULL, &jerr);
|
||||
if (s == NATS_NOT_FOUND)
|
||||
{
|
||||
jsStreamConfig cfg;
|
||||
|
||||
// Since we are the one creating this stream, we can delete at the end.
|
||||
delStream = true;
|
||||
|
||||
// Initialize the configuration structure.
|
||||
jsStreamConfig_Init(&cfg);
|
||||
cfg.Name = stream;
|
||||
// Set the subject
|
||||
cfg.Subjects = (const char*[1]){subj};
|
||||
cfg.SubjectsLen = 1;
|
||||
// Make it a memory stream.
|
||||
cfg.Storage = js_MemoryStorage;
|
||||
// Add the stream,
|
||||
s = js_AddStream(&si, js, &cfg, NULL, &jerr);
|
||||
}
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printf("Stream %s has %" PRIu64 " messages (%" PRIu64 " bytes)\n",
|
||||
si->Config->Name, si->State.Msgs, si->State.Bytes);
|
||||
|
||||
// Need to destroy the returned stream object.
|
||||
jsStreamInfo_Destroy(si);
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (pull)
|
||||
s = js_PullSubscribe(&sub, js, subj, durable, &jsOpts, &so, &jerr);
|
||||
else if (async)
|
||||
s = js_Subscribe(&sub, js, subj, onMsg, NULL, &jsOpts, &so, &jerr);
|
||||
else
|
||||
s = js_SubscribeSync(&sub, js, subj, &jsOpts, &so, &jerr);
|
||||
}
|
||||
if (s == NATS_OK)
|
||||
s = natsSubscription_SetPendingLimits(sub, -1, -1);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsStatistics_Create(&stats);
|
||||
|
||||
if ((s == NATS_OK) && pull)
|
||||
{
|
||||
natsMsgList list;
|
||||
int i;
|
||||
|
||||
for (count = 0; (s == NATS_OK) && (count < total); )
|
||||
{
|
||||
s = natsSubscription_Fetch(&list, sub, 1024, 5000, &jerr);
|
||||
if (s != NATS_OK)
|
||||
break;
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
count += (int64_t) list.Count;
|
||||
for (i=0; (s == NATS_OK) && (i<list.Count); i++)
|
||||
s = natsMsg_Ack(list.Msgs[i], &jsOpts);
|
||||
|
||||
natsMsgList_Destroy(&list);
|
||||
}
|
||||
}
|
||||
else if ((s == NATS_OK) && async)
|
||||
{
|
||||
while (s == NATS_OK)
|
||||
{
|
||||
if (count + dropped == total)
|
||||
break;
|
||||
|
||||
nats_Sleep(1000);
|
||||
}
|
||||
}
|
||||
else if (s == NATS_OK)
|
||||
{
|
||||
for (count = 0; (s == NATS_OK) && (count < total); count++)
|
||||
{
|
||||
s = natsSubscription_NextMsg(&msg, sub, 5000);
|
||||
if (s != NATS_OK)
|
||||
break;
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
s = natsMsg_Ack(msg, &jsOpts);
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printStats(STATS_IN|STATS_COUNT, conn, sub, stats);
|
||||
printPerf("Received");
|
||||
}
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
jsStreamInfo *si = NULL;
|
||||
|
||||
// Let's report some stats after the run
|
||||
s = js_GetStreamInfo(&si, js, stream, NULL, &jerr);
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printf("\nStream %s has %" PRIu64 " messages (%" PRIu64 " bytes)\n",
|
||||
si->Config->Name, si->State.Msgs, si->State.Bytes);
|
||||
|
||||
jsStreamInfo_Destroy(si);
|
||||
}
|
||||
if (delStream)
|
||||
{
|
||||
printf("\nDeleting stream %s: ", stream);
|
||||
s = js_DeleteStream(js, stream, NULL, &jerr);
|
||||
if (s == NATS_OK)
|
||||
printf("OK!");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %u - %s - jerr=%u\n", s, natsStatus_GetText(s), jerr);
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
jsCtx_Destroy(js);
|
||||
natsStatistics_Destroy(stats);
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
147
deps/nats.c/examples/libevent-pub.c
vendored
Normal file
147
deps/nats.c/examples/libevent-pub.c
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "adapters/libevent.h"
|
||||
#include "examples.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <pthread.h>
|
||||
#define THREAD_T pthread_t
|
||||
#define THREAD_FN void *
|
||||
#define THREAD_RETURN() return (NULL)
|
||||
#define THREAD_START(threadvar, fn, arg) \
|
||||
pthread_create(&(threadvar), NULL, fn, arg)
|
||||
#define THREAD_JOIN(th) pthread_join(th, NULL)
|
||||
#else
|
||||
#include <process.h>
|
||||
#define THREAD_T HANDLE
|
||||
#define THREAD_FN unsigned __stdcall
|
||||
#define THREAD_RETURN() return (0)
|
||||
#define THREAD_START(threadvar, fn, arg) do { \
|
||||
uintptr_t threadhandle = _beginthreadex(NULL,0,fn,(arg),0,NULL); \
|
||||
(threadvar) = (HANDLE) threadhandle; \
|
||||
} while (0)
|
||||
#define THREAD_JOIN(th) WaitForSingleObject(th, INFINITE)
|
||||
#endif
|
||||
|
||||
static const char *usage = ""\
|
||||
"-txt text to send (default is 'hello')\n" \
|
||||
"-count number of messages to send\n";
|
||||
|
||||
typedef struct
|
||||
{
|
||||
natsConnection *conn;
|
||||
natsStatus status;
|
||||
|
||||
} threadInfo;
|
||||
|
||||
static THREAD_FN
|
||||
pubThread(void *arg)
|
||||
{
|
||||
threadInfo *info = (threadInfo*) arg;
|
||||
natsStatus s = NATS_OK;
|
||||
|
||||
for (count = 0; (s == NATS_OK) && (count < total); count++)
|
||||
s = natsConnection_PublishString(info->conn, subj, payload);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Flush(info->conn);
|
||||
|
||||
natsConnection_Close(info->conn);
|
||||
|
||||
info->status = s;
|
||||
|
||||
if (s != NATS_OK)
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
|
||||
THREAD_RETURN();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsStatus s = NATS_OK;
|
||||
struct event_base *evLoop= NULL;
|
||||
THREAD_T pub;
|
||||
threadInfo info;
|
||||
|
||||
nats_Open(-1);
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Sending %" PRId64 " messages to subject '%s'\n", total, subj);
|
||||
|
||||
// One time initialization of things that we need.
|
||||
natsLibevent_Init();
|
||||
|
||||
// Create a loop.
|
||||
evLoop = event_base_new();
|
||||
if (evLoop == NULL)
|
||||
s = NATS_ERR;
|
||||
|
||||
// Indicate which loop and callbacks to use once connected.
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetEventLoop(opts, (void*) evLoop,
|
||||
natsLibevent_Attach,
|
||||
natsLibevent_Read,
|
||||
natsLibevent_Write,
|
||||
natsLibevent_Detach);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
start = nats_Now();
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
info.conn = conn;
|
||||
info.status = NATS_OK;
|
||||
|
||||
THREAD_START(pub, pubThread, (void*) &info);
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
event_base_dispatch(evLoop);
|
||||
|
||||
THREAD_JOIN(pub);
|
||||
s = info.status;
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printPerf("Sent");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %d - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
if (evLoop != NULL)
|
||||
event_base_free(evLoop);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
libevent_global_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
115
deps/nats.c/examples/libevent-sub.c
vendored
Normal file
115
deps/nats.c/examples/libevent-sub.c
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "adapters/libevent.h"
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-gd use global message delivery thread pool\n" \
|
||||
"-count number of expected messages\n";
|
||||
|
||||
static void
|
||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||
{
|
||||
if (print)
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
natsMsg_Destroy(msg);
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
// We should be using a mutex to protect those variables since
|
||||
// they are used from the subscription's delivery and the main
|
||||
// threads. For demo purposes, this is fine.
|
||||
if (++count == total)
|
||||
{
|
||||
elapsed = nats_Now() - start;
|
||||
|
||||
natsConnection_Close(nc);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsStatus s = NATS_OK;
|
||||
struct event_base *evLoop= NULL;
|
||||
|
||||
nats_Open(-1);
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Listening on '%s'.\n", subj);
|
||||
|
||||
// One time initialization of things that we need.
|
||||
natsLibevent_Init();
|
||||
|
||||
// Create a loop.
|
||||
evLoop = event_base_new();
|
||||
if (evLoop == NULL)
|
||||
s = NATS_ERR;
|
||||
|
||||
// Indicate which loop and callbacks to use once connected.
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetEventLoop(opts, (void*) evLoop,
|
||||
natsLibevent_Attach,
|
||||
natsLibevent_Read,
|
||||
natsLibevent_Write,
|
||||
natsLibevent_Detach);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Subscribe(&sub, conn, subj, onMsg, NULL);
|
||||
|
||||
// For maximum performance, set no limit on the number of pending messages.
|
||||
if (s == NATS_OK)
|
||||
s = natsSubscription_SetPendingLimits(sub, -1, -1);
|
||||
|
||||
// Run the event loop.
|
||||
// This call will return when the connection is closed (either after
|
||||
// receiving all messages, or disconnected and unable to reconnect).
|
||||
if (s == NATS_OK)
|
||||
event_base_dispatch(evLoop);
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printPerf("Received");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %d - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
if (evLoop != NULL)
|
||||
event_base_free(evLoop);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
libevent_global_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
135
deps/nats.c/examples/libuv-pub.c
vendored
Normal file
135
deps/nats.c/examples/libuv-pub.c
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "adapters/libuv.h"
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-txt text to send (default is 'hello')\n" \
|
||||
"-count number of messages to send\n";
|
||||
|
||||
typedef struct
|
||||
{
|
||||
natsConnection *conn;
|
||||
natsStatus status;
|
||||
|
||||
} threadInfo;
|
||||
|
||||
static void
|
||||
pubThread(void *arg)
|
||||
{
|
||||
threadInfo *info = (threadInfo*) arg;
|
||||
natsStatus s = NATS_OK;
|
||||
|
||||
for (count = 0; (s == NATS_OK) && (count < total); count++)
|
||||
s = natsConnection_PublishString(info->conn, subj, payload);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Flush(info->conn);
|
||||
|
||||
natsConnection_Close(info->conn);
|
||||
|
||||
info->status = s;
|
||||
|
||||
// Since this is a user-thread, call this function to release
|
||||
// possible thread-local memory allocated by the library.
|
||||
nats_ReleaseThreadMemory();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsStatus s = NATS_OK;
|
||||
uv_loop_t *uvLoop= NULL;
|
||||
uv_thread_t pub;
|
||||
threadInfo info;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Sending %" PRId64 " messages to subject '%s'\n", total, subj);
|
||||
|
||||
// One time initialization of things that we need.
|
||||
natsLibuv_Init();
|
||||
|
||||
// Create a loop.
|
||||
uvLoop = uv_default_loop();
|
||||
if (uvLoop != NULL)
|
||||
{
|
||||
// Libuv is not thread-safe. Almost all calls to libuv need to
|
||||
// occur from the thread where the loop is running. NATS library
|
||||
// may have to call into the event loop from different threads.
|
||||
// This call allows natsLibuv APIs to know if they are executing
|
||||
// from the event loop thread or not.
|
||||
natsLibuv_SetThreadLocalLoop(uvLoop);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = NATS_ERR;
|
||||
}
|
||||
|
||||
// Indicate which loop and callbacks to use once connected.
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetEventLoop(opts, (void*) uvLoop,
|
||||
natsLibuv_Attach,
|
||||
natsLibuv_Read,
|
||||
natsLibuv_Write,
|
||||
natsLibuv_Detach);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
start = nats_Now();
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
info.conn = conn;
|
||||
info.status = NATS_OK;
|
||||
|
||||
if (uv_thread_create(&pub, pubThread, (void*) &info) != 0)
|
||||
s = NATS_ERR;
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
uv_run(uvLoop, UV_RUN_DEFAULT);
|
||||
|
||||
uv_thread_join(&pub);
|
||||
s = info.status;
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printPerf("Sent");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %d - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
if (uvLoop != NULL)
|
||||
uv_loop_close(uvLoop);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
125
deps/nats.c/examples/libuv-sub.c
vendored
Normal file
125
deps/nats.c/examples/libuv-sub.c
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright 2016-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "adapters/libuv.h"
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-gd use global message delivery thread pool\n" \
|
||||
"-count number of expected messages\n";
|
||||
|
||||
static void
|
||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||
{
|
||||
if (print)
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
natsMsg_Destroy(msg);
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
// We should be using a mutex to protect those variables since
|
||||
// they are used from the subscription's delivery and the main
|
||||
// threads. For demo purposes, this is fine.
|
||||
if (++count == total)
|
||||
{
|
||||
elapsed = nats_Now() - start;
|
||||
|
||||
natsConnection_Close(nc);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsStatus s = NATS_OK;
|
||||
uv_loop_t *uvLoop= NULL;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Listening on '%s'.\n", subj);
|
||||
|
||||
// One time initialization of things that we need.
|
||||
natsLibuv_Init();
|
||||
|
||||
// Create a loop.
|
||||
uvLoop = uv_default_loop();
|
||||
if (uvLoop != NULL)
|
||||
{
|
||||
// Libuv is not thread-safe. Almost all calls to libuv need to
|
||||
// occur from the thread where the loop is running. NATS library
|
||||
// may have to call into the event loop from different threads.
|
||||
// This call allows natsLibuv APIs to know if they are executing
|
||||
// from the event loop thread or not.
|
||||
natsLibuv_SetThreadLocalLoop(uvLoop);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = NATS_ERR;
|
||||
}
|
||||
|
||||
// Indicate which loop and callbacks to use once connected.
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetEventLoop(opts, (void*) uvLoop,
|
||||
natsLibuv_Attach,
|
||||
natsLibuv_Read,
|
||||
natsLibuv_Write,
|
||||
natsLibuv_Detach);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Subscribe(&sub, conn, subj, onMsg, NULL);
|
||||
|
||||
// For maximum performance, set no limit on the number of pending messages.
|
||||
if (s == NATS_OK)
|
||||
s = natsSubscription_SetPendingLimits(sub, -1, -1);
|
||||
|
||||
// Run the event loop.
|
||||
// This call will return when the connection is closed (either after
|
||||
// receiving all messages, or disconnected and unable to reconnect).
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
uv_run(uvLoop, UV_RUN_DEFAULT);
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printPerf("Received");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %d - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
if (uvLoop != NULL)
|
||||
uv_loop_close(uvLoop);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
67
deps/nats.c/examples/publisher.c
vendored
Normal file
67
deps/nats.c/examples/publisher.c
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2015-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-txt text to send (default is 'hello')\n" \
|
||||
"-count number of messages to send\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsStatistics *stats = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsStatus s;
|
||||
int dataLen=0;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Sending %" PRId64 " messages to subject '%s'\n", total, subj);
|
||||
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsStatistics_Create(&stats);
|
||||
|
||||
if (s == NATS_OK)
|
||||
start = nats_Now();
|
||||
|
||||
dataLen = (int) strlen(payload);
|
||||
for (count = 0; (s == NATS_OK) && (count < total); count++)
|
||||
s = natsConnection_Publish(conn, subj, (const void*) payload, dataLen);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_FlushTimeout(conn, 1000);
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printStats(STATS_OUT, conn, NULL, stats);
|
||||
printPerf("Sent");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %u - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsStatistics_Destroy(stats);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
144
deps/nats.c/examples/queuegroup.c
vendored
Normal file
144
deps/nats.c/examples/queuegroup.c
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright 2015-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = "" \
|
||||
"-gd use global message delivery thread pool\n" \
|
||||
"-name queue name (default is 'worker')\n" \
|
||||
"-count number of expected messages\n";
|
||||
|
||||
static void
|
||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||
{
|
||||
// If 'print' is on, the server is likely to break the connection
|
||||
// since the client library will become a slow consumer.
|
||||
if (print)
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
// We should be using a mutex to protect those variables since
|
||||
// they are used from the subscription's delivery and the main
|
||||
// threads. For demo purposes, this is fine.
|
||||
if (++count == total)
|
||||
elapsed = nats_Now() - start;
|
||||
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
|
||||
static void
|
||||
asyncCb(natsConnection *nc, natsSubscription *sub, natsStatus err, void *closure)
|
||||
{
|
||||
printf("Async error: %u - %s\n", err, natsStatus_GetText(err));
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsStatistics *stats = NULL;
|
||||
natsMsg *msg = NULL;
|
||||
natsStatus s;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Listening %ssynchronously on '%s' with name '%s'.\n",
|
||||
(async ? "a" : ""), subj, name);
|
||||
|
||||
s = natsOptions_SetErrorHandler(opts, asyncCb, NULL);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (async)
|
||||
s = natsConnection_QueueSubscribe(&sub, conn, subj, name, onMsg, NULL);
|
||||
else
|
||||
s = natsConnection_QueueSubscribeSync(&sub, conn, subj, name);
|
||||
}
|
||||
|
||||
// For maximum performance, set no limit on the number of pending messages.
|
||||
if (s == NATS_OK)
|
||||
s = natsSubscription_SetPendingLimits(sub, -1, -1);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsSubscription_AutoUnsubscribe(sub, (int) total);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsStatistics_Create(&stats);
|
||||
|
||||
if ((s == NATS_OK) && async)
|
||||
{
|
||||
while (s == NATS_OK)
|
||||
{
|
||||
s = printStats(STATS_IN|STATS_COUNT,conn, sub, stats);
|
||||
|
||||
if (count == total)
|
||||
break;
|
||||
|
||||
if (s == NATS_OK)
|
||||
nats_Sleep(1000);
|
||||
}
|
||||
}
|
||||
else if (s == NATS_OK)
|
||||
{
|
||||
int64_t last = 0;
|
||||
|
||||
for (count = 0; (s == NATS_OK) && (count < total); count++)
|
||||
{
|
||||
s = natsSubscription_NextMsg(&msg, sub, 10000);
|
||||
if (s != NATS_OK)
|
||||
break;
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
if (nats_Now() - last >= 1000)
|
||||
{
|
||||
s = printStats(STATS_IN|STATS_COUNT,conn, sub, stats);
|
||||
last = nats_Now();
|
||||
}
|
||||
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printStats(STATS_IN|STATS_COUNT,conn, sub, stats);
|
||||
printPerf("Received");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %u - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsStatistics_Destroy(stats);
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
160
deps/nats.c/examples/replier.c
vendored
Normal file
160
deps/nats.c/examples/replier.c
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright 2015-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = "" \
|
||||
"-gd use global message delivery thread pool\n" \
|
||||
"-sync receive synchronously (default is asynchronous)\n" \
|
||||
"-count number of expected requests\n";
|
||||
|
||||
static void
|
||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||
{
|
||||
if (print)
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
natsConnection_PublishString(nc, natsMsg_GetReply(msg),
|
||||
"here's some help");
|
||||
|
||||
// We should be using a mutex to protect those variables since
|
||||
// they are used from the subscription's delivery and the main
|
||||
// threads. For demo purposes, this is fine.
|
||||
if (++count == total)
|
||||
elapsed = nats_Now() - start;
|
||||
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
|
||||
static void
|
||||
asyncCb(natsConnection *nc, natsSubscription *sub, natsStatus err, void *closure)
|
||||
{
|
||||
if (print)
|
||||
printf("Async error: %u - %s\n", err, natsStatus_GetText(err));
|
||||
|
||||
natsSubscription_GetDropped(sub, (int64_t*) &dropped);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsStatistics *stats = NULL;
|
||||
natsMsg *msg = NULL;
|
||||
natsStatus s;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Listening %ssynchronously for requests on '%s'\n",
|
||||
(async ? "a" : ""), subj);
|
||||
|
||||
s = natsOptions_SetErrorHandler(opts, asyncCb, NULL);
|
||||
// Since the replier is sending one message at a time, reduce
|
||||
// latency by making Publish calls send data right away
|
||||
// instead of buffering them.
|
||||
if (s == NATS_OK)
|
||||
s = natsOptions_SetSendAsap(opts, true);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (async)
|
||||
s = natsConnection_Subscribe(&sub, conn, subj, onMsg, NULL);
|
||||
else
|
||||
s = natsConnection_SubscribeSync(&sub, conn, subj);
|
||||
}
|
||||
|
||||
// For maximum performance, set no limit on the number of pending messages.
|
||||
if (s == NATS_OK)
|
||||
s = natsSubscription_SetPendingLimits(sub, -1, -1);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsSubscription_AutoUnsubscribe(sub, (int) total);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsStatistics_Create(&stats);
|
||||
|
||||
if ((s == NATS_OK) && async)
|
||||
{
|
||||
while (s == NATS_OK)
|
||||
{
|
||||
s = printStats(STATS_IN|STATS_COUNT,conn, sub, stats);
|
||||
|
||||
if (count + dropped == total)
|
||||
break;
|
||||
|
||||
if (s == NATS_OK)
|
||||
nats_Sleep(1000);
|
||||
}
|
||||
}
|
||||
else if (s == NATS_OK)
|
||||
{
|
||||
int64_t last = 0;
|
||||
|
||||
for (count = 0; (s == NATS_OK) && (count < total); count++)
|
||||
{
|
||||
s = natsSubscription_NextMsg(&msg, sub, 10000);
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_PublishString(conn,
|
||||
natsMsg_GetReply(msg),
|
||||
"here's some help");
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
if (nats_Now() - last >= 1000)
|
||||
{
|
||||
s = printStats(STATS_IN|STATS_COUNT,conn, sub, stats);
|
||||
last = nats_Now();
|
||||
}
|
||||
}
|
||||
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_FlushTimeout(conn, 1000);
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printStats(STATS_IN|STATS_COUNT,conn, sub, stats);
|
||||
printPerf("Received");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %u - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsStatistics_Destroy(stats);
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
87
deps/nats.c/examples/requestor.c
vendored
Normal file
87
deps/nats.c/examples/requestor.c
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright 2015-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = "" \
|
||||
"-txt text to send (default is 'hello')\n" \
|
||||
"-count number of requests to send\n";
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsStatistics *stats = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsMsg *reply = NULL;
|
||||
int64_t last = 0;
|
||||
natsStatus s;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Sending %" PRId64 " requests to subject '%s'\n", total, subj);
|
||||
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsStatistics_Create(&stats);
|
||||
|
||||
if (s == NATS_OK)
|
||||
start = nats_Now();
|
||||
|
||||
for (count = 0; (s == NATS_OK) && (count < total); count++)
|
||||
{
|
||||
s = natsConnection_RequestString(&reply, conn, subj, payload, 1000);
|
||||
if (s != NATS_OK)
|
||||
break;
|
||||
|
||||
if (print)
|
||||
{
|
||||
printf("Received reply: %s - %.*s\n",
|
||||
natsMsg_GetSubject(reply),
|
||||
natsMsg_GetDataLength(reply),
|
||||
natsMsg_GetData(reply));
|
||||
}
|
||||
|
||||
if (nats_Now() - last >= 1000)
|
||||
{
|
||||
s = printStats(STATS_OUT,conn, NULL, stats);
|
||||
last = nats_Now();
|
||||
}
|
||||
|
||||
natsMsg_Destroy(reply);
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_FlushTimeout(conn, 1000);
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printStats(STATS_OUT, conn, NULL, stats);
|
||||
printPerf("Sent");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %u - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsStatistics_Destroy(stats);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
29
deps/nats.c/examples/stan/CMakeLists.txt
vendored
Normal file
29
deps/nats.c/examples/stan/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
if(NOT NATS_BUILD_EXAMPLES)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# We need this directory to build the examples
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/examples/stan)
|
||||
|
||||
# Get all the .c files in the examples directory
|
||||
file(GLOB EXAMPLES_SOURCES RELATIVE ${PROJECT_SOURCE_DIR}/examples/stan *.c)
|
||||
|
||||
# For each file...
|
||||
foreach(examples_src ${EXAMPLES_SOURCES})
|
||||
|
||||
# Remove the suffix so that it becomes the executable name
|
||||
string(REPLACE ".c" "" examplename ${examples_src})
|
||||
set(exampleexe "stan-${examplename}")
|
||||
|
||||
# Build the executable
|
||||
add_executable(${exampleexe} ${PROJECT_SOURCE_DIR}/examples/stan/${examples_src})
|
||||
|
||||
# Link
|
||||
if(NATS_BUILD_STATIC_EXAMPLES)
|
||||
target_link_libraries(${exampleexe} nats_static ${NATS_EXTRA_LIB})
|
||||
else()
|
||||
target_link_libraries(${exampleexe} nats ${NATS_EXTRA_LIB})
|
||||
endif()
|
||||
|
||||
endforeach()
|
127
deps/nats.c/examples/stan/pub-async.c
vendored
Normal file
127
deps/nats.c/examples/stan/pub-async.c
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright 2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "../examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-txt text to send (default is 'hello')\n";
|
||||
|
||||
typedef struct __myPubMsgInfo
|
||||
{
|
||||
const char *payload;
|
||||
int size;
|
||||
char ID[30];
|
||||
|
||||
} myPubMsgInfo;
|
||||
|
||||
static volatile bool done = false;
|
||||
|
||||
static void
|
||||
_pubAckHandler(const char *guid, const char *error, void *closure)
|
||||
{
|
||||
myPubMsgInfo *pubMsg = (myPubMsgInfo*) closure;
|
||||
|
||||
printf("Ack handler for message ID=%s Data=%.*s GUID=%s - ",
|
||||
pubMsg->ID, pubMsg->size, pubMsg->payload, guid);
|
||||
|
||||
if (error != NULL)
|
||||
printf("Error= %s\n", error);
|
||||
else
|
||||
printf("Success!\n");
|
||||
|
||||
// This is a good place to free the pubMsg info since
|
||||
// we no longer need it.
|
||||
free(pubMsg);
|
||||
|
||||
// Notify the main thread that we are done. This is
|
||||
// not the proper way and you should use some locking.
|
||||
done = true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsStatus s;
|
||||
stanConnOptions *connOpts = NULL;
|
||||
stanConnection *sc = NULL;
|
||||
myPubMsgInfo *pubMsg = NULL;
|
||||
|
||||
// This example demonstrates the use of the pubAckHandler closure
|
||||
// to correlate published messages and their acks.
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Sending 1 message to channel '%s'\n", subj);
|
||||
|
||||
// Now create STAN Connection Options and set the NATS Options.
|
||||
s = stanConnOptions_Create(&connOpts);
|
||||
if (s == NATS_OK)
|
||||
s = stanConnOptions_SetNATSOptions(connOpts, opts);
|
||||
|
||||
// Create the Connection using the STAN Connection Options
|
||||
if (s == NATS_OK)
|
||||
s = stanConnection_Connect(&sc, cluster, clientID, connOpts);
|
||||
|
||||
// Once the connection is created, we can destroy the options
|
||||
natsOptions_Destroy(opts);
|
||||
stanConnOptions_Destroy(connOpts);
|
||||
|
||||
// Create an object that represents our message
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
pubMsg = (myPubMsgInfo*) calloc(1, sizeof(myPubMsgInfo));
|
||||
if (pubMsg == NULL)
|
||||
s = NATS_NO_MEMORY;
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
// Say we want to bind the data that we are going to send
|
||||
// to some unique ID that we know about this message.
|
||||
pubMsg->payload = payload;
|
||||
pubMsg->size = (int)strlen(payload);
|
||||
snprintf(pubMsg->ID, sizeof(pubMsg->ID), "%s:%d", "xyz", 234);
|
||||
}
|
||||
}
|
||||
// We send the message and pass our message info as the closure
|
||||
// for the pubAckHandler.
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
s = stanConnection_PublishAsync(sc, subj, pubMsg->payload, pubMsg->size,
|
||||
_pubAckHandler, (void*) pubMsg);
|
||||
|
||||
// Note that if this call fails, then we need to free the pubMsg
|
||||
// object here since it won't be passed to the ack handler.
|
||||
if (s != NATS_OK)
|
||||
free(pubMsg);
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
while (!done)
|
||||
nats_Sleep(15);
|
||||
}
|
||||
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
printf("Error: %d - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy the connection
|
||||
stanConnection_Destroy(sc);
|
||||
|
||||
// To silence reports of memory still in-use with valgrind.
|
||||
nats_Sleep(50);
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
143
deps/nats.c/examples/stan/pub.c
vendored
Normal file
143
deps/nats.c/examples/stan/pub.c
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright 2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "../examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-txt text to send (default is 'hello')\n" \
|
||||
"-count number of messages to send\n" \
|
||||
"-sync publish synchronously (default is async)\n";
|
||||
|
||||
static volatile int ackCount = 0;
|
||||
static volatile int errCount = 0;
|
||||
|
||||
static void
|
||||
_pubAckHandler(const char *guid, const char *error, void *closure)
|
||||
{
|
||||
// This callback can be invoked by different threads for the
|
||||
// same connection, so access should be protected. For this
|
||||
// example, we don't.
|
||||
ackCount++;
|
||||
if (error != NULL)
|
||||
{
|
||||
printf("pub ack for guid:%s error=%s\n", guid, error);
|
||||
errCount++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
connectionLostCB(stanConnection *sc, const char *errTxt, void *closure)
|
||||
{
|
||||
bool *connLost = (bool*) closure;
|
||||
|
||||
printf("Connection lost: %s\n", errTxt);
|
||||
*connLost = true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsStatus s;
|
||||
stanConnOptions *connOpts = NULL;
|
||||
stanConnection *sc = NULL;
|
||||
int len;
|
||||
bool connLost = false;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
len = (int) strlen(payload);
|
||||
|
||||
printf("Sending %" PRId64 " messages to channel '%s'\n", total, subj);
|
||||
|
||||
// Now create STAN Connection Options and set the NATS Options.
|
||||
s = stanConnOptions_Create(&connOpts);
|
||||
if (s == NATS_OK)
|
||||
s = stanConnOptions_SetNATSOptions(connOpts, opts);
|
||||
|
||||
// Set smaller ping intervals
|
||||
if (s == NATS_OK)
|
||||
s = stanConnOptions_SetPings(connOpts, 1, 5);
|
||||
|
||||
// Add a callback to be notified if the STAN connection is lost for good.
|
||||
if (s == NATS_OK)
|
||||
s = stanConnOptions_SetConnectionLostHandler(connOpts, connectionLostCB, (void*)&connLost);
|
||||
|
||||
/*
|
||||
// To reduce MaxPubAcksInflight to 1000 and factor of 1.0
|
||||
if (s == NATS_OK)
|
||||
s = stanConnOptions_SetMaxPubAcksInflight(connOpts, 1000, 1.0);
|
||||
*/
|
||||
|
||||
// Create the Connection using the STAN Connection Options
|
||||
if (s == NATS_OK)
|
||||
s = stanConnection_Connect(&sc, cluster, clientID, connOpts);
|
||||
|
||||
// Once the connection is created, we can destroy the options
|
||||
natsOptions_Destroy(opts);
|
||||
stanConnOptions_Destroy(connOpts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
start = nats_Now();
|
||||
|
||||
for (count = 0; (s == NATS_OK) && (count < total); count++)
|
||||
{
|
||||
if (async)
|
||||
s = stanConnection_PublishAsync(sc, subj, (const void*) payload, len, _pubAckHandler, NULL);
|
||||
else
|
||||
s = stanConnection_Publish(sc, subj, (const void*) payload, len);
|
||||
}
|
||||
|
||||
if (!connLost && (s == NATS_OK))
|
||||
{
|
||||
if (async)
|
||||
{
|
||||
while (ackCount != total)
|
||||
nats_Sleep(15);
|
||||
}
|
||||
|
||||
printPerf("Sent");
|
||||
printf("Publish ack received: %d - with error: %d\n", ackCount, errCount);
|
||||
}
|
||||
|
||||
// If the connection was created, try to close it
|
||||
if (!connLost && (sc != NULL))
|
||||
{
|
||||
natsStatus closeSts = stanConnection_Close(sc);
|
||||
|
||||
if ((s == NATS_OK) && (closeSts != NATS_OK))
|
||||
s = closeSts;
|
||||
}
|
||||
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
// If we finished before the end, let's wait a tiny
|
||||
// bit to see if the failure is due to connection lost.
|
||||
if (ackCount != total)
|
||||
nats_Sleep(100);
|
||||
|
||||
// If connection was lost, the real reason is reported
|
||||
// the the connectionLostCB callback.
|
||||
if (!connLost)
|
||||
{
|
||||
printf("Error: %d - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy the connection
|
||||
stanConnection_Destroy(sc);
|
||||
|
||||
// To silence reports of memory still in-use with valgrind.
|
||||
nats_Sleep(50);
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
235
deps/nats.c/examples/stan/sub.c
vendored
Normal file
235
deps/nats.c/examples/stan/sub.c
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
// Copyright 2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "../examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-c cluster name (default \"test-cluster\")\n" \
|
||||
"-id client ID (default \"client\"\n" \
|
||||
"-count number of messages to receive\n" \
|
||||
"-last deliver starting with last published message (default)\n" \
|
||||
"-all deliver all available messages\n" \
|
||||
"-seq deliver starting at given sequence number\n" \
|
||||
"-durable durable subscription name\n" \
|
||||
"-qgroup queue group name\n" \
|
||||
"-unsubscribe unsubscribe the durable on exit\n";
|
||||
|
||||
static volatile bool done = false;
|
||||
|
||||
static void
|
||||
onMsg(stanConnection *sc, stanSubscription *sub, const char *channel, stanMsg *msg, void *closure)
|
||||
{
|
||||
if (print)
|
||||
printf("Received on [%s]: sequence:%" PRIu64 " data:%.*s timestamp:%" PRId64 " redelivered: %s\n",
|
||||
channel,
|
||||
stanMsg_GetSequence(msg),
|
||||
stanMsg_GetDataLength(msg),
|
||||
stanMsg_GetData(msg),
|
||||
stanMsg_GetTimestamp(msg),
|
||||
stanMsg_IsRedelivered(msg) ? "yes" : "no");
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
// We should be using a mutex to protect those variables since
|
||||
// they are used from the subscription's delivery and the main
|
||||
// threads. For demo purposes, this is fine.
|
||||
if (count == total-1)
|
||||
{
|
||||
natsStatus s;
|
||||
|
||||
elapsed = nats_Now() - start;
|
||||
|
||||
if (unsubscribe)
|
||||
s = stanSubscription_Unsubscribe(sub);
|
||||
else
|
||||
s = stanSubscription_Close(sub);
|
||||
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
printf("Error: %d - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// If manual acknowledgment was selected, we would acknowledge
|
||||
// the message this way:
|
||||
stanSubscription_AckMsg(sub, msg);
|
||||
*/
|
||||
|
||||
stanMsg_Destroy(msg);
|
||||
|
||||
// Increment only here so that when the main thread detects
|
||||
// that the total has been sent, it does not start cleaning
|
||||
// objects before we have closed the subscription and destroyed
|
||||
// the last message. This is to reduce risk of valgrind reporting
|
||||
// memory still in-use.
|
||||
count++;
|
||||
}
|
||||
|
||||
#if WIN32
|
||||
static BOOL
|
||||
sigHandler(DWORD fdwCtrlType)
|
||||
{
|
||||
if (fdwCtrlType==CTRL_C_EVENT)
|
||||
{
|
||||
done = true;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
static void
|
||||
sigHandler(int ignored) {
|
||||
done = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
connectionLostCB(stanConnection *sc, const char *errTxt, void *closure)
|
||||
{
|
||||
bool *connLost = (bool*) closure;
|
||||
|
||||
printf("Connection lost: %s\n", errTxt);
|
||||
*connLost = true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsStatus s;
|
||||
stanConnOptions *connOpts = NULL;
|
||||
stanSubOptions *subOpts = NULL;
|
||||
stanConnection *sc = NULL;
|
||||
stanSubscription *sub = NULL;
|
||||
bool connLost = false;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Receiving %" PRId64 " messages from channel '%s'\n", total, subj);
|
||||
|
||||
// Now create STAN Connection Options and set the NATS Options.
|
||||
s = stanConnOptions_Create(&connOpts);
|
||||
if (s == NATS_OK)
|
||||
s = stanConnOptions_SetNATSOptions(connOpts, opts);
|
||||
|
||||
// Add a callback to be notified if the STAN connection is lost for good.
|
||||
if (s == NATS_OK)
|
||||
s = stanConnOptions_SetConnectionLostHandler(connOpts, connectionLostCB, (void*)&connLost);
|
||||
|
||||
// Create the Connection using the STAN Connection Options
|
||||
if (s == NATS_OK)
|
||||
s = stanConnection_Connect(&sc, cluster, clientID, connOpts);
|
||||
|
||||
// Once connection is created, we can destroy opts and connOpts
|
||||
natsOptions_Destroy(opts);
|
||||
stanConnOptions_Destroy(connOpts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = stanSubOptions_Create(&subOpts);
|
||||
|
||||
// If durable
|
||||
if ((s == NATS_OK) && (durable != NULL))
|
||||
s = stanSubOptions_SetDurableName(subOpts, durable);
|
||||
|
||||
// Set position
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (deliverAll)
|
||||
s = stanSubOptions_DeliverAllAvailable(subOpts);
|
||||
else if (deliverLast)
|
||||
s = stanSubOptions_StartWithLastReceived(subOpts);
|
||||
else if (deliverSeq > 0)
|
||||
s = stanSubOptions_StartAtSequence(subOpts, deliverSeq);
|
||||
}
|
||||
|
||||
/*
|
||||
// To manually acknowledge the messages, you would need to set this option
|
||||
if (s == NATS_OK)
|
||||
s = stanSubOptions_SetManualAckMode(subOpts, true);
|
||||
|
||||
// To change the number of MaxInflight messages, set this option.
|
||||
// For instance, to receive a single message between each ACK, set
|
||||
// the value to 1.
|
||||
if (s == NATS_OK)
|
||||
s = stanSubOptions_SetMaxInflight(subOpts, 1);
|
||||
|
||||
// To change the duration after which the server resends unacknowledged
|
||||
// messages, use this option. For instance, cause re-delivery after 5 seconds:
|
||||
if (s == NATS_OK)
|
||||
s = stanSubOptions_SetAckWait(subOpts, 5000);
|
||||
*/
|
||||
|
||||
// Create subscription
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (qgroup != NULL)
|
||||
s = stanConnection_QueueSubscribe(&sub, sc, subj, qgroup, onMsg, NULL, subOpts);
|
||||
else
|
||||
s = stanConnection_Subscribe(&sub, sc, subj, onMsg, NULL, subOpts);
|
||||
}
|
||||
|
||||
// Once subscription is created, we can destroy the subOpts object
|
||||
stanSubOptions_Destroy(subOpts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
#if WIN32
|
||||
SetConsoleCtrlHandler((PHANDLER_ROUTINE) sigHandler, TRUE);
|
||||
#else
|
||||
signal(SIGINT, sigHandler);
|
||||
#endif
|
||||
|
||||
while (!done && !connLost && (count < total))
|
||||
nats_Sleep(15);
|
||||
|
||||
if (!connLost)
|
||||
printPerf("Received");
|
||||
}
|
||||
|
||||
// If test was interrupted before receiving all expected messages,
|
||||
// close or unsubscribe. Otherwise, this is done in the message
|
||||
// callback.
|
||||
if (!connLost && ((sub != NULL) && (count < total)))
|
||||
{
|
||||
if (unsubscribe)
|
||||
s = stanSubscription_Unsubscribe(sub);
|
||||
else
|
||||
s = stanSubscription_Close(sub);
|
||||
}
|
||||
|
||||
// If the connection was created, try to close it
|
||||
if (!connLost && (sc != NULL))
|
||||
{
|
||||
natsStatus closeSts = stanConnection_Close(sc);
|
||||
|
||||
if ((s == NATS_OK) && (closeSts != NATS_OK))
|
||||
s = closeSts;
|
||||
}
|
||||
|
||||
if (s != NATS_OK)
|
||||
{
|
||||
printf("Error: %d - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy our objects
|
||||
stanSubscription_Destroy(sub);
|
||||
stanConnection_Destroy(sc);
|
||||
|
||||
// To silence reports of memory still in-use with valgrind.
|
||||
nats_Sleep(50);
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
145
deps/nats.c/examples/subscriber.c
vendored
Normal file
145
deps/nats.c/examples/subscriber.c
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright 2015-2018 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "examples.h"
|
||||
|
||||
static const char *usage = ""\
|
||||
"-gd use global message delivery thread pool\n" \
|
||||
"-sync receive synchronously (default is asynchronous)\n" \
|
||||
"-count number of expected messages\n";
|
||||
|
||||
static void
|
||||
onMsg(natsConnection *nc, natsSubscription *sub, natsMsg *msg, void *closure)
|
||||
{
|
||||
if (print)
|
||||
printf("Received msg: %s - %.*s\n",
|
||||
natsMsg_GetSubject(msg),
|
||||
natsMsg_GetDataLength(msg),
|
||||
natsMsg_GetData(msg));
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
// We should be using a mutex to protect those variables since
|
||||
// they are used from the subscription's delivery and the main
|
||||
// threads. For demo purposes, this is fine.
|
||||
if (++count == total)
|
||||
elapsed = nats_Now() - start;
|
||||
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
|
||||
static void
|
||||
asyncCb(natsConnection *nc, natsSubscription *sub, natsStatus err, void *closure)
|
||||
{
|
||||
if (print)
|
||||
printf("Async error: %u - %s\n", err, natsStatus_GetText(err));
|
||||
|
||||
natsSubscription_GetDropped(sub, (int64_t*) &dropped);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
natsConnection *conn = NULL;
|
||||
natsOptions *opts = NULL;
|
||||
natsSubscription *sub = NULL;
|
||||
natsStatistics *stats = NULL;
|
||||
natsMsg *msg = NULL;
|
||||
natsStatus s;
|
||||
|
||||
opts = parseArgs(argc, argv, usage);
|
||||
|
||||
printf("Listening %ssynchronously on '%s'.\n",
|
||||
(async ? "a" : ""), subj);
|
||||
|
||||
s = natsOptions_SetErrorHandler(opts, asyncCb, NULL);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsConnection_Connect(&conn, opts);
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
if (async)
|
||||
s = natsConnection_Subscribe(&sub, conn, subj, onMsg, NULL);
|
||||
else
|
||||
s = natsConnection_SubscribeSync(&sub, conn, subj);
|
||||
}
|
||||
|
||||
// For maximum performance, set no limit on the number of pending messages.
|
||||
if (s == NATS_OK)
|
||||
s = natsSubscription_SetPendingLimits(sub, -1, -1);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsSubscription_AutoUnsubscribe(sub, (int) total);
|
||||
|
||||
if (s == NATS_OK)
|
||||
s = natsStatistics_Create(&stats);
|
||||
|
||||
if ((s == NATS_OK) && async)
|
||||
{
|
||||
while (s == NATS_OK)
|
||||
{
|
||||
s = printStats(STATS_IN|STATS_COUNT, conn, sub, stats);
|
||||
|
||||
if (count + dropped == total)
|
||||
break;
|
||||
|
||||
if (s == NATS_OK)
|
||||
nats_Sleep(1000);
|
||||
}
|
||||
}
|
||||
else if (s == NATS_OK)
|
||||
{
|
||||
int64_t last = 0;
|
||||
|
||||
for (count = 0; (s == NATS_OK) && (count < total); count++)
|
||||
{
|
||||
s = natsSubscription_NextMsg(&msg, sub, 10000);
|
||||
if (s != NATS_OK)
|
||||
break;
|
||||
|
||||
if (start == 0)
|
||||
start = nats_Now();
|
||||
|
||||
if (nats_Now() - last >= 1000)
|
||||
{
|
||||
s = printStats(STATS_IN|STATS_COUNT, conn, sub, stats);
|
||||
last = nats_Now();
|
||||
}
|
||||
|
||||
natsMsg_Destroy(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (s == NATS_OK)
|
||||
{
|
||||
printStats(STATS_IN|STATS_COUNT,conn, sub, stats);
|
||||
printPerf("Received");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Error: %u - %s\n", s, natsStatus_GetText(s));
|
||||
nats_PrintLastErrorStack(stderr);
|
||||
}
|
||||
|
||||
// Destroy all our objects to avoid report of memory leak
|
||||
natsStatistics_Destroy(stats);
|
||||
natsSubscription_Destroy(sub);
|
||||
natsConnection_Destroy(conn);
|
||||
natsOptions_Destroy(opts);
|
||||
|
||||
// To silence reports of memory still in used with valgrind
|
||||
nats_Close();
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user