summaryrefslogtreecommitdiffstats
path: root/src/jaegertracing/thrift/tutorial/c_glib
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xsrc/jaegertracing/thrift/tutorial/c_glib/Makefile.am84
-rw-r--r--src/jaegertracing/thrift/tutorial/c_glib/c_glib_client.c190
-rw-r--r--src/jaegertracing/thrift/tutorial/c_glib/c_glib_server.c527
3 files changed, 801 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/tutorial/c_glib/Makefile.am b/src/jaegertracing/thrift/tutorial/c_glib/Makefile.am
new file mode 100755
index 000000000..f37649495
--- /dev/null
+++ b/src/jaegertracing/thrift/tutorial/c_glib/Makefile.am
@@ -0,0 +1,84 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc
+
+BUILT_SOURCES = \
+ gen-c_glib/calculator.h \
+ gen-c_glib/shared_service.h \
+ gen-c_glib/shared_types.h \
+ gen-c_glib/tutorial_types.h
+
+AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) @GCOV_CFLAGS@ -I$(top_builddir)/lib/c_glib/src/thrift
+AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib
+AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS) @GCOV_LDFLAGS@
+
+noinst_LTLIBRARIES = \
+ libtutorialgencglib.la
+
+nodist_libtutorialgencglib_la_SOURCES = \
+ gen-c_glib/calculator.c \
+ gen-c_glib/calculator.h \
+ gen-c_glib/shared_service.c \
+ gen-c_glib/shared_service.h \
+ gen-c_glib/shared_types.c \
+ gen-c_glib/shared_types.h \
+ gen-c_glib/tutorial_types.c \
+ gen-c_glib/tutorial_types.h
+
+libtutorialgencglib_la_LIBADD = \
+ $(top_builddir)/lib/c_glib/libthrift_c_glib.la
+
+libtutorialgencglib_la_CFLAGS = \
+ $(AM_CFLAGS) -Wno-unused-function
+
+noinst_PROGRAMS = \
+ tutorial_server \
+ tutorial_client
+
+tutorial_server_SOURCES = \
+ c_glib_server.c
+tutorial_server_LDFLAGS = $(OPENSSL_LIBS)
+
+tutorial_server_LDADD = \
+ libtutorialgencglib.la \
+ $(top_builddir)/lib/c_glib/libthrift_c_glib.la
+
+tutorial_client_SOURCES = \
+ c_glib_client.c
+
+tutorial_client_LDADD = \
+ libtutorialgencglib.la \
+ $(top_builddir)/lib/c_glib/libthrift_c_glib.la
+
+
+gen-c_glib/calculator.c gen-c_glib/calculator.h gen-c_glib/shared_service.c gen-c_glib/shared_service.h gen-c_glib/shared_types.c gen-c_glib/shared_types.h gen-c_glib/tutorial_types.c gen-c_glib/tutorial_types.h: $(top_srcdir)/tutorial/tutorial.thrift
+ $(THRIFT) --gen c_glib -r $<
+
+clean-local:
+ $(RM) gen-c_glib/*
+
+tutorialserver: all
+ ./tutorial_server
+
+tutorialclient: all
+ ./tutorial_client
+
+EXTRA_DIST = \
+ c_glib_server.c \
+ c_glib_client.c
diff --git a/src/jaegertracing/thrift/tutorial/c_glib/c_glib_client.c b/src/jaegertracing/thrift/tutorial/c_glib/c_glib_client.c
new file mode 100644
index 000000000..986d5174c
--- /dev/null
+++ b/src/jaegertracing/thrift/tutorial/c_glib/c_glib_client.c
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 <stdio.h>
+#include <glib-object.h>
+
+#include <thrift/c_glib/protocol/thrift_binary_protocol.h>
+#include <thrift/c_glib/transport/thrift_buffered_transport.h>
+#include <thrift/c_glib/transport/thrift_socket.h>
+
+#include "gen-c_glib/calculator.h"
+
+int main (void)
+{
+ ThriftSocket *socket;
+ ThriftTransport *transport;
+ ThriftProtocol *protocol;
+ CalculatorIf *client;
+
+ GError *error = NULL;
+ InvalidOperation *invalid_operation = NULL;
+
+ Work *work;
+
+ gint32 sum;
+ gint32 diff;
+
+ int exit_status = 0;
+
+#if (!GLIB_CHECK_VERSION (2, 36, 0))
+ g_type_init ();
+#endif
+
+ socket = g_object_new (THRIFT_TYPE_SOCKET,
+ "hostname", "localhost",
+ "port", 9090,
+ NULL);
+ transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT,
+ "transport", socket,
+ NULL);
+ protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL,
+ "transport", transport,
+ NULL);
+
+ thrift_transport_open (transport, &error);
+
+
+ /* In the C (GLib) implementation of Thrift, service methods on the
+ server are accessed via a generated client class that implements
+ the service interface. In this tutorial, we access a Calculator
+ service through an instance of CalculatorClient, which implements
+ CalculatorIf. */
+ client = g_object_new (TYPE_CALCULATOR_CLIENT,
+ "input_protocol", protocol,
+ "output_protocol", protocol,
+ NULL);
+
+ /* Each of the client methods requires at least two parameters: A
+ pointer to the client-interface implementation (the client
+ object), and a handle to a GError structure to receive
+ information about any error that occurs.
+
+ On success, client methods return TRUE. A return value of FALSE
+ indicates an error occurred and the error parameter has been
+ set. */
+ if (!error && calculator_if_ping (client, &error)) {
+ puts ("ping()");
+ }
+
+ /* Service methods that return a value do so by passing the result
+ back via an output parameter (here, "sum"). */
+ if (!error && calculator_if_add (client, &sum, 1, 1, &error)) {
+ printf ("1+1=%d\n", sum);
+ }
+
+ /* Thrift structs are implemented as GObjects, with each of the
+ struct's members exposed as an object property. */
+ work = g_object_new (TYPE_WORK, NULL);
+
+ if (!error) {
+ g_object_set (work,
+ "num1", 1,
+ "num2", 0,
+ "op", OPERATION_DIVIDE,
+ NULL);
+
+ /* Exceptions are passed back from service methods in a manner
+ similar to return values. */
+ if (calculator_if_calculate (client,
+ NULL,
+ 1,
+ work,
+ &invalid_operation,
+ &error)) {
+ puts ("Whoa? We can divide by zero!");
+ }
+ else {
+ if (invalid_operation) {
+ gchar *why;
+
+ /* Like structs, exceptions are implemented as objects with
+ properties. */
+ g_object_get (invalid_operation, "why", &why, NULL);
+
+ printf ("InvalidOperation: %s\n", why);
+
+ if (why != NULL)
+ g_free (why);
+ g_object_unref (invalid_operation);
+ invalid_operation = NULL;
+ }
+
+ g_clear_error (&error);
+ }
+ }
+
+ if (!error) {
+ /* Struct objects can be reused across method invocations. */
+ g_object_set (work,
+ "num1", 15,
+ "num2", 10,
+ "op", OPERATION_SUBTRACT,
+ NULL);
+
+ if (calculator_if_calculate (client,
+ &diff,
+ 1,
+ work,
+ &invalid_operation,
+ &error)) {
+ printf ("15-10=%d\n", diff);
+ }
+ }
+
+ g_object_unref (work);
+
+ if (!error) {
+ SharedStruct *shared_struct;
+ gchar *value;
+
+ shared_struct = g_object_new (TYPE_SHARED_STRUCT, NULL);
+
+ /* As defined in the Thrift file, the Calculator service extends
+ the SharedService service. Correspondingly, in the generated
+ code CalculatorIf inherits from SharedServiceIf, and the parent
+ service's methods are accessible through a simple cast. */
+ if (shared_service_client_get_struct (SHARED_SERVICE_IF (client),
+ &shared_struct,
+ 1,
+ &error)) {
+ g_object_get (shared_struct, "value", &value, NULL);
+ printf ("Check log: %s\n", value);
+ g_free (value);
+ }
+
+ g_object_unref (shared_struct);
+ }
+
+ if (error) {
+ printf ("ERROR: %s\n", error->message);
+ g_clear_error (&error);
+
+ exit_status = 1;
+ }
+
+ thrift_transport_close (transport, NULL);
+
+ g_object_unref (client);
+ g_object_unref (protocol);
+ g_object_unref (transport);
+ g_object_unref (socket);
+
+ return exit_status;
+}
diff --git a/src/jaegertracing/thrift/tutorial/c_glib/c_glib_server.c b/src/jaegertracing/thrift/tutorial/c_glib/c_glib_server.c
new file mode 100644
index 000000000..47bf47fa0
--- /dev/null
+++ b/src/jaegertracing/thrift/tutorial/c_glib/c_glib_server.c
@@ -0,0 +1,527 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 <glib-object.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <thrift/c_glib/thrift.h>
+#include <thrift/c_glib/protocol/thrift_binary_protocol_factory.h>
+#include <thrift/c_glib/protocol/thrift_protocol_factory.h>
+#include <thrift/c_glib/server/thrift_server.h>
+#include <thrift/c_glib/server/thrift_simple_server.h>
+#include <thrift/c_glib/transport/thrift_buffered_transport_factory.h>
+#include <thrift/c_glib/transport/thrift_server_socket.h>
+#include <thrift/c_glib/transport/thrift_server_transport.h>
+
+#include "gen-c_glib/calculator.h"
+
+G_BEGIN_DECLS
+
+/* In the C (GLib) implementation of Thrift, the actual work done by a
+ server---that is, the code that runs when a client invokes a
+ service method---is defined in a separate "handler" class that
+ implements the service interface. Here we define the
+ TutorialCalculatorHandler class, which implements the CalculatorIf
+ interface and provides the behavior expected by tutorial clients.
+ (Typically this code would be placed in its own module but for
+ clarity this tutorial is presented entirely in a single file.)
+
+ For each service the Thrift compiler generates an abstract base
+ class from which handler implementations should inherit. In our
+ case TutorialCalculatorHandler inherits from CalculatorHandler,
+ defined in gen-c_glib/calculator.h.
+
+ If you're new to GObject, try not to be intimidated by the quantity
+ of code here---much of it is boilerplate and can mostly be
+ copied-and-pasted from existing work. For more information refer to
+ the GObject Reference Manual, available online at
+ https://developer.gnome.org/gobject/. */
+
+#define TYPE_TUTORIAL_CALCULATOR_HANDLER \
+ (tutorial_calculator_handler_get_type ())
+
+#define TUTORIAL_CALCULATOR_HANDLER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ TYPE_TUTORIAL_CALCULATOR_HANDLER, \
+ TutorialCalculatorHandler))
+#define TUTORIAL_CALCULATOR_HANDLER_CLASS(c) \
+ (G_TYPE_CHECK_CLASS_CAST ((c), \
+ TYPE_TUTORIAL_CALCULATOR_HANDLER, \
+ TutorialCalculatorHandlerClass))
+#define IS_TUTORIAL_CALCULATOR_HANDLER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ TYPE_TUTORIAL_CALCULATOR_HANDLER))
+#define IS_TUTORIAL_CALCULATOR_HANDLER_CLASS(c) \
+ (G_TYPE_CHECK_CLASS_TYPE ((c), \
+ TYPE_TUTORIAL_CALCULATOR_HANDLER))
+#define TUTORIAL_CALCULATOR_HANDLER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ TYPE_TUTORIAL_CALCULATOR_HANDLER, \
+ TutorialCalculatorHandlerClass))
+
+struct _TutorialCalculatorHandler {
+ CalculatorHandler parent_instance;
+
+ /* private */
+ GHashTable *log;
+};
+typedef struct _TutorialCalculatorHandler TutorialCalculatorHandler;
+
+struct _TutorialCalculatorHandlerClass {
+ CalculatorHandlerClass parent_class;
+};
+typedef struct _TutorialCalculatorHandlerClass TutorialCalculatorHandlerClass;
+
+GType tutorial_calculator_handler_get_type (void);
+
+G_END_DECLS
+
+/* ---------------------------------------------------------------- */
+
+/* The implementation of TutorialCalculatorHandler follows. */
+
+G_DEFINE_TYPE (TutorialCalculatorHandler,
+ tutorial_calculator_handler,
+ TYPE_CALCULATOR_HANDLER)
+
+/* Each of a handler's methods accepts at least two parameters: A
+ pointer to the service-interface implementation (the handler object
+ itself) and a handle to a GError structure to receive information
+ about any error that occurs.
+
+ On success, a handler method returns TRUE. A return value of FALSE
+ indicates an error occurred and the error parameter has been
+ set. (Methods should not return FALSE without first setting the
+ error parameter.) */
+static gboolean
+tutorial_calculator_handler_ping (CalculatorIf *iface,
+ GError **error)
+{
+ THRIFT_UNUSED_VAR (iface);
+ THRIFT_UNUSED_VAR (error);
+
+ puts ("ping()");
+
+ return TRUE;
+}
+
+/* Service-method parameters are passed through as parameters to the
+ handler method.
+
+ If the service method returns a value an output parameter, _return,
+ is additionally passed to the handler method. This parameter should
+ be set appropriately before the method returns, whenever it
+ succeeds.
+
+ The return value from this method happens to be of a base type,
+ i32, but note if a method returns a complex type such as a map or
+ list *_return will point to a pre-allocated data structure that
+ does not need to be re-allocated and should not be destroyed. */
+static gboolean
+tutorial_calculator_handler_add (CalculatorIf *iface,
+ gint32 *_return,
+ const gint32 num1,
+ const gint32 num2,
+ GError **error)
+{
+ THRIFT_UNUSED_VAR (iface);
+ THRIFT_UNUSED_VAR (error);
+
+ printf ("add(%d,%d)\n", num1, num2);
+ *_return = num1 + num2;
+
+ return TRUE;
+}
+
+/* Any handler method can return a ThriftApplicationException to the
+ client by setting its error parameter appropriately and returning
+ FALSE. See the ThriftApplicationExceptionError enumeration defined
+ in thrift_application_exception.h for a list of recognized
+ exception types (GError codes).
+
+ If a service method can also throw a custom exception (that is, one
+ defined in the .thrift file) an additional output parameter will be
+ provided (here, "ouch") to hold an instance of the exception, when
+ necessary. Note there will be a separate parameter added for each
+ type of exception the method can throw.
+
+ Unlike return values, exception objects are never pre-created; this
+ is always the responsibility of the handler method. */
+static gboolean
+tutorial_calculator_handler_calculate (CalculatorIf *iface,
+ gint32 *_return,
+ const gint32 logid,
+ const Work *w,
+ InvalidOperation **ouch,
+ GError **error)
+{
+ TutorialCalculatorHandler *self;
+
+ gint *log_key;
+ gchar log_value[12];
+ SharedStruct *log_struct;
+
+ gint num1;
+ gint num2;
+ Operation op;
+ gboolean result = TRUE;
+
+ THRIFT_UNUSED_VAR (error);
+
+ g_return_val_if_fail (IS_TUTORIAL_CALCULATOR_HANDLER (iface),
+ FALSE);
+ self = TUTORIAL_CALCULATOR_HANDLER (iface);
+
+ /* Remember: Exception objects are never pre-created */
+ g_assert (*ouch == NULL);
+
+ /* Fetch the contents of our Work parameter.
+
+ Note that integer properties of thirty-two bits or fewer in width
+ are _always_ of type gint, regardless of the range of values they
+ hold. A common error is trying to retrieve, say, a structure
+ member defined in the .thrift file as type i16 into a variable of
+ type gint16, which will clobber variables adjacent on the
+ stack. Remember: If you're retrieving an integer property the
+ receiving variable must be of either type gint or gint64, as
+ appropriate. */
+ g_object_get ((Work *)w,
+ "num1", &num1,
+ "num2", &num2,
+ "op", &op,
+ NULL);
+
+ printf ("calculate(%d,{%d,%d,%d})\n", logid, op, num1, num2);
+
+ switch (op) {
+ case OPERATION_ADD:
+ *_return = num1 + num2;
+ break;
+
+ case OPERATION_SUBTRACT:
+ *_return = num1 - num2;
+ break;
+
+ case OPERATION_MULTIPLY:
+ *_return = num1 * num2;
+ break;
+
+ case OPERATION_DIVIDE:
+ if (num2 == 0) {
+ /* For each custom exception type a subclass of ThriftStruct is
+ generated by the Thrift compiler. Throw an exception by
+ setting the corresponding output parameter to a new instance
+ of its type and returning FALSE. */
+ *ouch = g_object_new (TYPE_INVALID_OPERATION,
+ "whatOp", op,
+ "why", g_strdup ("Cannot divide by 0"),
+ NULL);
+ result = FALSE;
+
+ /* Note the call to g_strdup above: All the memory used by a
+ ThriftStruct's properties belongs to the object itself and
+ will be freed on destruction. Removing this call to g_strdup
+ will lead to a segmentation fault as the object tries to
+ release memory allocated statically to the program. */
+ }
+ else {
+ *_return = num1 / num2;
+ }
+ break;
+
+ default:
+ *ouch = g_object_new (TYPE_INVALID_OPERATION,
+ "whatOp", op,
+ "why", g_strdup ("Invalid Operation"),
+ NULL);
+ result = FALSE;
+ }
+
+ /* On success, log a record of the result to our hash table */
+ if (result) {
+ log_key = g_malloc (sizeof *log_key);
+ *log_key = logid;
+
+ snprintf (log_value, sizeof log_value, "%d", *_return);
+
+ log_struct = g_object_new (TYPE_SHARED_STRUCT,
+ "key", *log_key,
+ "value", g_strdup (log_value),
+ NULL);
+ g_hash_table_replace (self->log, log_key, log_struct);
+ }
+
+ return result;
+}
+
+/* A one-way method has the same signature as an equivalent, regular
+ method that returns no value. */
+static gboolean
+tutorial_calculator_handler_zip (CalculatorIf *iface,
+ GError **error)
+{
+ THRIFT_UNUSED_VAR (iface);
+ THRIFT_UNUSED_VAR (error);
+
+ puts ("zip()");
+
+ return TRUE;
+}
+
+/* As specified in the .thrift file (tutorial.thrift), the Calculator
+ service extends the SharedService service. Correspondingly, in the
+ generated code the Calculator interface, CalculatorIf, extends the
+ SharedService interface, SharedServiceIf, and subclasses of
+ CalculatorHandler should implement its methods as well.
+
+ Here we provide an implementation for the getStruct method from the
+ parent service. */
+static gboolean
+tutorial_calculator_handler_get_struct (SharedServiceIf *iface,
+ SharedStruct **_return,
+ const gint32 key32,
+ GError **error)
+{
+ gint key = (gint)key32;
+ TutorialCalculatorHandler *self;
+ SharedStruct *log_struct;
+ gint log_key;
+ gchar *log_value;
+
+ THRIFT_UNUSED_VAR (error);
+
+ g_return_val_if_fail (IS_TUTORIAL_CALCULATOR_HANDLER (iface),
+ FALSE);
+ self = TUTORIAL_CALCULATOR_HANDLER (iface);
+
+ /* Remember: Complex return types are always pre-created and need
+ only be populated */
+ g_assert (*_return != NULL);
+
+ printf ("getStruct(%d)\n", key);
+
+ /* If the key exists in our log, return the corresponding logged
+ data (or an empty SharedStruct structure if it does not).
+
+ Incidentally, note we _must_ here copy the values from the hash
+ table into the return structure. All memory used by the return
+ structure belongs to the structure itself and will be freed once
+ a response is sent to the client. If we merely freed *_return and
+ set it to point to our hash-table entry, that would mean memory
+ would be released (effectively, data erased) out of the hash
+ table! */
+ log_struct = g_hash_table_lookup (self->log, &key);
+ if (log_struct != NULL) {
+ g_object_get (log_struct,
+ "key", &log_key,
+ "value", &log_value,
+ NULL);
+ g_object_set (*_return,
+ "key", log_key,
+ "value", g_strdup (log_value),
+ NULL);
+ }
+
+ return TRUE;
+}
+
+/* TutorialCalculatorHandler's instance finalizer (destructor) */
+static void
+tutorial_calculator_handler_finalize (GObject *object)
+{
+ TutorialCalculatorHandler *self =
+ TUTORIAL_CALCULATOR_HANDLER (object);
+
+ /* Free our calculation-log hash table */
+ g_hash_table_unref (self->log);
+ self->log = NULL;
+
+ /* Chain up to the parent class */
+ G_OBJECT_CLASS (tutorial_calculator_handler_parent_class)->
+ finalize (object);
+}
+
+/* TutorialCalculatorHandler's instance initializer (constructor) */
+static void
+tutorial_calculator_handler_init (TutorialCalculatorHandler *self)
+{
+ /* Create our calculation-log hash table */
+ self->log = g_hash_table_new_full (g_int_hash,
+ g_int_equal,
+ g_free,
+ g_object_unref);
+}
+
+/* TutorialCalculatorHandler's class initializer */
+static void
+tutorial_calculator_handler_class_init (TutorialCalculatorHandlerClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ SharedServiceHandlerClass *shared_service_handler_class =
+ SHARED_SERVICE_HANDLER_CLASS (klass);
+ CalculatorHandlerClass *calculator_handler_class =
+ CALCULATOR_HANDLER_CLASS (klass);
+
+ /* Register our destructor */
+ gobject_class->finalize = tutorial_calculator_handler_finalize;
+
+ /* Register our implementations of CalculatorHandler's methods */
+ calculator_handler_class->ping =
+ tutorial_calculator_handler_ping;
+ calculator_handler_class->add =
+ tutorial_calculator_handler_add;
+ calculator_handler_class->calculate =
+ tutorial_calculator_handler_calculate;
+ calculator_handler_class->zip =
+ tutorial_calculator_handler_zip;
+
+ /* Register our implementation of SharedServiceHandler's method */
+ shared_service_handler_class->get_struct =
+ tutorial_calculator_handler_get_struct;
+}
+
+/* ---------------------------------------------------------------- */
+
+/* That ends the implementation of TutorialCalculatorHandler.
+ Everything below is fairly generic code that sets up a minimal
+ Thrift server for tutorial clients. */
+
+
+/* Our server object, declared globally so it is accessible within the
+ SIGINT signal handler */
+ThriftServer *server = NULL;
+
+/* A flag that indicates whether the server was interrupted with
+ SIGINT (i.e. Ctrl-C) so we can tell whether its termination was
+ abnormal */
+gboolean sigint_received = FALSE;
+
+/* Handle SIGINT ("Ctrl-C") signals by gracefully stopping the
+ server */
+static void
+sigint_handler (int signal_number)
+{
+ THRIFT_UNUSED_VAR (signal_number);
+
+ /* Take note we were called */
+ sigint_received = TRUE;
+
+ /* Shut down the server gracefully */
+ if (server != NULL)
+ thrift_server_stop (server);
+}
+
+int main (void)
+{
+ TutorialCalculatorHandler *handler;
+ CalculatorProcessor *processor;
+
+ ThriftServerTransport *server_transport;
+ ThriftTransportFactory *transport_factory;
+ ThriftProtocolFactory *protocol_factory;
+
+ struct sigaction sigint_action;
+
+ GError *error = NULL;
+ int exit_status = 0;
+
+#if (!GLIB_CHECK_VERSION (2, 36, 0))
+ g_type_init ();
+#endif
+
+ /* Create an instance of our handler, which provides the service's
+ methods' implementation */
+ handler =
+ g_object_new (TYPE_TUTORIAL_CALCULATOR_HANDLER,
+ NULL);
+
+ /* Create an instance of the service's processor, automatically
+ generated by the Thrift compiler, which parses incoming messages
+ and dispatches them to the appropriate method in the handler */
+ processor =
+ g_object_new (TYPE_CALCULATOR_PROCESSOR,
+ "handler", handler,
+ NULL);
+
+ /* Create our server socket, which binds to the specified port and
+ listens for client connections */
+ server_transport =
+ g_object_new (THRIFT_TYPE_SERVER_SOCKET,
+ "port", 9090,
+ NULL);
+
+ /* Create our transport factory, used by the server to wrap "raw"
+ incoming connections from the client (in this case with a
+ ThriftBufferedTransport to improve performance) */
+ transport_factory =
+ g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY,
+ NULL);
+
+ /* Create our protocol factory, which determines which wire protocol
+ the server will use (in this case, Thrift's binary protocol) */
+ protocol_factory =
+ g_object_new (THRIFT_TYPE_BINARY_PROTOCOL_FACTORY,
+ NULL);
+
+ /* Create the server itself */
+ server =
+ g_object_new (THRIFT_TYPE_SIMPLE_SERVER,
+ "processor", processor,
+ "server_transport", server_transport,
+ "input_transport_factory", transport_factory,
+ "output_transport_factory", transport_factory,
+ "input_protocol_factory", protocol_factory,
+ "output_protocol_factory", protocol_factory,
+ NULL);
+
+ /* Install our SIGINT handler, which handles Ctrl-C being pressed by
+ stopping the server gracefully (not strictly necessary, but a
+ nice touch) */
+ memset (&sigint_action, 0, sizeof (sigint_action));
+ sigint_action.sa_handler = sigint_handler;
+ sigint_action.sa_flags = SA_RESETHAND;
+ sigaction (SIGINT, &sigint_action, NULL);
+
+ /* Start the server, which will run until its stop method is invoked
+ (from within the SIGINT handler, in this case) */
+ puts ("Starting the server...");
+ thrift_server_serve (server, &error);
+
+ /* If the server stopped for any reason other than having been
+ interrupted by the user, report the error */
+ if (!sigint_received) {
+ g_message ("thrift_server_serve: %s",
+ error != NULL ? error->message : "(null)");
+ g_clear_error (&error);
+ }
+
+ puts ("done.");
+
+ g_object_unref (server);
+ g_object_unref (transport_factory);
+ g_object_unref (protocol_factory);
+ g_object_unref (server_transport);
+
+ g_object_unref (processor);
+ g_object_unref (handler);
+
+ return exit_status;
+}