diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/jaegertracing/thrift/tutorial/c_glib | |
parent | Initial commit. (diff) | |
download | ceph-upstream/16.2.11+ds.tar.xz ceph-upstream/16.2.11+ds.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
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; +} |