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 | |
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 '')
168 files changed, 13790 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/tutorial/Makefile.am b/src/jaegertracing/thrift/tutorial/Makefile.am new file mode 100755 index 000000000..17a92573b --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/Makefile.am @@ -0,0 +1,111 @@ +# +# 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. +# + +SUBDIRS = + +if MINGW +# do nothing, just build the compiler +else + +if WITH_C_GLIB +SUBDIRS += c_glib +endif + +if WITH_CPP +SUBDIRS += cpp +endif + +if WITH_D +SUBDIRS += d +endif + +if WITH_JAVA +SUBDIRS += java +SUBDIRS += js +endif + +if WITH_PYTHON +SUBDIRS += py +SUBDIRS += py.twisted +SUBDIRS += py.tornado +endif + +if WITH_RUBY +SUBDIRS += rb +endif + +if WITH_HASKELL +SUBDIRS += hs +endif + +if WITH_HAXE +SUBDIRS += haxe +endif + +if WITH_DOTNET +SUBDIRS += netcore +SUBDIRS += netstd +endif + +if WITH_GO +SUBDIRS += go +endif + +if WITH_NODEJS +SUBDIRS += nodejs +endif + +if WITH_DART +SUBDIRS += dart +endif + +if WITH_RS +SUBDIRS += rs +endif + +if WITH_CL +SUBDIRS += cl +endif + +# +# generate html for ThriftTest.thrift +# +all-local: + $(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/tutorial/tutorial.thrift + +clean-local: + rm -rf $(top_srcdir)/tutorial/gen-html + +endif + +# Any folders or files not listed above being added to SUBDIR need to be placed here in +# EXTRA_DIST to be included in the release +EXTRA_DIST = \ + as3 \ + csharp \ + d \ + delphi \ + erl \ + hs \ + ocaml \ + perl \ + php \ + shared.thrift \ + tutorial.thrift \ + README.md diff --git a/src/jaegertracing/thrift/tutorial/README.md b/src/jaegertracing/thrift/tutorial/README.md new file mode 100644 index 000000000..7772bf3e6 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/README.md @@ -0,0 +1,42 @@ +Thrift Tutorial + +License +======= + +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. + +Tutorial +======== + +1) First things first, you'll need to install the Thrift compiler and the + language libraries. Do that using the instructions in the top level + README.md file. + +2) Read tutorial.thrift to learn about the syntax of a Thrift file + +3) Compile the code for the language of your choice: + + $ thrift + $ thrift -r --gen cpp tutorial.thrift + +4) Take a look at the generated code. + +5) Look in the language directories for sample client/server code. + +6) That's about it for now. This tutorial is intentionally brief. It should be + just enough to get you started and ready to build your own project. diff --git a/src/jaegertracing/thrift/tutorial/as3/build.xml b/src/jaegertracing/thrift/tutorial/as3/build.xml new file mode 100644 index 000000000..f7ed32d04 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/as3/build.xml @@ -0,0 +1,50 @@ +<project name="tutorial" default="dist" basedir="."> + + <description>Thrift actionscript 3.0 tutorial.</description> + + <property name="gen" location="gen-as3" /> + <property name="src" location="src" /> + <property name="thrift.src" location="../../lib/as3/src/" /> + <property name="dist" location="dist" /> + + <property name="final.name" value="as3-tutorial" /> + <property name="swf.name" value="${dist}/${final.name}.swf" /> + + <target name="flex.check" unless="FLEX_HOME"> + <fail message='You must set the FLEX_HOME property pointing to your flex SDK, eg. ant -DFLEX_HOME="/Applications/Adobe Flex Builder 3/sdks/3.2.0"'/> + </target> + + <target name="flex.init" depends="flex.check" unless="flex.finished"> + <taskdef resource="flexTasks.tasks" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" /> + <property name="flex.finished" value="true"/> + </target> + + <target name="init"> + <tstamp /> + <mkdir dir="${dist}"/> + </target> + + <target name="dist" depends="generate, flex.init, init"> + <mxmlc output="${swf.name}" file="${src}/CalculatorUI.as"> + <source-path path-element="${gen}" /> + <source-path path-element="${src}" /> + <source-path path-element="${thrift.src}" /> + </mxmlc> + </target> + + <target name="generate"> + <!-- Generate the thrift gen-java source --> + <exec executable="../../compiler/cpp/thrift" failonerror="true"> + <arg line="--gen as3 ../shared.thrift"/> + </exec> + <exec executable="../../compiler/cpp/thrift" failonerror="true"> + <arg line="--gen as3 ../tutorial.thrift"/> + </exec> + </target> + + <target name="clean"> + <delete dir="${gen}"/> + <delete dir="${dist}" /> + </target> + +</project> diff --git a/src/jaegertracing/thrift/tutorial/as3/src/CalculatorUI.as b/src/jaegertracing/thrift/tutorial/as3/src/CalculatorUI.as new file mode 100644 index 000000000..d996df5fa --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/as3/src/CalculatorUI.as @@ -0,0 +1,142 @@ +package { + import flash.display.Sprite; + import flash.text.TextField; + import flash.text.TextFieldType; + import flash.events.MouseEvent; + import flash.system.Security; + + import org.apache.thrift.transport.TSocket; + import org.apache.thrift.transport.TTransport; + import org.apache.thrift.protocol.TProtocol; + import org.apache.thrift.protocol.TBinaryProtocol; + + /** + * Simple interface and connection logic implementation for tutorial. + */ + public class CalculatorUI extends Sprite { + public static const BUTTON_PADDING:uint = 5; + + private var mCalculatorClient:Calculator; // we use calculator through interface + private var mTransport:TTransport; // Transport, used to comunicate with server + + private var mAddButton:Sprite; + private var mLeft:TextField; + private var mRight:TextField; + private var mResult:TextField; + + private var pingButton:Sprite; + + public function CalculatorUI() { + buildInterface(); + initSecurity(); + initConnection(); + } + + private function initSecurity():void { + Security.loadPolicyFile("xmlsocket://127.0.0.1:9092"); + } + + /** + * Example of initializing connection. + */ + private function initConnection():void { + mTransport = new TSocket("127.0.0.1", 9090); // we connect to server + mTransport.open(); + // initialize protocol: + var protocol:TProtocol = new TBinaryProtocol(mTransport, false, false); + mCalculatorClient = new CalculatorImpl(protocol); // finally, we create calculator client instance + } + + private function onPingClick(me:MouseEvent):void { + if(!mTransport.isOpen()) return; + mCalculatorClient.ping(onPingError, onPingSuccess); + } + + private function onPingError(error:Error):void { + trace("Error, while requesting ping."); + throw error; + } + + private function onPingSuccess():void { + trace("Ping returned successfully"); + } + + private function onAddClick(me:MouseEvent):void { + if(!mTransport.isOpen()) return; + var num1:Number = Number(mLeft.text); + var num2:Number = Number(mRight.text); + mResult.text = "Processing..."; + mCalculatorClient.add(num1, num2, onAddError, onAddSuccess); + } + + private function onAddError(error:Error):void { + trace("Error, while requesting add."); + throw error; + } + + private function onAddSuccess(res:Number):void { + mResult.text = String(res); + } + + private function buildInterface():void { + addChild(pingButton = buildButton("PING")); + pingButton.x = (stage.stageWidth - pingButton.width) / 2; + pingButton.y = 10; + pingButton.addEventListener(MouseEvent.CLICK, onPingClick); + + var top:Number = pingButton.y + pingButton.height + 20; + addChild(mLeft = buildDigitInput()); + mLeft.x = 15; + mLeft.y = top + BUTTON_PADDING; + addChild(mRight = buildDigitInput()); + mRight.x = mLeft.x + mLeft.width + 15; + mRight.y = top + BUTTON_PADDING; + addChild(mAddButton = buildButton("ADD")); + mAddButton.x = mRight.x + mRight.width + 15; + mAddButton.y = top; + mAddButton.addEventListener(MouseEvent.CLICK, onAddClick); + addChild(mResult = buildDigitInput()); + mResult.x = mAddButton.x + mAddButton.width + 15; + mResult.y = top + BUTTON_PADDING; + } + + /** + * Simple digit-only input field. + */ + private function buildDigitInput():TextField { + var textField:TextField = new TextField; + textField.width = 75; + textField.height = 20; + textField.restrict = "0987654321."; + textField.type = TextFieldType.INPUT; + textField.background = true; + textField.backgroundColor = 0xaaaaff; + textField.textColor = 0xffff00; + return textField; + } + + /** + * Simple button drawing. + */ + private function buildButton(text:String):Sprite { + var button:Sprite = new Sprite; + var textField:TextField = new TextField; + textField.width = 4000; + textField.text = text; + textField.textColor = 0xffff00; + textField.width = textField.textWidth + 4; + textField.height = textField.textHeight + 4; + textField.mouseEnabled = false; + button.graphics.beginFill(0x0000ff); + button.graphics.lineStyle(0, 0x000000); + button.graphics.drawRoundRect(0, 0, textField.width + BUTTON_PADDING * 2, + textField.height + BUTTON_PADDING * 2, BUTTON_PADDING); + button.graphics.endFill(); + button.addChild(textField); + textField.x = BUTTON_PADDING; + textField.y = BUTTON_PADDING; + button.useHandCursor = button.buttonMode = true; + return button; + } + } +} 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; +} diff --git a/src/jaegertracing/thrift/tutorial/cl/Makefile.am b/src/jaegertracing/thrift/tutorial/cl/Makefile.am new file mode 100755 index 000000000..2b2013a3c --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cl/Makefile.am @@ -0,0 +1,65 @@ +# +# 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. + +setup-local-lisp-env: ensure-externals.sh + bash ensure-externals.sh + +gen-cl: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen cl -r $< + +ALL_FILE_PREREQS = \ + load-locally.lisp \ + make-tutorial-server.lisp \ + make-tutorial-client.lisp \ + shared-implementation.lisp \ + thrift-tutorial.asd \ + tutorial-implementation.lisp + +# NOTE: the server and client cannot be built in parallel +# because on loading the make-tutorial-* scripts SBCL will +# attempt to compile their dependencies. Unfortunately, +# because their dependencies are shared, parallel jobs can +# end up overwriting or corrupting the compiled files +all-local: gen-cl setup-local-lisp-env $(ALL_FILE_PREREQS) + $(SBCL) --script make-tutorial-server.lisp + $(SBCL) --script make-tutorial-client.lisp + +tutorialserver: all + ./TutorialServer + +tutorialclient: all + ./TutorialClient + +clean-local: + -$(RM) -r gen-* + -$(RM) -r externals + -$(RM) -r quicklisp + -$(RM) -r lib + -$(RM) quicklisp.lisp + -$(RM) backport-update.zip + -$(RM) shared-implementation.fasl + -$(RM) tutorial-implementation.fasl + -$(RM) TutorialServer + -$(RM) TutorialClient + +EXTRA_DIST = \ + tutorial-implementation.lisp \ + shared-implementation.lisp \ + thrift-tutorial.asd \ + make-tutorial-server.lisp \ + make-tutorial-client.lisp diff --git a/src/jaegertracing/thrift/tutorial/cl/ensure-externals.sh b/src/jaegertracing/thrift/tutorial/cl/ensure-externals.sh new file mode 120000 index 000000000..5ae8c5657 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cl/ensure-externals.sh @@ -0,0 +1 @@ +../../lib/cl/ensure-externals.sh
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/cl/load-locally.lisp b/src/jaegertracing/thrift/tutorial/cl/load-locally.lisp new file mode 100644 index 000000000..b52a0a269 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cl/load-locally.lisp @@ -0,0 +1,22 @@ +(in-package #:cl-user) + +;;;; 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. + +;;;; Just a script for loading the library itself, using bundled dependencies. +;;;; This is an identical copy of the file in lib/cl. + +(require "asdf") + +(load (merge-pathnames "externals/bundle.lisp" *load-truename*)) +(asdf:load-asd (merge-pathnames "lib/de.setf.thrift-backport-update/thrift.asd" *load-truename*)) +(asdf:load-system :thrift) diff --git a/src/jaegertracing/thrift/tutorial/cl/make-tutorial-client.lisp b/src/jaegertracing/thrift/tutorial/cl/make-tutorial-client.lisp new file mode 100644 index 000000000..3a6d86134 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cl/make-tutorial-client.lisp @@ -0,0 +1,51 @@ +(in-package #:cl-user) + +;;;; 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. + +(require "asdf") +(load (merge-pathnames "load-locally.lisp" *load-truename*)) +(asdf:load-system :net.didierverna.clon) +(asdf:load-asd (merge-pathnames "gen-cl/shared/thrift-gen-shared.asd" *load-truename*)) +(asdf:load-asd (merge-pathnames "gen-cl/tutorial/thrift-gen-tutorial.asd" *load-truename*)) +(asdf:load-asd (merge-pathnames "thrift-tutorial.asd" *load-truename*)) +(asdf:load-system :thrift-tutorial) + +(net.didierverna.clon:nickname-package) + +(defun main () + "Entry point for the binary." + (thrift:with-client (prot #u"thrift://127.0.0.1:9090") + (tutorial.calculator:ping prot) + (format t "ping()~%") + (format t "1 + 1 = ~a~%" (tutorial.calculator:add prot 1 1)) + (let ((work-instance (tutorial:make-work :num1 5 + :num2 0 + :op tutorial:operation.divide + :comment "Booya!"))) + (handler-case (format t + "5 / 0 = ~a - Oh, really? An exception should have been thrown here.~%" + (tutorial.calculator:calculate prot 1 work-instance)) + (tutorial:invalidoperation (e) + (format t "---~%(Expected) Invalid Operation caught: ~%~a~%---~%" e)))) + (let ((work-instance (tutorial:make-work :num1 15 + :num2 10 + :op tutorial:operation.subtract + :comment "Playing nice this time."))) + (handler-case (format t + "15 - 10 = ~a~%" + (tutorial.calculator:calculate prot 1 work-instance)) + (tutorial:invalidoperation (e) + (format t "---~%(Unexpected) Invalid Operation caught: ~%~a~%---~%" e)))) + (format t "Check log: ~a~%" (shared.shared-service:get-struct prot 1)))) + +(clon:dump "TutorialClient" main) diff --git a/src/jaegertracing/thrift/tutorial/cl/make-tutorial-server.lisp b/src/jaegertracing/thrift/tutorial/cl/make-tutorial-server.lisp new file mode 100644 index 000000000..4cf1a9026 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cl/make-tutorial-server.lisp @@ -0,0 +1,29 @@ +(in-package #:cl-user) + +;;;; 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. + +(require "asdf") +(load (merge-pathnames "load-locally.lisp" *load-truename*)) +(asdf:load-system :net.didierverna.clon) +(asdf:load-asd (merge-pathnames "gen-cl/shared/thrift-gen-shared.asd" *load-truename*)) +(asdf:load-asd (merge-pathnames "gen-cl/tutorial/thrift-gen-tutorial.asd" *load-truename*)) +(asdf:load-asd (merge-pathnames "thrift-tutorial.asd" *load-truename*)) +(asdf:load-system :thrift-tutorial) + +(net.didierverna.clon:nickname-package) + +(defun main () + "Entry point for the binary." + (thrift:serve #u"thrift://127.0.0.1:9090" tutorial:calculator)) + +(clon:dump "TutorialServer" main) diff --git a/src/jaegertracing/thrift/tutorial/cl/shared-implementation.lisp b/src/jaegertracing/thrift/tutorial/cl/shared-implementation.lisp new file mode 100644 index 000000000..c197626a5 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cl/shared-implementation.lisp @@ -0,0 +1,25 @@ +(in-package #:shared-implementation) + +;;;; 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. + +(defvar *structs* (make-hash-table)) + +(defun shared.shared-service-implementation:get-struct (key) + (format t "getStruct(~a)~%" key) + (gethash key *structs*)) + +(defun add-log (key value) + (setf (gethash key *structs*) + (make-instance 'shared:sharedstruct + :key key + :value (write-to-string value)))) diff --git a/src/jaegertracing/thrift/tutorial/cl/thrift-tutorial.asd b/src/jaegertracing/thrift/tutorial/cl/thrift-tutorial.asd new file mode 100644 index 000000000..8a0353763 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cl/thrift-tutorial.asd @@ -0,0 +1,17 @@ +;;;; 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. + +(asdf:defsystem #:thrift-tutorial + :depends-on (#:thrift-gen-tutorial) + :serial t + :components ((:file "shared-implementation") + (:file "tutorial-implementation"))) diff --git a/src/jaegertracing/thrift/tutorial/cl/tutorial-implementation.lisp b/src/jaegertracing/thrift/tutorial/cl/tutorial-implementation.lisp new file mode 100644 index 000000000..5c92fe405 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cl/tutorial-implementation.lisp @@ -0,0 +1,41 @@ +(in-package #:tutorial-implementation) + +;;;; 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. + +(defun tutorial.calculator-implementation:ping () + (format t "ping()~%")) + +(defun tutorial.calculator-implementation:add (num1 num2) + (format t "add(~a, ~a)~%" num1 num2) + (+ num1 num2)) + +(defun tutorial.calculator-implementation:calculate (logid work) + (format t "calculate(~a, ~a)~%" logid work) + (handler-case + (let* ((num1 (tutorial:work-num1 work)) + (num2 (tutorial:work-num2 work)) + (op (tutorial:work-op work)) + (result + (cond + ((= op tutorial:operation.add) (+ num1 num2)) + ((= op tutorial:operation.subtract) (- num1 num2)) + ((= op tutorial:operation.multiply) (* num1 num2)) + ((= op tutorial:operation.divide) (/ num1 num2))))) + (shared-implementation::add-log logid result) + result) + (division-by-zero () (error 'tutorial:invalidoperation + :why "Division by zero." + :what-op (tutorial:work-op work))))) + +(defun tutorial.calculator-implementation:zip () + (format t "zip()~%")) diff --git a/src/jaegertracing/thrift/tutorial/cpp/CMakeLists.txt b/src/jaegertracing/thrift/tutorial/cpp/CMakeLists.txt new file mode 100644 index 000000000..c6d8fc320 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cpp/CMakeLists.txt @@ -0,0 +1,57 @@ +# +# 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(BoostMacros) +REQUIRE_BOOST_HEADERS() + +#Make sure gen-cpp files can be included +include_directories("${CMAKE_CURRENT_BINARY_DIR}") +include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-cpp") +include_directories("${PROJECT_SOURCE_DIR}/lib/cpp/src") + +include(ThriftMacros) + +set(tutorialgencpp_SOURCES + gen-cpp/Calculator.cpp + gen-cpp/SharedService.cpp + gen-cpp/shared_constants.cpp + gen-cpp/shared_types.cpp + gen-cpp/tutorial_constants.cpp + gen-cpp/tutorial_types.cpp +) +add_library(tutorialgencpp STATIC ${tutorialgencpp_SOURCES}) +LINK_AGAINST_THRIFT_LIBRARY(tutorialgencpp thrift) + +add_custom_command(OUTPUT gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_constants.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp + COMMAND ${THRIFT_COMPILER} --gen cpp -r ${PROJECT_SOURCE_DIR}/tutorial/tutorial.thrift +) + +add_executable(TutorialServer CppServer.cpp) +target_link_libraries(TutorialServer tutorialgencpp) +LINK_AGAINST_THRIFT_LIBRARY(TutorialServer thrift) +if (ZLIB_FOUND) + target_link_libraries(TutorialServer ${ZLIB_LIBRARIES}) +endif () + +add_executable(TutorialClient CppClient.cpp) +target_link_libraries(TutorialClient tutorialgencpp) +LINK_AGAINST_THRIFT_LIBRARY(TutorialClient thrift) +if (ZLIB_FOUND) + target_link_libraries(TutorialClient ${ZLIB_LIBRARIES}) +endif () diff --git a/src/jaegertracing/thrift/tutorial/cpp/CppClient.cpp b/src/jaegertracing/thrift/tutorial/cpp/CppClient.cpp new file mode 100644 index 000000000..520841143 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cpp/CppClient.cpp @@ -0,0 +1,80 @@ +/* + * 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 <iostream> + +#include <thrift/protocol/TBinaryProtocol.h> +#include <thrift/transport/TSocket.h> +#include <thrift/transport/TTransportUtils.h> + +#include "../gen-cpp/Calculator.h" + +using namespace std; +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; + +using namespace tutorial; +using namespace shared; + +int main() { + std::shared_ptr<TTransport> socket(new TSocket("localhost", 9090)); + std::shared_ptr<TTransport> transport(new TBufferedTransport(socket)); + std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); + CalculatorClient client(protocol); + + try { + transport->open(); + + client.ping(); + cout << "ping()" << endl; + + cout << "1 + 1 = " << client.add(1, 1) << endl; + + Work work; + work.op = Operation::DIVIDE; + work.num1 = 1; + work.num2 = 0; + + try { + client.calculate(1, work); + cout << "Whoa? We can divide by zero!" << endl; + } catch (InvalidOperation& io) { + cout << "InvalidOperation: " << io.why << endl; + // or using generated operator<<: cout << io << endl; + // or by using std::exception native method what(): cout << io.what() << endl; + } + + work.op = Operation::SUBTRACT; + work.num1 = 15; + work.num2 = 10; + int32_t diff = client.calculate(1, work); + cout << "15 - 10 = " << diff << endl; + + // Note that C++ uses return by reference for complex types to avoid + // costly copy construction + SharedStruct ss; + client.getStruct(ss, 1); + cout << "Received log: " << ss << endl; + + transport->close(); + } catch (TException& tx) { + cout << "ERROR: " << tx.what() << endl; + } +} diff --git a/src/jaegertracing/thrift/tutorial/cpp/CppServer.cpp b/src/jaegertracing/thrift/tutorial/cpp/CppServer.cpp new file mode 100644 index 000000000..635afefda --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cpp/CppServer.cpp @@ -0,0 +1,179 @@ +/* + * 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 <thrift/concurrency/ThreadManager.h> +#include <thrift/concurrency/ThreadFactory.h> +#include <thrift/protocol/TBinaryProtocol.h> +#include <thrift/server/TSimpleServer.h> +#include <thrift/server/TThreadPoolServer.h> +#include <thrift/server/TThreadedServer.h> +#include <thrift/transport/TServerSocket.h> +#include <thrift/transport/TSocket.h> +#include <thrift/transport/TTransportUtils.h> +#include <thrift/TToString.h> + +#include <iostream> +#include <stdexcept> +#include <sstream> + +#include "../gen-cpp/Calculator.h" + +using namespace std; +using namespace apache::thrift; +using namespace apache::thrift::concurrency; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::server; + +using namespace tutorial; +using namespace shared; + +class CalculatorHandler : public CalculatorIf { +public: + CalculatorHandler() = default; + + void ping() override { cout << "ping()" << endl; } + + int32_t add(const int32_t n1, const int32_t n2) override { + cout << "add(" << n1 << ", " << n2 << ")" << endl; + return n1 + n2; + } + + int32_t calculate(const int32_t logid, const Work& work) override { + cout << "calculate(" << logid << ", " << work << ")" << endl; + int32_t val; + + switch (work.op) { + case Operation::ADD: + val = work.num1 + work.num2; + break; + case Operation::SUBTRACT: + val = work.num1 - work.num2; + break; + case Operation::MULTIPLY: + val = work.num1 * work.num2; + break; + case Operation::DIVIDE: + if (work.num2 == 0) { + InvalidOperation io; + io.whatOp = work.op; + io.why = "Cannot divide by 0"; + throw io; + } + val = work.num1 / work.num2; + break; + default: + InvalidOperation io; + io.whatOp = work.op; + io.why = "Invalid Operation"; + throw io; + } + + SharedStruct ss; + ss.key = logid; + ss.value = to_string(val); + + log[logid] = ss; + + return val; + } + + void getStruct(SharedStruct& ret, const int32_t logid) override { + cout << "getStruct(" << logid << ")" << endl; + ret = log[logid]; + } + + void zip() override { cout << "zip()" << endl; } + +protected: + map<int32_t, SharedStruct> log; +}; + +/* + CalculatorIfFactory is code generated. + CalculatorCloneFactory is useful for getting access to the server side of the + transport. It is also useful for making per-connection state. Without this + CloneFactory, all connections will end up sharing the same handler instance. +*/ +class CalculatorCloneFactory : virtual public CalculatorIfFactory { + public: + ~CalculatorCloneFactory() override = default; + CalculatorIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) override + { + std::shared_ptr<TSocket> sock = std::dynamic_pointer_cast<TSocket>(connInfo.transport); + cout << "Incoming connection\n"; + cout << "\tSocketInfo: " << sock->getSocketInfo() << "\n"; + cout << "\tPeerHost: " << sock->getPeerHost() << "\n"; + cout << "\tPeerAddress: " << sock->getPeerAddress() << "\n"; + cout << "\tPeerPort: " << sock->getPeerPort() << "\n"; + return new CalculatorHandler; + } + void releaseHandler( ::shared::SharedServiceIf* handler) override { + delete handler; + } +}; + +int main() { + TThreadedServer server( + std::make_shared<CalculatorProcessorFactory>(std::make_shared<CalculatorCloneFactory>()), + std::make_shared<TServerSocket>(9090), //port + std::make_shared<TBufferedTransportFactory>(), + std::make_shared<TBinaryProtocolFactory>()); + + /* + // if you don't need per-connection state, do the following instead + TThreadedServer server( + std::make_shared<CalculatorProcessor>(std::make_shared<CalculatorHandler>()), + std::make_shared<TServerSocket>(9090), //port + std::make_shared<TBufferedTransportFactory>(), + std::make_shared<TBinaryProtocolFactory>()); + */ + + /** + * Here are some alternate server types... + + // This server only allows one connection at a time, but spawns no threads + TSimpleServer server( + std::make_shared<CalculatorProcessor>(std::make_shared<CalculatorHandler>()), + std::make_shared<TServerSocket>(9090), + std::make_shared<TBufferedTransportFactory>(), + std::make_shared<TBinaryProtocolFactory>()); + + const int workerCount = 4; + + std::shared_ptr<ThreadManager> threadManager = + ThreadManager::newSimpleThreadManager(workerCount); + threadManager->threadFactory( + std::make_shared<ThreadFactory>()); + threadManager->start(); + + // This server allows "workerCount" connection at a time, and reuses threads + TThreadPoolServer server( + std::make_shared<CalculatorProcessorFactory>(std::make_shared<CalculatorCloneFactory>()), + std::make_shared<TServerSocket>(9090), + std::make_shared<TBufferedTransportFactory>(), + std::make_shared<TBinaryProtocolFactory>(), + threadManager); + */ + + cout << "Starting the server..." << endl; + server.serve(); + cout << "Done." << endl; + return 0; +} diff --git a/src/jaegertracing/thrift/tutorial/cpp/Makefile.am b/src/jaegertracing/thrift/tutorial/cpp/Makefile.am new file mode 100755 index 000000000..95497d5f3 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/cpp/Makefile.am @@ -0,0 +1,86 @@ +# +# 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-cpp/shared_types.cpp \ + gen-cpp/tutorial_types.cpp + +noinst_LTLIBRARIES = libtutorialgencpp.la +nodist_libtutorialgencpp_la_SOURCES = \ + gen-cpp/Calculator.cpp \ + gen-cpp/Calculator.h \ + gen-cpp/SharedService.cpp \ + gen-cpp/SharedService.h \ + gen-cpp/shared_constants.cpp \ + gen-cpp/shared_constants.h \ + gen-cpp/shared_types.cpp \ + gen-cpp/shared_types.h \ + gen-cpp/tutorial_constants.cpp \ + gen-cpp/tutorial_constants.h \ + gen-cpp/tutorial_types.cpp \ + gen-cpp/tutorial_types.h + + + +libtutorialgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la + +noinst_PROGRAMS = \ + TutorialServer \ + TutorialClient + +TutorialServer_SOURCES = \ + CppServer.cpp + +TutorialServer_LDADD = \ + libtutorialgencpp.la \ + $(top_builddir)/lib/cpp/libthrift.la + +TutorialClient_SOURCES = \ + CppClient.cpp + +TutorialClient_LDADD = \ + libtutorialgencpp.la \ + $(top_builddir)/lib/cpp/libthrift.la + +# +# Common thrift code generation rules +# +gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_constants.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen cpp -r $< + +AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp +AM_CXXFLAGS = -Wall -Wextra -pedantic +AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) + +clean-local: + $(RM) gen-cpp/* + +tutorialserver: all + ./TutorialServer + +tutorialclient: all + ./TutorialClient + +style-local: + $(CPPSTYLE_CMD) + +EXTRA_DIST = \ + CMakeLists.txt \ + CppClient.cpp \ + CppServer.cpp diff --git a/src/jaegertracing/thrift/tutorial/csharp/CsharpClient/CsharpClient.cs b/src/jaegertracing/thrift/tutorial/csharp/CsharpClient/CsharpClient.cs new file mode 100644 index 000000000..113a47223 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/csharp/CsharpClient/CsharpClient.cs @@ -0,0 +1,92 @@ +/* + * 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. + */ + +using System; +using Thrift; +using Thrift.Protocol; +using Thrift.Server; +using Thrift.Transport; + + +namespace CSharpTutorial +{ + public class CSharpClient + { + public static void Main() + { + try + { + TTransport transport = new TSocket("localhost", 9090); + TProtocol protocol = new TBinaryProtocol(transport); + Calculator.Client client = new Calculator.Client(protocol); + + transport.Open(); + try + { + client.ping(); + Console.WriteLine("ping()"); + + int sum = client.add(1, 1); + Console.WriteLine("1+1={0}", sum); + + Work work = new Work(); + + work.Op = Operation.DIVIDE; + work.Num1 = 1; + work.Num2 = 0; + try + { + int quotient = client.calculate(1, work); + Console.WriteLine("Whoa we can divide by 0"); + } + catch (InvalidOperation io) + { + Console.WriteLine("Invalid operation: " + io.Why); + } + + work.Op = Operation.SUBTRACT; + work.Num1 = 15; + work.Num2 = 10; + try + { + int diff = client.calculate(1, work); + Console.WriteLine("15-10={0}", diff); + } + catch (InvalidOperation io) + { + Console.WriteLine("Invalid operation: " + io.Why); + } + + SharedStruct log = client.getStruct(1); + Console.WriteLine("Check log: {0}", log.Value); + + } + finally + { + transport.Close(); + } + } + catch (TApplicationException x) + { + Console.WriteLine(x.StackTrace); + } + + } + } +} diff --git a/src/jaegertracing/thrift/tutorial/csharp/CsharpClient/CsharpClient.csproj b/src/jaegertracing/thrift/tutorial/csharp/CsharpClient/CsharpClient.csproj new file mode 100644 index 000000000..1ea7ff639 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/csharp/CsharpClient/CsharpClient.csproj @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.30729</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{18F24087-4760-43DA-ACAB-7B9F0E096B11}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>CsharpClient</RootNamespace> + <AssemblyName>CsharpClient</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Xml.Linq"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data.DataSetExtensions"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="..\gen-csharp\Calculator.cs"> + <Link>Calculator.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\InvalidOperation.cs"> + <Link>InvalidOperation.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\Operation.cs"> + <Link>Operation.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\SharedService.cs"> + <Link>SharedService.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\SharedStruct.cs"> + <Link>SharedStruct.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\tutorial.Constants.cs"> + <Link>tutorial.Constants.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\Work.cs"> + <Link>Work.cs</Link> + </Compile> + <Compile Include="CsharpClient.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\lib\csharp\src\Thrift.csproj"> + <Project>{499eb63c-d74c-47e8-ae48-a2fc94538e9d}</Project> + <Name>Thrift</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <PropertyGroup> + <PreBuildEvent>pushd "$(SolutionDir)" +thrift -gen csharp -r ../tutorial.thrift +popd +</PreBuildEvent> + </PropertyGroup> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..bae5e70c9 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +/* + * 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. + */ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CsharpClient")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("1a461214-fa28-452a-bd1d-d23ca8e947e3")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/src/jaegertracing/thrift/tutorial/csharp/CsharpServer/CsharpServer.cs b/src/jaegertracing/thrift/tutorial/csharp/CsharpServer/CsharpServer.cs new file mode 100644 index 000000000..439790aaf --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/csharp/CsharpServer/CsharpServer.cs @@ -0,0 +1,129 @@ +/* + * 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. + */ + +using System; +using System.Collections.Generic; +using Thrift.Server; +using Thrift.Transport; + +namespace CSharpTutorial +{ + public class CalculatorHandler : Calculator.Iface + { + Dictionary<int, SharedStruct> log; + + public CalculatorHandler() + { + log = new Dictionary<int, SharedStruct>(); + } + + public void ping() + { + Console.WriteLine("ping()"); + } + + public int add(int n1, int n2) + { + Console.WriteLine("add({0},{1})", n1, n2); + return n1 + n2; + } + + public int calculate(int logid, Work work) + { + Console.WriteLine("calculate({0}, [{1},{2},{3}])", logid, work.Op, work.Num1, work.Num2); + int val = 0; + switch (work.Op) + { + case Operation.ADD: + val = work.Num1 + work.Num2; + break; + + case Operation.SUBTRACT: + val = work.Num1 - work.Num2; + break; + + case Operation.MULTIPLY: + val = work.Num1 * work.Num2; + break; + + case Operation.DIVIDE: + if (work.Num2 == 0) + { + InvalidOperation io = new InvalidOperation(); + io.WhatOp = (int)work.Op; + io.Why = "Cannot divide by 0"; + throw io; + } + val = work.Num1 / work.Num2; + break; + + default: + { + InvalidOperation io = new InvalidOperation(); + io.WhatOp = (int)work.Op; + io.Why = "Unknown operation"; + throw io; + } + } + + SharedStruct entry = new SharedStruct(); + entry.Key = logid; + entry.Value = val.ToString(); + log[logid] = entry; + + return val; + } + + public SharedStruct getStruct(int key) + { + Console.WriteLine("getStruct({0})", key); + return log[key]; + } + + public void zip() + { + Console.WriteLine("zip()"); + } + } + + public class CSharpServer + { + public static void Main() + { + try + { + CalculatorHandler handler = new CalculatorHandler(); + Calculator.Processor processor = new Calculator.Processor(handler); + TServerTransport serverTransport = new TServerSocket(9090); + TServer server = new TSimpleServer(processor, serverTransport); + + // Use this for a multithreaded server + // server = new TThreadPoolServer(processor, serverTransport); + + Console.WriteLine("Starting the server..."); + server.Serve(); + } + catch (Exception x) + { + Console.WriteLine(x.StackTrace); + } + Console.WriteLine("done."); + } + } +} diff --git a/src/jaegertracing/thrift/tutorial/csharp/CsharpServer/CsharpServer.csproj b/src/jaegertracing/thrift/tutorial/csharp/CsharpServer/CsharpServer.csproj new file mode 100644 index 000000000..07481806c --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/csharp/CsharpServer/CsharpServer.csproj @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.30729</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{66707BAE-BBF9-4F03-B53E-BE3AD58322F8}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>CsharpServer</RootNamespace> + <AssemblyName>CsharpServer</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Xml.Linq"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data.DataSetExtensions"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="..\gen-csharp\Calculator.cs"> + <Link>Calculator.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\InvalidOperation.cs"> + <Link>InvalidOperation.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\Operation.cs"> + <Link>Operation.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\SharedService.cs"> + <Link>SharedService.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\SharedStruct.cs"> + <Link>SharedStruct.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\tutorial.Constants.cs"> + <Link>tutorial.Constants.cs</Link> + </Compile> + <Compile Include="..\gen-csharp\Work.cs"> + <Link>Work.cs</Link> + </Compile> + <Compile Include="CsharpServer.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\lib\csharp\src\Thrift.csproj"> + <Project>{499eb63c-d74c-47e8-ae48-a2fc94538e9d}</Project> + <Name>Thrift</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <PropertyGroup> + <PreBuildEvent>pushd "$(SolutionDir)" +thrift -gen csharp -r ../tutorial.thrift +popd + +</PreBuildEvent> + </PropertyGroup> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..e3ed39a9c --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +/* + * 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. + */ + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CsharpServer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("e3b428f4-b2e9-4fc1-8a34-84abc4339860")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/src/jaegertracing/thrift/tutorial/csharp/tutorial.sln b/src/jaegertracing/thrift/tutorial/csharp/tutorial.sln new file mode 100644 index 000000000..ec57a188d --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/csharp/tutorial.sln @@ -0,0 +1,39 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift", "..\..\lib\csharp\src\Thrift.csproj", "{499EB63C-D74C-47E8-AE48-A2FC94538E9D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsharpClient", "CsharpClient\CsharpClient.csproj", "{18F24087-4760-43DA-ACAB-7B9F0E096B11}" + ProjectSection(ProjectDependencies) = postProject + {499EB63C-D74C-47E8-AE48-A2FC94538E9D} = {499EB63C-D74C-47E8-AE48-A2FC94538E9D} + {66707BAE-BBF9-4F03-B53E-BE3AD58322F8} = {66707BAE-BBF9-4F03-B53E-BE3AD58322F8} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsharpServer", "CsharpServer\CsharpServer.csproj", "{66707BAE-BBF9-4F03-B53E-BE3AD58322F8}" + ProjectSection(ProjectDependencies) = postProject + {499EB63C-D74C-47E8-AE48-A2FC94538E9D} = {499EB63C-D74C-47E8-AE48-A2FC94538E9D} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Release|Any CPU.Build.0 = Release|Any CPU + {18F24087-4760-43DA-ACAB-7B9F0E096B11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {18F24087-4760-43DA-ACAB-7B9F0E096B11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {18F24087-4760-43DA-ACAB-7B9F0E096B11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {18F24087-4760-43DA-ACAB-7B9F0E096B11}.Release|Any CPU.Build.0 = Release|Any CPU + {66707BAE-BBF9-4F03-B53E-BE3AD58322F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66707BAE-BBF9-4F03-B53E-BE3AD58322F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66707BAE-BBF9-4F03-B53E-BE3AD58322F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66707BAE-BBF9-4F03-B53E-BE3AD58322F8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/jaegertracing/thrift/tutorial/d/Makefile.am b/src/jaegertracing/thrift/tutorial/d/Makefile.am new file mode 100644 index 000000000..358294ce5 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/d/Makefile.am @@ -0,0 +1,53 @@ +# +# 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. +# + +LIB_D_DIR = $(top_srcdir)/lib/d + +GEN_SRC = gen-d/share/SharedService.d gen-d/share/shared_types.d \ + gen-d/tutorial/tutorial_types.d gen-d/tutorial/Calculator.d + +$(GEN_SRC): $(top_srcdir)/tutorial/tutorial.thrift + $(top_builddir)/compiler/cpp/thrift --gen d -r $< + +server: server.d $(GEN_SRC) + $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd server.d ${GEN_SRC} + +client: client.d $(GEN_SRC) + $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd client.d ${GEN_SRC} + +PROGS = server client + +if WITH_D_EVENT_TESTS +async_client: async_client.d $(GEN_SRC) + $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd-event -L-lthriftd -L-levent async_client.d ${GEN_SRC} + +PROGS += async_client +endif + +all-local: $(PROGS) + +clean: + $(RM) -f $(PROGS) + $(RM) -r gen-d/ + find . -type f -name '*.o' | xargs rm -f + +dist-hook: + $(RM) -f $(distdir)/$(PROGS) + $(RM) -r $(distdir)/gen-d/ + find $(destdir) -type f -name '*.o' | xargs rm -f diff --git a/src/jaegertracing/thrift/tutorial/d/async_client.d b/src/jaegertracing/thrift/tutorial/d/async_client.d new file mode 100644 index 000000000..1defce082 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/d/async_client.d @@ -0,0 +1,86 @@ +/* + * 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. + */ +module async_client; + +import std.exception; +import std.stdio; +import thrift.async.libevent; +import thrift.async.socket; +import thrift.base; +import thrift.codegen.async_client; +import thrift.protocol.binary; +import thrift.transport.buffered; + +import tutorial.Calculator; +import tutorial.tutorial_types; + +void main() { + auto asyncManager = new TLibeventAsyncManager; + + // If we are done, gracefully stop the async manager to avoid hanging on + // appplication shutdown. + scope (exit) asyncManager.stop(); + + auto socket = new TAsyncSocket(asyncManager, "localhost", 9090); + auto client = new TAsyncClient!Calculator( + socket, + new TBufferedTransportFactory, + new TBinaryProtocolFactory!TBufferedTransport + ); + + socket.open(); + + // Invoke all the methods. + auto pingResult = client.ping(); + + auto addResult = client.add(1, 1); + + auto work = Work(); + work.op = Operation.DIVIDE; + work.num1 = 1; + work.num2 = 0; + auto quotientResult = client.calculate(1, work); + + work.op = Operation.SUBTRACT; + work.num1 = 15; + work.num2 = 10; + auto diffResult = client.calculate(1, work); + + auto logResult = client.getStruct(1); + + // Await the responses. + pingResult.waitGet(); + writeln("ping()"); + + int sum = addResult.waitGet(); + writefln("1 + 1 = %s", sum); + + try { + quotientResult.waitGet(); + writeln("Whoa we can divide by 0"); + } catch (InvalidOperation io) { + writeln("Invalid operation: " ~ io.why); + } + + writefln("15 - 10 = %s", diffResult.waitGet()); + + // TFuture is implicitly convertible to the result type via »alias this«, + // for which it (eagerly, of course) awaits completion. + writefln("Check log: %s", logResult.value); +} diff --git a/src/jaegertracing/thrift/tutorial/d/client.d b/src/jaegertracing/thrift/tutorial/d/client.d new file mode 100644 index 000000000..1867a17bc --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/d/client.d @@ -0,0 +1,64 @@ +/* + * 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. + */ +module client; + +import std.stdio; +import thrift.base; +import thrift.codegen.client; +import thrift.protocol.binary; +import thrift.transport.buffered; +import thrift.transport.socket; + +import tutorial.Calculator; +import tutorial.tutorial_types; + +void main() { + auto socket = new TSocket("localhost", 9090); + auto transport = new TBufferedTransport(socket); + auto protocol = tBinaryProtocol(transport); + auto client = tClient!Calculator(protocol); + + transport.open(); + + client.ping(); + writeln("ping()"); + + int sum = client.add(1, 1); + writefln("1 + 1 = %s", sum); + + auto work = Work(); + work.op = Operation.DIVIDE; + work.num1 = 1; + work.num2 = 0; + try { + int quotient = client.calculate(1, work); + writeln("Whoa we can divide by 0"); + } catch (InvalidOperation io) { + writeln("Invalid operation: " ~ io.why); + } + + work.op = Operation.SUBTRACT; + work.num1 = 15; + work.num2 = 10; + int diff = client.calculate(1, work); + writefln("15 - 10 = %s", diff); + + auto log = client.getStruct(1); + writefln("Check log: %s", log.value); +} diff --git a/src/jaegertracing/thrift/tutorial/d/server.d b/src/jaegertracing/thrift/tutorial/d/server.d new file mode 100644 index 000000000..cbcedccf3 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/d/server.d @@ -0,0 +1,111 @@ +/* + * 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. + */ +module server; + +import std.conv : to; +import std.stdio; +import thrift.codegen.processor; +import thrift.protocol.binary; +import thrift.server.simple; +import thrift.server.transport.socket; +import thrift.transport.buffered; + +import share.SharedService; +import share.shared_types; +import tutorial.Calculator; +import tutorial.tutorial_types; + +/** + * The actual implementation of the Calculator interface that is called by + * the server to answer the requests. + */ +class CalculatorHandler : Calculator { + void ping() { + writeln("ping()"); + } + + int add(int n1, int n2) { + writefln("add(%s,%s)", n1, n2); + return n1 + n2; + } + + int calculate(int logid, ref const(Work) work) { + writefln("calculate(%s, {%s, %s, %s})", logid, work.op, work.num1, work.num2); + int val; + + switch (work.op) { + case Operation.ADD: + val = work.num1 + work.num2; + break; + case Operation.SUBTRACT: + val = work.num1 - work.num2; + break; + case Operation.MULTIPLY: + val = work.num1 * work.num2; + break; + case Operation.DIVIDE: + if (work.num2 == 0) { + auto io = new InvalidOperation(); + io.whatOp = work.op; + io.why = "Cannot divide by 0"; + throw io; + } + val = work.num1 / work.num2; + break; + default: + auto io = new InvalidOperation(); + io.whatOp = work.op; + io.why = "Invalid Operation"; + throw io; + } + + auto ss = SharedStruct(); + ss.key = logid; + ss.value = to!string(val); + log[logid] = ss; + + return val; + } + + SharedStruct getStruct(int logid) { + writefln("getStruct(%s)", logid); + return log[logid]; + } + + void zip() { + writeln("zip()"); + } + +protected: + SharedStruct[int] log; +} + +void main() { + auto protocolFactory = new TBinaryProtocolFactory!(); + auto processor = new TServiceProcessor!Calculator(new CalculatorHandler); + auto serverTransport = new TServerSocket(9090); + auto transportFactory = new TBufferedTransportFactory; + + auto server = new TSimpleServer( + processor, serverTransport, transportFactory, protocolFactory); + + writeln("Starting the server on port 9090..."); + server.serve(); + writeln("done."); +} diff --git a/src/jaegertracing/thrift/tutorial/dart/Makefile.am b/src/jaegertracing/thrift/tutorial/dart/Makefile.am new file mode 100644 index 000000000..0b93ac859 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/Makefile.am @@ -0,0 +1,81 @@ +# +# 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. +# + +BUILT_SOURCES = gen-dart/tutorial/lib/tutorial.dart gen-dart/shared/lib/shared.dart + +gen-dart/tutorial/lib/tutorial.dart gen-dart/shared/lib/shared.dart: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen dart -r $< + +all-local: gen-dart/tutorial/lib/tutorial.dart pub-get + +clean-local: + $(RM) -r gen-*/ + find . -type d -name ".dart_tool" | xargs $(RM) -r + find . -type d -name "packages" | xargs $(RM) -r + find . -type f -name ".packages" | xargs $(RM) + find . -type f -name "pubspec.lock" | xargs $(RM) + +dist-hook: + $(RM) -r $(distdir)/gen-*/ + find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r + find $(distdir) -type d -name "packages" | xargs $(RM) -r + find $(distdir) -type f -name ".packages" | xargs $(RM) + find $(distdir) -type f -name "pubspec.lock" | xargs $(RM) + +pub-get: pub-get-gen pub-get-client pub-get-console-client pub-get-server + +pub-get-gen: pub-get-tutorial pub-get-shared + +pub-get-tutorial: gen-dart/tutorial/lib/tutorial.dart + cd gen-dart/tutorial; ${DARTPUB} get + +pub-get-shared: gen-dart/shared/lib/shared.dart + cd gen-dart/shared; ${DARTPUB} get + +pub-get-client: + cd client; ${DARTPUB} get + +pub-get-console-client: + cd console_client; ${DARTPUB} get + +pub-get-server: + cd server; ${DARTPUB} get + +tutorialserver: pub-get-gen pub-get-server + ${DART} server/bin/main.dart + +tutorialclient: pub-get-gen pub-get-client + cd client; ${DARTPUB} serve + +tutorialconsoleclient: pub-get-console-client + ${DART} console_client/bin/main.dart + +EXTRA_DIST = \ + client/web/client.dart \ + client/web/index.html \ + client/web/styles.css \ + client/pubspec.yaml \ + console_client/bin/main.dart \ + console_client/pubspec.yaml \ + server/bin/main.dart \ + server/pubspec.yaml \ + console_client/.analysis_options \ + client/.analysis_options \ + server/.analysis_options \ + build.sh diff --git a/src/jaegertracing/thrift/tutorial/dart/build.sh b/src/jaegertracing/thrift/tutorial/dart/build.sh new file mode 100644 index 000000000..eabe04a18 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/build.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +# 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. + +set -e; +rm -r gen-dart || true; + +thrift --gen dart ../shared.thrift; +cd gen-dart/shared; +pub get; +cd ../..; + +thrift --gen dart ../tutorial.thrift; +cd gen-dart/tutorial; +pub get; +cd ../..; + +cd client; +pub get; +cd ..; + +cd console_client; +pub get; +cd ..; + +cd server; +pub get; +cd ..; + +dartfmt -w gen-dart; + +echo "\nEnjoy the Dart tutorial!"; +echo "\nTo run the server:"; +echo "> dart server/bin/main.dart"; +echo "\nTo run the client:"; +echo "# Serve the app from the client directory and view in a browser"; +echo "> cd client;"; +echo "> pub serve;"; +echo "\nTo run the console client:"; +echo "> dart console_client/bin/main.dart"; +echo ""; diff --git a/src/jaegertracing/thrift/tutorial/dart/client/.analysis_options b/src/jaegertracing/thrift/tutorial/dart/client/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/client/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/src/jaegertracing/thrift/tutorial/dart/client/pubspec.yaml b/src/jaegertracing/thrift/tutorial/dart/client/pubspec.yaml new file mode 100644 index 000000000..6581b4d21 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/client/pubspec.yaml @@ -0,0 +1,33 @@ +# 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. + +name: tutorial_client +version: 0.13.0 +description: A Dart client implementation of the Apache Thrift tutorial +author: Apache Thrift Developers <dev@thrift.apache.org> +homepage: http://thrift.apache.org + +environment: + sdk: ">=1.13.0 <3.0.0" + +dependencies: + shared: + path: ../gen-dart/shared + thrift: + path: ../../../lib/dart + tutorial: + path: ../gen-dart/tutorial diff --git a/src/jaegertracing/thrift/tutorial/dart/client/web/client.dart b/src/jaegertracing/thrift/tutorial/dart/client/web/client.dart new file mode 100644 index 000000000..4f02d0d98 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/client/web/client.dart @@ -0,0 +1,278 @@ +/// 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. + +import 'dart:html'; + +import 'package:thrift/thrift.dart'; +import 'package:thrift/thrift_browser.dart'; +import 'package:shared/shared.dart'; +import 'package:tutorial/tutorial.dart'; + +/// Adapted from the AS3 tutorial +void main() { + new CalculatorUI(querySelector('#output')).start(); +} + +class CalculatorUI { + final DivElement output; + + CalculatorUI(this.output); + + TTransport _transport; + Calculator _calculatorClient; + + void start() { + _buildInterface(); + _initConnection(); + } + + void _validate() { + if (!_transport.isOpen) { + window.alert("The transport is not open!"); + } + } + + void _initConnection() { + _transport = new TAsyncClientSocketTransport( + new TWebSocket(Uri.parse('ws://127.0.0.1:9090/ws')), + new TMessageReader(new TBinaryProtocolFactory())); + TProtocol protocol = new TBinaryProtocol(_transport); + _transport.open(); + + _calculatorClient = new CalculatorClient(protocol); + } + + void _buildInterface() { + output.children.forEach((e) { + e.remove(); + }); + + _buildPingComponent(); + + _buildAddComponent(); + + _buildCalculatorComponent(); + + _buildGetStructComponent(); + } + + void _buildPingComponent() { + output.append(new HeadingElement.h3()..text = "Ping"); + ButtonElement pingButton = new ButtonElement() + ..text = "PING" + ..onClick.listen(_onPingClick); + output.append(pingButton); + } + + void _onPingClick(MouseEvent e) { + _validate(); + + _calculatorClient.ping(); + } + + void _buildAddComponent() { + output.append(new HeadingElement.h3()..text = "Add"); + InputElement num1 = new InputElement() + ..id = "add1" + ..type = "number" + ..style.fontSize = "14px" + ..style.width = "50px"; + output.append(num1); + SpanElement op = new SpanElement() + ..text = "+" + ..style.fontSize = "14px" + ..style.marginLeft = "10px"; + output.append(op); + InputElement num2 = new InputElement() + ..id = "add2" + ..type = "number" + ..style.fontSize = "14px" + ..style.width = "50px" + ..style.marginLeft = "10px"; + output.append(num2); + ButtonElement addButton = new ButtonElement() + ..text = "=" + ..style.fontSize = "14px" + ..style.marginLeft = "10px" + ..onClick.listen(_onAddClick); + output.append(addButton); + SpanElement result = new SpanElement() + ..id = "addResult" + ..style.fontSize = "14px" + ..style.marginLeft = "10px"; + output.append(result); + } + + void _onAddClick(MouseEvent e) { + _validate(); + + InputElement num1 = querySelector("#add1"); + InputElement num2 = querySelector("#add2"); + SpanElement result = querySelector("#addResult"); + + _calculatorClient + .add(int.parse(num1.value), int.parse(num2.value)) + .then((int n) { + result.text = "$n"; + }); + } + + void _buildCalculatorComponent() { + output.append(new HeadingElement.h3()..text = "Calculator"); + InputElement num1 = new InputElement() + ..id = "calc1" + ..type = "number" + ..style.fontSize = "14px" + ..style.width = "50px"; + output.append(num1); + SelectElement op = new SelectElement() + ..id = "calcOp" + ..multiple = false + ..selectedIndex = 0 + ..style.fontSize = "16px" + ..style.marginLeft = "10px" + ..style.width = "50px"; + OptionElement addOp = new OptionElement() + ..text = "+" + ..value = Operation.ADD.toString(); + op.add(addOp, 0); + OptionElement subtractOp = new OptionElement() + ..text = "-" + ..value = Operation.SUBTRACT.toString(); + op.add(subtractOp, 1); + OptionElement multiplyOp = new OptionElement() + ..text = "*" + ..value = Operation.MULTIPLY.toString(); + op.add(multiplyOp, 2); + OptionElement divideOp = new OptionElement() + ..text = "/" + ..value = Operation.DIVIDE.toString(); + op.add(divideOp, 3); + output.append(op); + InputElement num2 = new InputElement() + ..id = "calc2" + ..type = "number" + ..style.fontSize = "14px" + ..style.width = "50px" + ..style.marginLeft = "10px"; + output.append(num2); + ButtonElement calcButton = new ButtonElement() + ..text = "=" + ..style.fontSize = "14px" + ..style.marginLeft = "10px" + ..onClick.listen(_onCalcClick); + output.append(calcButton); + SpanElement result = new SpanElement() + ..id = "calcResult" + ..style.fontSize = "14px" + ..style.marginLeft = "10px"; + output.append(result); + output.append(new BRElement()); + output.append(new BRElement()); + LabelElement logIdLabel = new LabelElement() + ..text = "Log ID:" + ..style.fontSize = "14px"; + output.append(logIdLabel); + InputElement logId = new InputElement() + ..id = "logId" + ..type = "number" + ..value = "1" + ..style.fontSize = "14px" + ..style.width = "50px" + ..style.marginLeft = "10px"; + output.append(logId); + LabelElement commentLabel = new LabelElement() + ..text = "Comment:" + ..style.fontSize = "14px" + ..style.marginLeft = "10px"; + output.append(commentLabel); + InputElement comment = new InputElement() + ..id = "comment" + ..style.fontSize = "14px" + ..style.width = "100px" + ..style.marginLeft = "10px"; + output.append(comment); + } + + void _onCalcClick(MouseEvent e) { + _validate(); + + InputElement num1 = querySelector("#calc1"); + InputElement num2 = querySelector("#calc2"); + SelectElement op = querySelector("#calcOp"); + SpanElement result = querySelector("#calcResult"); + InputElement logId = querySelector("#logId"); + InputElement comment = querySelector("#comment"); + + int logIdValue = int.parse(logId.value); + logId.value = (logIdValue + 1).toString(); + + Work work = new Work(); + work.num1 = int.parse(num1.value); + work.num2 = int.parse(num2.value); + work.op = int.parse(op.options[op.selectedIndex].value); + work.comment = comment.value; + + _calculatorClient.calculate(logIdValue, work).then((int n) { + result.text = "$n"; + }); + } + + void _buildGetStructComponent() { + output.append(new HeadingElement.h3()..text = "Get Struct"); + LabelElement logIdLabel = new LabelElement() + ..text = "Struct Key:" + ..style.fontSize = "14px"; + output.append(logIdLabel); + InputElement logId = new InputElement() + ..id = "structKey" + ..type = "number" + ..value = "1" + ..style.fontSize = "14px" + ..style.width = "50px" + ..style.marginLeft = "10px"; + output.append(logId); + ButtonElement getStructButton = new ButtonElement() + ..text = "GET" + ..style.fontSize = "14px" + ..style.marginLeft = "10px" + ..onClick.listen(_onGetStructClick); + output.append(getStructButton); + output.append(new BRElement()); + output.append(new BRElement()); + TextAreaElement result = new TextAreaElement() + ..id = "getStructResult" + ..style.fontSize = "14px" + ..style.width = "300px" + ..style.height = "50px" + ..style.marginLeft = "10px"; + output.append(result); + } + + void _onGetStructClick(MouseEvent e) { + _validate(); + + InputElement structKey = querySelector("#structKey"); + TextAreaElement result = querySelector("#getStructResult"); + + _calculatorClient + .getStruct(int.parse(structKey.value)) + .then((SharedStruct s) { + result.text = "${s.toString()}"; + }); + } +} diff --git a/src/jaegertracing/thrift/tutorial/dart/client/web/index.html b/src/jaegertracing/thrift/tutorial/dart/client/web/index.html new file mode 100644 index 000000000..9d36b4388 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/client/web/index.html @@ -0,0 +1,35 @@ +<!-- + * 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. +--> +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Thrift Tutorial</title> + <link rel="stylesheet" href="styles.css"> + <script async src="client.dart.js"></script> +</head> + +<body> + + <div id="output"></div> + +</body> +</html> diff --git a/src/jaegertracing/thrift/tutorial/dart/client/web/styles.css b/src/jaegertracing/thrift/tutorial/dart/client/web/styles.css new file mode 100644 index 000000000..c0315025b --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/client/web/styles.css @@ -0,0 +1,33 @@ +/* + * 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. + */ +@import url(https://fonts.googleapis.com/css?family=Roboto); + +html, body { + width: 100%; + height: 100%; + margin: 0; + padding: 10px; + font-family: 'Roboto', sans-serif; +} + +h3 { + border-bottom: solid; + border-width: thin; + padding-top: 20px; +} diff --git a/src/jaegertracing/thrift/tutorial/dart/console_client/.analysis_options b/src/jaegertracing/thrift/tutorial/dart/console_client/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/console_client/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/src/jaegertracing/thrift/tutorial/dart/console_client/bin/main.dart b/src/jaegertracing/thrift/tutorial/dart/console_client/bin/main.dart new file mode 100644 index 000000000..fda206ab9 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/console_client/bin/main.dart @@ -0,0 +1,149 @@ +/// 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. + +import 'dart:async'; +import 'dart:io'; + +import 'package:args/args.dart'; +import 'package:logging/logging.dart'; +import 'package:thrift/thrift.dart'; +import 'package:thrift/thrift_console.dart'; +import 'package:tutorial/tutorial.dart'; + +TTransport _transport; +Calculator _calculator; +int logid = 0; + +const Map<String, int> operationLookup = const { + '+': Operation.ADD, + '-': Operation.SUBTRACT, + '*': Operation.MULTIPLY, + '/': Operation.DIVIDE +}; + +main(List<String> args) { + Logger.root.level = Level.ALL; + Logger.root.onRecord.listen((LogRecord rec) { + print('${rec.level.name}: ${rec.time}: ${rec.message}'); + }); + + var parser = new ArgParser(); + parser.addOption('port', defaultsTo: '9090', help: 'The port to connect to'); + + ArgResults results; + try { + results = parser.parse(args); + } catch (e) { + results = null; + } + + if (results == null) { + print(parser.usage); + exit(0); + } + + int port = int.parse(results['port']); + + _initConnection(port).then((_) => _run()); +} + +Future _initConnection(int port) async { + var socket = await Socket.connect('127.0.0.1', port); + _transport = new TAsyncClientSocketTransport( + new TTcpSocket(socket), new TMessageReader(new TBinaryProtocolFactory())); + TProtocol protocol = new TBinaryProtocol(_transport); + await _transport.open(); + + _calculator = new CalculatorClient(protocol); +} + +Future _run() async { + _help(); + + while (true) { + stdout.write("> "); + var input = stdin.readLineSync(); + var parts = input.split(' '); + var command = parts[0]; + var args = parts.length > 1 ? parts.sublist(1) : []; + + switch (command) { + case 'ping': + await _ping(); + break; + + case 'add': + await _add(int.parse(args[0]), int.parse(args[1])); + break; + + case 'calc': + int op = operationLookup[args[1]]; + if (!Operation.VALID_VALUES.contains(op)) { + stdout.writeln('Unknown operator ${args[1]}'); + break; + } + + var work = new Work() + ..num1 = int.parse(args[0]) + ..op = op + ..num2 = int.parse(args[2]) + ..comment = args.length > 3 ? args[3] : ''; + + await _calc(work); + break; + + case 'struct': + await _struct(int.parse(args[0])); + break; + + case 'help': + default: + _help(); + break; + } + } +} + +void _help() { + stdout.writeln('Commands:'); + stdout.writeln(' help'); + stdout.writeln(' ping'); + stdout.writeln(' add x y'); + stdout.writeln(' calc x op y [comment]'); + stdout.writeln(' struct id'); + stdout.writeln(''); +} + +Future _ping() async { + await _calculator.ping(); + stdout.writeln('ping succeeded'); +} + +Future _add(int x, int y) async { + int result = await _calculator.add(x, y); + stdout.writeln('= $result'); +} + +Future _calc(Work work) async { + int result = await _calculator.calculate(logid++, work); + stdout.writeln('= $result'); +} + +Future _struct(int key) async { + var struct = await _calculator.getStruct(key); + stdout.writeln(struct.toString()); +} diff --git a/src/jaegertracing/thrift/tutorial/dart/console_client/pubspec.yaml b/src/jaegertracing/thrift/tutorial/dart/console_client/pubspec.yaml new file mode 100644 index 000000000..ca122d2fd --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/console_client/pubspec.yaml @@ -0,0 +1,36 @@ +# 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. + +name: tutorial_console_client +version: 0.13.0 +description: > + A Dart console client to implementation of the Apache Thrift tutorial +author: Apache Thrift Developers <dev@thrift.apache.org> +homepage: http://thrift.apache.org + +environment: + sdk: ">=1.13.0 <3.0.0" + +dependencies: + args: ">=0.13.0 <2.0.0" + collection: ^1.1.0 + shared: + path: ../gen-dart/shared + thrift: + path: ../../../lib/dart + tutorial: + path: ../gen-dart/tutorial diff --git a/src/jaegertracing/thrift/tutorial/dart/server/.analysis_options b/src/jaegertracing/thrift/tutorial/dart/server/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/server/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/src/jaegertracing/thrift/tutorial/dart/server/bin/main.dart b/src/jaegertracing/thrift/tutorial/dart/server/bin/main.dart new file mode 100644 index 000000000..b8ac30d3d --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/server/bin/main.dart @@ -0,0 +1,163 @@ +/// 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. + +import 'dart:async'; +import 'dart:io'; + +import 'package:args/args.dart'; +import 'package:logging/logging.dart'; +import 'package:thrift/thrift.dart'; +import 'package:thrift/thrift_console.dart'; +import 'package:tutorial/tutorial.dart'; +import 'package:shared/shared.dart'; + +TProtocol _protocol; +TProcessor _processor; +WebSocket _webSocket; + +main(List<String> args) { + Logger.root.level = Level.ALL; + Logger.root.onRecord.listen((LogRecord rec) { + print('${rec.level.name}: ${rec.time}: ${rec.message}'); + }); + + var parser = new ArgParser(); + parser.addOption('port', defaultsTo: '9090', help: 'The port to listen on'); + parser.addOption('type', + defaultsTo: 'ws', + allowed: ['ws', 'tcp'], + help: 'The type of socket', + allowedHelp: {'ws': 'WebSocket', 'tcp': 'TCP Socket'}); + + ArgResults results; + try { + results = parser.parse(args); + } catch (e) { + results = null; + } + + if (results == null) { + print(parser.usage); + exit(0); + } + + int port = int.parse(results['port']); + String socketType = results['type']; + + if (socketType == 'tcp') { + _runTcpServer(port); + } else if (socketType == 'ws') { + _runWebSocketServer(port); + } +} + +Future _runWebSocketServer(int port) async { + var httpServer = await HttpServer.bind('127.0.0.1', port); + print('listening for WebSocket connections on $port'); + + httpServer.listen((HttpRequest request) async { + if (request.uri.path == '/ws') { + _webSocket = await WebSocketTransformer.upgrade(request); + await _initProcessor(new TWebSocket(_webSocket)); + } else { + print('Invalid path: ${request.uri.path}'); + } + }); +} + +Future _runTcpServer(int port) async { + var serverSocket = await ServerSocket.bind('127.0.0.1', port); + print('listening for TCP connections on $port'); + + Socket socket = await serverSocket.first; + await _initProcessor(new TTcpSocket(socket)); +} + +Future _initProcessor(TSocket socket) async { + TServerSocketTransport transport = new TServerSocketTransport(socket); + transport.onIncomingMessage.listen(_processMessage); + _processor = new CalculatorProcessor(new CalculatorServer()); + _protocol = new TBinaryProtocol(transport); + await _protocol.transport.open(); + + print('connected'); +} + +Future _processMessage(_) async { + _processor.process(_protocol, _protocol); +} + +class CalculatorServer implements Calculator { + final Map<int, SharedStruct> _log = {}; + + Future ping() async { + print('ping()'); + } + + Future<int> add(int num1, int num2) async { + print('add($num1, $num2)'); + + return num1 + num2; + } + + Future<int> calculate(int logid, Work work) async { + print('calulate($logid, ${work.toString()})'); + + int val; + + switch (work.op) { + case Operation.ADD: + val = work.num1 + work.num2; + break; + + case Operation.SUBTRACT: + val = work.num1 - work.num2; + break; + + case Operation.MULTIPLY: + val = work.num1 * work.num2; + break; + + case Operation.DIVIDE: + if (work.num2 == 0) { + var x = new InvalidOperation(); + x.whatOp = work.op; + x.why = 'Cannot divide by 0'; + throw x; + } + val = (work.num1 / work.num2).floor(); + break; + } + + var log = new SharedStruct(); + log.key = logid; + log.value = '$val "${work.comment}"'; + this._log[logid] = log; + + return val; + } + + Future zip() async { + print('zip()'); + } + + Future<SharedStruct> getStruct(int key) async { + print('getStruct($key)'); + + return _log[key]; + } +} diff --git a/src/jaegertracing/thrift/tutorial/dart/server/pubspec.yaml b/src/jaegertracing/thrift/tutorial/dart/server/pubspec.yaml new file mode 100644 index 000000000..e09465e70 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/dart/server/pubspec.yaml @@ -0,0 +1,34 @@ +# 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. + +name: tutorial_server +version: 0.13.0 +description: A Dart server to support the Apache Thrift tutorial +author: Apache Thrift Developers <dev@thrift.apache.org> +homepage: http://thrift.apache.org + +environment: + sdk: ">=1.13.0 <3.0.0" + +dependencies: + args: ">=0.13.0 <2.0.0" + shared: + path: ../gen-dart/shared + thrift: + path: ../../../lib/dart + tutorial: + path: ../gen-dart/tutorial diff --git a/src/jaegertracing/thrift/tutorial/delphi/DelphiClient/DelphiClient.dpr b/src/jaegertracing/thrift/tutorial/delphi/DelphiClient/DelphiClient.dpr new file mode 100644 index 000000000..4ea9eb3e9 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/delphi/DelphiClient/DelphiClient.dpr @@ -0,0 +1,117 @@ +(* + * 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. + *) +program DelphiClient; + +{$APPTYPE CONSOLE} +{$D 'Copyright (c) 2012 The Apache Software Foundation'} + +uses + SysUtils, + Generics.Collections, + Thrift in '..\..\..\lib\delphi\src\Thrift.pas', + Thrift.Collections in '..\..\..\lib\delphi\src\Thrift.Collections.pas', + Thrift.Exception in '..\..\..\lib\delphi\src\Thrift.Exception.pas', + Thrift.Utils in '..\..\..\lib\delphi\src\Thrift.Utils.pas', + Thrift.Stream in '..\..\..\lib\delphi\src\Thrift.Stream.pas', + Thrift.Protocol in '..\..\..\lib\delphi\src\Thrift.Protocol.pas', + Thrift.Server in '..\..\..\lib\delphi\src\Thrift.Server.pas', + Thrift.Transport in '..\..\..\lib\delphi\src\Thrift.Transport.pas', + Thrift.Transport.WinHTTP in '..\..\..\lib\delphi\src\Thrift.Transport.WinHTTP.pas', + Thrift.Transport.MsxmlHTTP in '..\..\..\lib\delphi\src\Thrift.Transport.MsxmlHTTP.pas', + Thrift.WinHTTP in '..\..\..\lib\delphi\src\Thrift.WinHTTP.pas', + Shared in '..\..\gen-delphi\Shared.pas', + Tutorial in '..\..\gen-delphi\Tutorial.pas'; + + +type + DelphiTutorialClient = class + public + class procedure Main; + end; + + +//--- DelphiTutorialClient --------------------------------------- + + +class procedure DelphiTutorialClient.Main; +var transport : ITransport; + protocol : IProtocol; + client : TCalculator.Iface; + work : IWork; + sum, quotient, diff : Integer; + log : ISharedStruct; +begin + try + transport := TSocketImpl.Create( 'localhost', 9090); + protocol := TBinaryProtocolImpl.Create( transport); + client := TCalculator.TClient.Create( protocol); + + transport.Open; + + client.ping; + WriteLn('ping()'); + + sum := client.add( 1, 1); + WriteLn( Format( '1+1=%d', [sum])); + + work := TWorkImpl.Create; + + work.Op := TOperation.DIVIDE; + work.Num1 := 1; + work.Num2 := 0; + try + quotient := client.calculate(1, work); + WriteLn( 'Whoa we can divide by 0'); + WriteLn( Format('1/0=%d',[quotient])); + except + on io: TInvalidOperation + do WriteLn( 'Invalid operation: ' + io.Why); + end; + + work.Op := TOperation.SUBTRACT; + work.Num1 := 15; + work.Num2 := 10; + try + diff := client.calculate( 1, work); + WriteLn( Format('15-10=%d', [diff])); + except + on io: TInvalidOperation + do WriteLn( 'Invalid operation: ' + io.Why); + end; + + log := client.getStruct(1); + WriteLn( Format( 'Check log: %s', [log.Value])); + + transport.Close(); + + except + on e : Exception + do WriteLn( e.ClassName+': '+e.Message); + end; +end; + + +begin + try + DelphiTutorialClient.Main; + except + on E: Exception do + Writeln(E.ClassName, ': ', E.Message); + end; +end. diff --git a/src/jaegertracing/thrift/tutorial/delphi/DelphiClient/DelphiClient.dproj b/src/jaegertracing/thrift/tutorial/delphi/DelphiClient/DelphiClient.dproj new file mode 100644 index 000000000..7026747d0 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/delphi/DelphiClient/DelphiClient.dproj @@ -0,0 +1,122 @@ + <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <ProjectGuid>{2B8FB3A1-2F9E-4883-8C53-0F56220B34F6}</ProjectGuid> + <MainSource>DelphiClient.dpr</MainSource> + <ProjectVersion>12.3</ProjectVersion> + <Basis>True</Basis> + <Config Condition="'$(Config)'==''">Debug</Config> + <Platform>Win32</Platform> + <AppType>Console</AppType> + <FrameworkType>None</FrameworkType> + <DCC_DCCCompiler>DCC32</DCC_DCCCompiler> + </PropertyGroup> + <PropertyGroup Condition="'$(Config)'=='Basis' or '$(Base)'!=''"> + <Base>true</Base> + </PropertyGroup> + <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''"> + <Cfg_1>true</Cfg_1> + <CfgParent>Base</CfgParent> + <Base>true</Base> + </PropertyGroup> + <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''"> + <Cfg_2>true</Cfg_2> + <CfgParent>Base</CfgParent> + <Base>true</Base> + </PropertyGroup> + <PropertyGroup Condition="'$(Base)'!=''"> + <DCC_UnitSearchPath>..\..\..\lib\delphi\src;$(DCC_UnitSearchPath)</DCC_UnitSearchPath> + <DCC_ImageBase>00400000</DCC_ImageBase> + <DCC_DcuOutput>.\dcu\$(Config)\$(Platform)</DCC_DcuOutput> + <DCC_UnitAlias>WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias)</DCC_UnitAlias> + <DCC_ExeOutput>..\bin\$(Config)\$(Platform)</DCC_ExeOutput> + <DCC_E>false</DCC_E> + <DCC_N>false</DCC_N> + <DCC_S>false</DCC_S> + <DCC_F>false</DCC_F> + <DCC_K>false</DCC_K> + </PropertyGroup> + <PropertyGroup Condition="'$(Cfg_1)'!=''"> + <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define> + <DCC_Optimize>false</DCC_Optimize> + <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames> + </PropertyGroup> + <PropertyGroup Condition="'$(Cfg_2)'!=''"> + <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols> + <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define> + <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo> + <DCC_DebugInformation>false</DCC_DebugInformation> + </PropertyGroup> + <ItemGroup> + <DelphiCompile Include="DelphiClient.dpr"> + <MainSource>MainSource</MainSource> + </DelphiCompile> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Collections.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Exception.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Utils.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Stream.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Protocol.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Server.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Transport.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Transport.WinHTTP.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Transport.MsxmlHTTP.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.WinHTTP.pas"/> + <DCCReference Include="..\..\gen-delphi\Shared.pas"/> + <DCCReference Include="..\..\gen-delphi\Tutorial.pas"/> + <BuildConfiguration Include="Release"> + <Key>Cfg_2</Key> + <CfgParent>Base</CfgParent> + </BuildConfiguration> + <BuildConfiguration Include="Basis"> + <Key>Base</Key> + </BuildConfiguration> + <BuildConfiguration Include="Debug"> + <Key>Cfg_1</Key> + <CfgParent>Base</CfgParent> + </BuildConfiguration> + </ItemGroup> + <Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/> + <Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/> + <ProjectExtensions> + <Borland.Personality>Delphi.Personality.12</Borland.Personality> + <Borland.ProjectType/> + <BorlandProject> + <Delphi.Personality> + <VersionInfo> + <VersionInfo Name="IncludeVerInfo">True</VersionInfo> + <VersionInfo Name="AutoIncBuild">False</VersionInfo> + <VersionInfo Name="MajorVer">0</VersionInfo> + <VersionInfo Name="MinorVer">12</VersionInfo> + <VersionInfo Name="Release">0</VersionInfo> + <VersionInfo Name="Build">0</VersionInfo> + <VersionInfo Name="Debug">False</VersionInfo> + <VersionInfo Name="PreRelease">False</VersionInfo> + <VersionInfo Name="Special">False</VersionInfo> + <VersionInfo Name="Private">False</VersionInfo> + <VersionInfo Name="DLL">False</VersionInfo> + <VersionInfo Name="Locale">1033</VersionInfo> + <VersionInfo Name="CodePage">1252</VersionInfo> + </VersionInfo> + <VersionInfoKeys> + <VersionInfoKeys Name="CompanyName"/> + <VersionInfoKeys Name="FileDescription">Thrift Tutorial</VersionInfoKeys> + <VersionInfoKeys Name="FileVersion">0.13.0.0</VersionInfoKeys> + <VersionInfoKeys Name="InternalName">DelphiClient</VersionInfoKeys> + <VersionInfoKeys Name="LegalCopyright">Copyright © 2012 The Apache Software Foundation</VersionInfoKeys> + <VersionInfoKeys Name="LegalTrademarks"/> + <VersionInfoKeys Name="OriginalFilename">DelphiClient.exe</VersionInfoKeys> + <VersionInfoKeys Name="ProductName">Thrift</VersionInfoKeys> + <VersionInfoKeys Name="ProductVersion">0.13.0.0</VersionInfoKeys> + <VersionInfoKeys Name="Comments"/> + </VersionInfoKeys> + <Source> + <Source Name="MainSource">DelphiClient.dpr</Source> + </Source> + </Delphi.Personality> + <Platforms> + <Platform value="Win32">True</Platform> + </Platforms> + </BorlandProject> + <ProjectFileVersion>12</ProjectFileVersion> + </ProjectExtensions> + </Project> diff --git a/src/jaegertracing/thrift/tutorial/delphi/DelphiServer/DelphiServer.dpr b/src/jaegertracing/thrift/tutorial/delphi/DelphiServer/DelphiServer.dpr new file mode 100644 index 000000000..fc9997a3f --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/delphi/DelphiServer/DelphiServer.dpr @@ -0,0 +1,174 @@ +(* + * 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. + *) +program DelphiServer; + +{$APPTYPE CONSOLE} +{$D 'Copyright (c) 2012 The Apache Software Foundation'} + +{$Q+} // throws exceptions on numeric overflows + +uses + SysUtils, + Generics.Collections, + Thrift in '..\..\..\lib\delphi\src\Thrift.pas', + Thrift.Collections in '..\..\..\lib\delphi\src\Thrift.Collections.pas', + Thrift.Exception in '..\..\..\lib\delphi\src\Thrift.Exception.pas', + Thrift.Utils in '..\..\..\lib\delphi\src\Thrift.Utils.pas', + Thrift.Stream in '..\..\..\lib\delphi\src\Thrift.Stream.pas', + Thrift.Protocol in '..\..\..\lib\delphi\src\Thrift.Protocol.pas', + Thrift.Server in '..\..\..\lib\delphi\src\Thrift.Server.pas', + Thrift.Transport in '..\..\..\lib\delphi\src\Thrift.Transport.pas', + Thrift.WinHTTP in '..\..\..\lib\delphi\src\Thrift.WinHTTP.pas', + Shared in '..\..\gen-delphi\Shared.pas', + Tutorial in '..\..\gen-delphi\Tutorial.pas'; + + +type + TCalculatorHandler = class( TInterfacedObject, TCalculator.Iface) + protected + FLog : TDictionary< Integer, ISharedStruct>; + + // TSharedService.Iface + function getStruct(key: Integer): ISharedStruct; + + // TCalculator.Iface + procedure ping(); + function add(num1: Integer; num2: Integer): Integer; + function calculate(logid: Integer; const w: IWork): Integer; + procedure zip(); + + public + constructor Create; + destructor Destroy; override; + + end; + + DelphiTutorialServer = class + public + class procedure Main; + end; + + +//--- TCalculatorHandler --------------------------------------------------- + + +constructor TCalculatorHandler.Create; +begin + inherited Create; + FLog := TDictionary< Integer, ISharedStruct>.Create(); +end; + + +destructor TCalculatorHandler.Destroy; +begin + try + FreeAndNil( FLog); + finally + inherited Destroy; + end; +end; + + +procedure TCalculatorHandler.ping; +begin + WriteLn( 'ping()'); +end; + + +function TCalculatorHandler.add(num1: Integer; num2: Integer): Integer; +begin + WriteLn( Format( 'add( %d, %d)', [num1, num2])); + result := num1 + num2; +end; + + +function TCalculatorHandler.calculate(logid: Integer; const w: IWork): Integer; +var entry : ISharedStruct; +begin + try + WriteLn( Format('calculate( %d, [%d,%d,%d])', [logid, Ord(w.Op), w.Num1, w.Num2])); + + case w.Op of + TOperation.ADD : result := w.Num1 + w.Num2; + TOperation.SUBTRACT : result := w.Num1 - w.Num2; + TOperation.MULTIPLY : result := w.Num1 * w.Num2; + TOperation.DIVIDE : result := Round( w.Num1 / w.Num2); + else + raise TInvalidOperation.Create( Ord(w.Op), 'Unknown operation'); + end; + + except + on e:Thrift.TException do raise; // let Thrift Exceptions pass through + on e:Exception do raise TInvalidOperation.Create( Ord(w.Op), e.Message); // repackage all other + end; + + entry := TSharedStructImpl.Create; + entry.Key := logid; + entry.Value := IntToStr( result); + FLog.AddOrSetValue( logid, entry); +end; + + +function TCalculatorHandler.getStruct(key: Integer): ISharedStruct; +begin + WriteLn( Format( 'getStruct(%d)', [key])); + result := FLog[key]; +end; + + +procedure TCalculatorHandler.zip; +begin + WriteLn( 'zip()'); +end; + + +//--- DelphiTutorialServer ---------------------------------------------------------------------- + + +class procedure DelphiTutorialServer.Main; +var handler : TCalculator.Iface; + processor : IProcessor; + transport : IServerTransport; + server : IServer; +begin + try + handler := TCalculatorHandler.Create; + processor := TCalculator.TProcessorImpl.Create( handler); + transport := TServerSocketImpl.Create( 9090); + server := TSimpleServer.Create( processor, transport); + + WriteLn( 'Starting the server...'); + server.Serve(); + + except + on e: Exception do WriteLn( e.Message); + end; + + WriteLn('done.'); +end; + + +begin + try + DelphiTutorialServer.Main; + except + on E: Exception do + Writeln(E.ClassName, ': ', E.Message); + end; +end. diff --git a/src/jaegertracing/thrift/tutorial/delphi/DelphiServer/DelphiServer.dproj b/src/jaegertracing/thrift/tutorial/delphi/DelphiServer/DelphiServer.dproj new file mode 100644 index 000000000..ec1da2e69 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/delphi/DelphiServer/DelphiServer.dproj @@ -0,0 +1,119 @@ + <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <ProjectGuid>{2B8FB3A1-2F9E-4883-8C53-0F56220B34F6}</ProjectGuid> + <MainSource>DelphiServer.dpr</MainSource> + <ProjectVersion>12.3</ProjectVersion> + <Basis>True</Basis> + <Config Condition="'$(Config)'==''">Debug</Config> + <Platform>Win32</Platform> + <AppType>Console</AppType> + <FrameworkType>None</FrameworkType> + <DCC_DCCCompiler>DCC32</DCC_DCCCompiler> + </PropertyGroup> + <PropertyGroup Condition="'$(Config)'=='Basis' or '$(Base)'!=''"> + <Base>true</Base> + </PropertyGroup> + <PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''"> + <Cfg_1>true</Cfg_1> + <CfgParent>Base</CfgParent> + <Base>true</Base> + </PropertyGroup> + <PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''"> + <Cfg_2>true</Cfg_2> + <CfgParent>Base</CfgParent> + <Base>true</Base> + </PropertyGroup> + <PropertyGroup Condition="'$(Base)'!=''"> + <DCC_ImageBase>00400000</DCC_ImageBase> + <DCC_DcuOutput>.\dcu\$(Config)\$(Platform)</DCC_DcuOutput> + <DCC_UnitAlias>WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias)</DCC_UnitAlias> + <DCC_ExeOutput>..\bin\$(Config)\$(Platform)</DCC_ExeOutput> + <DCC_E>false</DCC_E> + <DCC_N>false</DCC_N> + <DCC_S>false</DCC_S> + <DCC_F>false</DCC_F> + <DCC_K>false</DCC_K> + </PropertyGroup> + <PropertyGroup Condition="'$(Cfg_1)'!=''"> + <DCC_Define>DEBUG;$(DCC_Define)</DCC_Define> + <DCC_Optimize>false</DCC_Optimize> + <DCC_GenerateStackFrames>true</DCC_GenerateStackFrames> + </PropertyGroup> + <PropertyGroup Condition="'$(Cfg_2)'!=''"> + <DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols> + <DCC_Define>RELEASE;$(DCC_Define)</DCC_Define> + <DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo> + <DCC_DebugInformation>false</DCC_DebugInformation> + </PropertyGroup> + <ItemGroup> + <DelphiCompile Include="DelphiServer.dpr"> + <MainSource>MainSource</MainSource> + </DelphiCompile> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Collections.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Exception.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Utils.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Stream.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Protocol.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Server.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.Transport.pas"/> + <DCCReference Include="..\..\..\lib\delphi\src\Thrift.WinHTTP.pas"/> + <DCCReference Include="..\..\gen-delphi\Shared.pas"/> + <DCCReference Include="..\..\gen-delphi\Tutorial.pas"/> + <BuildConfiguration Include="Release"> + <Key>Cfg_2</Key> + <CfgParent>Base</CfgParent> + </BuildConfiguration> + <BuildConfiguration Include="Basis"> + <Key>Base</Key> + </BuildConfiguration> + <BuildConfiguration Include="Debug"> + <Key>Cfg_1</Key> + <CfgParent>Base</CfgParent> + </BuildConfiguration> + </ItemGroup> + <Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/> + <Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/> + <ProjectExtensions> + <Borland.Personality>Delphi.Personality.12</Borland.Personality> + <Borland.ProjectType/> + <BorlandProject> + <Delphi.Personality> + <VersionInfo> + <VersionInfo Name="IncludeVerInfo">True</VersionInfo> + <VersionInfo Name="AutoIncBuild">False</VersionInfo> + <VersionInfo Name="MajorVer">0</VersionInfo> + <VersionInfo Name="MinorVer">12</VersionInfo> + <VersionInfo Name="Release">0</VersionInfo> + <VersionInfo Name="Build">0</VersionInfo> + <VersionInfo Name="Debug">False</VersionInfo> + <VersionInfo Name="PreRelease">False</VersionInfo> + <VersionInfo Name="Special">False</VersionInfo> + <VersionInfo Name="Private">False</VersionInfo> + <VersionInfo Name="DLL">False</VersionInfo> + <VersionInfo Name="Locale">1033</VersionInfo> + <VersionInfo Name="CodePage">1252</VersionInfo> + </VersionInfo> + <VersionInfoKeys> + <VersionInfoKeys Name="CompanyName"/> + <VersionInfoKeys Name="FileDescription">Thrift Tutorial</VersionInfoKeys> + <VersionInfoKeys Name="FileVersion">0.13.0.0</VersionInfoKeys> + <VersionInfoKeys Name="InternalName">DelphiServer</VersionInfoKeys> + <VersionInfoKeys Name="LegalCopyright">Copyright © 2012 The Apache Software Foundation</VersionInfoKeys> + <VersionInfoKeys Name="LegalTrademarks"/> + <VersionInfoKeys Name="OriginalFilename">DelphiServer.exe</VersionInfoKeys> + <VersionInfoKeys Name="ProductName">Thrift</VersionInfoKeys> + <VersionInfoKeys Name="ProductVersion">0.13.0.0</VersionInfoKeys> + <VersionInfoKeys Name="Comments"/> + </VersionInfoKeys> + <Source> + <Source Name="MainSource">DelphiServer.dpr</Source> + </Source> + </Delphi.Personality> + <Platforms> + <Platform value="Win32">True</Platform> + </Platforms> + </BorlandProject> + <ProjectFileVersion>12</ProjectFileVersion> + </ProjectExtensions> + </Project> diff --git a/src/jaegertracing/thrift/tutorial/delphi/Tutorial.groupproj b/src/jaegertracing/thrift/tutorial/delphi/Tutorial.groupproj new file mode 100644 index 000000000..3a2a23751 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/delphi/Tutorial.groupproj @@ -0,0 +1,48 @@ + <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <ProjectGuid>{3D042C7F-3EF2-4574-8304-AB7FB79F814C}</ProjectGuid> + </PropertyGroup> + <ItemGroup> + <Projects Include="DelphiServer\DelphiServer.dproj"> + <Dependencies/> + </Projects> + <Projects Include="DelphiClient\DelphiClient.dproj"> + <Dependencies/> + </Projects> + </ItemGroup> + <ProjectExtensions> + <Borland.Personality>Default.Personality.12</Borland.Personality> + <Borland.ProjectType/> + <BorlandProject> + <Default.Personality/> + </BorlandProject> + </ProjectExtensions> + <Target Name="DelphiServer"> + <MSBuild Projects="DelphiServer\DelphiServer.dproj"/> + </Target> + <Target Name="DelphiServer:Clean"> + <MSBuild Projects="DelphiServer\DelphiServer.dproj" Targets="Clean"/> + </Target> + <Target Name="DelphiServer:Make"> + <MSBuild Projects="DelphiServer\DelphiServer.dproj" Targets="Make"/> + </Target> + <Target Name="DelphiClient"> + <MSBuild Projects="DelphiClient\DelphiClient.dproj"/> + </Target> + <Target Name="DelphiClient:Clean"> + <MSBuild Projects="DelphiClient\DelphiClient.dproj" Targets="Clean"/> + </Target> + <Target Name="DelphiClient:Make"> + <MSBuild Projects="DelphiClient\DelphiClient.dproj" Targets="Make"/> + </Target> + <Target Name="Build"> + <CallTarget Targets="DelphiServer;DelphiClient"/> + </Target> + <Target Name="Clean"> + <CallTarget Targets="DelphiServer:Clean;DelphiClient:Clean"/> + </Target> + <Target Name="Make"> + <CallTarget Targets="DelphiServer:Make;DelphiClient:Make"/> + </Target> + <Import Condition="Exists('$(BDS)\Bin\CodeGear.Group.Targets')" Project="$(BDS)\Bin\CodeGear.Group.Targets"/> + </Project> diff --git a/src/jaegertracing/thrift/tutorial/erl/README.md b/src/jaegertracing/thrift/tutorial/erl/README.md new file mode 100644 index 000000000..9d17cd0c5 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/erl/README.md @@ -0,0 +1,8 @@ +To try things out, run + +% ./server.sh +Erlang R14B (erts-5.8.1) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false] + +Eshell V5.8.1 (abort with ^G) +> server:start(). +> client:t(). diff --git a/src/jaegertracing/thrift/tutorial/erl/client.erl b/src/jaegertracing/thrift/tutorial/erl/client.erl new file mode 100644 index 000000000..037422085 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/erl/client.erl @@ -0,0 +1,78 @@ +%% +%% 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. +%% + +-module(client). + +-include("calculator_thrift.hrl"). + +-export([t/0]). + +p(X) -> + io:format("~p~n", [X]), + ok. + +t() -> + Port = 9090, + + {ok, Client0} = thrift_client_util:new("127.0.0.1", + Port, + calculator_thrift, + []), + + {Client1, {ok, ok}} = thrift_client:call(Client0, ping, []), + io:format("ping~n", []), + + {Client2, {ok, Sum}} = thrift_client:call(Client1, add, [1, 1]), + io:format("1+1=~p~n", [Sum]), + + {Client3, {ok, Sum1}} = thrift_client:call(Client2, add, [1, 4]), + io:format("1+4=~p~n", [Sum1]), + + Work = #'Work'{op=?TUTORIAL_OPERATION_SUBTRACT, + num1=15, + num2=10}, + {Client4, {ok, Diff}} = thrift_client:call(Client3, calculate, [1, Work]), + io:format("15-10=~p~n", [Diff]), + + {Client5, {ok, Log}} = thrift_client:call(Client4, getStruct, [1]), + io:format("Log: ~p~n", [Log]), + + Client6 = + try + Work1 = #'Work'{op=?TUTORIAL_OPERATION_DIVIDE, + num1=1, + num2=0}, + {ClientS1, {ok, _Quot}} = thrift_client:call(Client5, calculate, [2, Work1]), + + io:format("LAME: exception handling is broken~n", []), + ClientS1 + catch + throw:{ClientS2, Z} -> + io:format("Got exception where expecting - the " ++ + "following is NOT a problem!!!~n"), + p(Z), + ClientS2 + end, + + + {Client7, {ok, ok}} = thrift_client:call(Client6, zip, []), + io:format("zip~n", []), + + {_Client8, ok} = thrift_client:close(Client7), + ok. diff --git a/src/jaegertracing/thrift/tutorial/erl/client.sh b/src/jaegertracing/thrift/tutorial/erl/client.sh new file mode 100755 index 000000000..775afb62d --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/erl/client.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +# +# 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. +# + +ERL_THRIFT=../../lib/erl + +if ! [ -d ${ERL_THRIFT}/ebin ]; then + echo "Please build the Thrift library by running \`make' in ${ERL_THRIFT}" + exit 1 +fi + +if ! [ -d gen-erl ]; then + ../../compiler/cpp/thrift -r --gen erl ../tutorial.thrift +fi + + +erlc -I ${ERL_THRIFT}/include -I ${ERL_THRIFT}/ebin \ + -I gen-erl -o gen-erl gen-erl/*.erl && + erlc -I ${ERL_THRIFT}/include -I gen-erl *.erl && + erl +K true -pa ${ERL_THRIFT}/ebin -pa gen-erl diff --git a/src/jaegertracing/thrift/tutorial/erl/json_client.erl b/src/jaegertracing/thrift/tutorial/erl/json_client.erl new file mode 100644 index 000000000..0b39ceda9 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/erl/json_client.erl @@ -0,0 +1,89 @@ +%% +%% 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. +%% +%% The JSON protocol over HTTP implementation was created by +%% Peter Neumark <neumark.peter@gmail.com> based on +%% the binary protocol + socket tutorial. Use with the same server +%% that the Javascript tutorial uses! + +-module(json_client). + +-include("calculator_thrift.hrl"). + +-export([t/0]). + +%% Client constructor for the http transports +%% with the json protocol +new_client(Host, Path, Service, _Options) -> + {ProtoOpts, TransOpts} = {[],[]}, + TransportFactory = fun() -> thrift_http_transport:new(Host, Path, TransOpts) end, + {ok, ProtocolFactory} = thrift_json_protocol:new_protocol_factory( + TransportFactory, ProtoOpts), + {ok, Protocol} = ProtocolFactory(), + thrift_client:new(Protocol, Service). + +p(X) -> + io:format("~p~n", [X]), + ok. + +t() -> + inets:start(), + {ok, Client0} = new_client("127.0.0.1:8088", "/thrift/service/tutorial/", + calculator_thrift, + []), + {Client1, {ok, ok}} = thrift_client:call(Client0, ping, []), + io:format("ping~n", []), + + {Client2, {ok, Sum}} = thrift_client:call(Client1, add, [1, 1]), + io:format("1+1=~p~n", [Sum]), + + {Client3, {ok, Sum1}} = thrift_client:call(Client2, add, [1, 4]), + io:format("1+4=~p~n", [Sum1]), + + Work = #'Work'{op=?TUTORIAL_OPERATION_SUBTRACT, + num1=15, + num2=10}, + {Client4, {ok, Diff}} = thrift_client:call(Client3, calculate, [1, Work]), + io:format("15-10=~p~n", [Diff]), + + {Client5, {ok, Log}} = thrift_client:call(Client4, getStruct, [1]), + io:format("Log: ~p~n", [Log]), + + Client6 = + try + Work1 = #'Work'{op=?TUTORIAL_OPERATION_DIVIDE, + num1=1, + num2=0}, + {ClientS1, {ok, _Quot}} = thrift_client:call(Client5, calculate, [2, Work1]), + + io:format("LAME: exception handling is broken~n", []), + ClientS1 + catch + throw:{ClientS2, Z} -> + io:format("Got exception where expecting - the " ++ + "following is NOT a problem!!!~n"), + p(Z), + ClientS2 + end, + + + {Client7, {ok, ok}} = thrift_client:call(Client6, zip, []), + io:format("zip~n", []), + + {_Client8, ok} = thrift_client:close(Client7), + ok. diff --git a/src/jaegertracing/thrift/tutorial/erl/server.erl b/src/jaegertracing/thrift/tutorial/erl/server.erl new file mode 100644 index 000000000..647cc2474 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/erl/server.erl @@ -0,0 +1,82 @@ +%% +%% 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. +%% + +-module(server). + +-include("calculator_thrift.hrl"). + +-export([start/0, start/1, handle_function/2, + stop/1, ping/0, add/2, calculate/2, getStruct/1, zip/0]). + +debug(Format, Data) -> + error_logger:info_msg(Format, Data). + +ping() -> + debug("ping()",[]), + ok. + +add(N1, N2) -> + debug("add(~p,~p)",[N1,N2]), + N1+N2. + +calculate(Logid, Work) -> + { Op, Num1, Num2 } = { Work#'Work'.op, Work#'Work'.num1, Work#'Work'.num2 }, + debug("calculate(~p, {~p,~p,~p})", [Logid, Op, Num1, Num2]), + case Op of + ?TUTORIAL_OPERATION_ADD -> Num1 + Num2; + ?TUTORIAL_OPERATION_SUBTRACT -> Num1 - Num2; + ?TUTORIAL_OPERATION_MULTIPLY -> Num1 * Num2; + + ?TUTORIAL_OPERATION_DIVIDE when Num2 == 0 -> + throw(#'InvalidOperation'{whatOp=Op, why="Cannot divide by 0"}); + ?TUTORIAL_OPERATION_DIVIDE -> + Num1 div Num2; + + _Else -> + throw(#'InvalidOperation'{whatOp=Op, why="Invalid operation"}) + end. + +getStruct(Key) -> + debug("getStruct(~p)", [Key]), + #'SharedStruct'{key=Key, value="RARG"}. + +zip() -> + debug("zip", []), + ok. + +%% + +start() -> + start(9090). + +start(Port) -> + Handler = ?MODULE, + thrift_socket_server:start([{handler, Handler}, + {service, calculator_thrift}, + {port, Port}, + {name, tutorial_server}]). + +stop(Server) -> + thrift_socket_server:stop(Server). + +handle_function(Function, Args) when is_atom(Function), is_tuple(Args) -> + case apply(?MODULE, Function, tuple_to_list(Args)) of + ok -> ok; + Reply -> {reply, Reply} + end. diff --git a/src/jaegertracing/thrift/tutorial/erl/server.sh b/src/jaegertracing/thrift/tutorial/erl/server.sh new file mode 100755 index 000000000..775afb62d --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/erl/server.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +# +# 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. +# + +ERL_THRIFT=../../lib/erl + +if ! [ -d ${ERL_THRIFT}/ebin ]; then + echo "Please build the Thrift library by running \`make' in ${ERL_THRIFT}" + exit 1 +fi + +if ! [ -d gen-erl ]; then + ../../compiler/cpp/thrift -r --gen erl ../tutorial.thrift +fi + + +erlc -I ${ERL_THRIFT}/include -I ${ERL_THRIFT}/ebin \ + -I gen-erl -o gen-erl gen-erl/*.erl && + erlc -I ${ERL_THRIFT}/include -I gen-erl *.erl && + erl +K true -pa ${ERL_THRIFT}/ebin -pa gen-erl diff --git a/src/jaegertracing/thrift/tutorial/go/Makefile.am b/src/jaegertracing/thrift/tutorial/go/Makefile.am new file mode 100644 index 000000000..bd57d656f --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/go/Makefile.am @@ -0,0 +1,59 @@ +# +# 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. +# + +gen-go/tutorial/calculator.go gen-go/shared/shared_service.go: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen go$(COMPILER_EXTRAFLAG) -r $< + +all-local: gen-go/tutorial/calculator.go + +check: src/github.com/apache/thrift/lib/go/thrift thirdparty-dep + $(THRIFT) -r --gen go$(COMPILER_EXTRAFLAG) $(top_srcdir)/tutorial/tutorial.thrift + cp -r gen-go/* src/ + GOPATH=`pwd` $(GO) build -o go-tutorial ./src + GOPATH=`pwd` $(GO) build -o calculator-remote src/tutorial/calculator-remote/calculator-remote.go + +src/github.com/apache/thrift/lib/go/thrift: + mkdir -p src/github.com/apache/thrift/lib/go + ln -sf $(realpath $(top_srcdir)/lib/go/thrift) src/github.com/apache/thrift/lib/go/thrift + +thirdparty-dep: + +tutorialserver: all + GOPATH=`pwd` $(GO) run src/*.go -server=true + +tutorialclient: all + GOPATH=`pwd` $(GO) run src/*.go + +tutorialsecureserver: all + GOPATH=`pwd` $(GO) run src/*.go -server=true -secure=true + +tutorialsecureclient: all + GOPATH=`pwd` $(GO) run src/*.go -secure=true + +clean-local: + $(RM) -r gen-* src/shared src/tutorial src/git.apache.org go-tutorial calculator-remote + +EXTRA_DIST = \ + src/client.go \ + src/handler.go \ + src/server.go \ + src/main.go \ + server.crt \ + server.key + diff --git a/src/jaegertracing/thrift/tutorial/go/server.crt b/src/jaegertracing/thrift/tutorial/go/server.crt new file mode 100644 index 000000000..8a5ef3c3a --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/go/server.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIENzCCAx+gAwIBAgIJAOYfYfw7NCOcMA0GCSqGSIb3DQEBBQUAMIGxMQswCQYD +VQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDASBgNVBAcMC0ZvcmVzdCBIaWxs +MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFjAUBgNV +BAsMDUFwYWNoZSBUaHJpZnQxEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3 +DQEJARYVZGV2QHRocmlmdC5hcGFjaGUub3JnMB4XDTE0MDQwNzE4NTgwMFoXDTIy +MDYyNDE4NTgwMFowgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEU +MBIGA1UEBwwLRm9yZXN0IEhpbGwxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdh +cmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIFRocmlmdDESMBAGA1UEAwwJ +bG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqE9TE9wEXp5LRtLQVDSGQ +GV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCySN8I2Xw6 +L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/HjKNg6ZKg +2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQBGmZmMIUw +AinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xku62LipkX +wCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDmtrhVQF4n +AgMBAAGjUDBOMB0GA1UdDgQWBBQo8v0wzQPx3EEexJPGlxPK1PpgKjAfBgNVHSME +GDAWgBQo8v0wzQPx3EEexJPGlxPK1PpgKjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3 +DQEBBQUAA4IBAQBGFRiJslcX0aJkwZpzTwSUdgcfKbpvNEbCNtVohfQVTI4a/oN5 +U+yqDZJg3vOaOuiAZqyHcIlZ8qyesCgRN314Tl4/JQ++CW8mKj1meTgo5YFxcZYm +T9vsI3C+Nzn84DINgI9mx6yktIt3QOKZRDpzyPkUzxsyJ8J427DaimDrjTR+fTwD +1Dh09xeeMnSa5zeV1HEDyJTqCXutLetwQ/IyfmMBhIx+nvB5f67pz/m+Dv6V0r3I +p4HCcdnDUDGJbfqtoqsAATQQWO+WWuswB6mOhDbvPTxhRpZq6AkgWqv4S+u3M2GO +r5p9FrBgavAw5bKO54C0oQKpN/5fta5l6Ws0 +-----END CERTIFICATE----- diff --git a/src/jaegertracing/thrift/tutorial/go/server.key b/src/jaegertracing/thrift/tutorial/go/server.key new file mode 100644 index 000000000..263cfce59 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/go/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCqE9TE9wEXp5LR +tLQVDSGQGV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCy +SN8I2Xw6L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/H +jKNg6ZKg2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQB +GmZmMIUwAinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xk +u62LipkXwCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDm +trhVQF4nAgMBAAECggEAW/y52YYW6ypROGbZ94DQpFV0kLO7qT8q0Ksxw5sPNaIt +fEPRIymDa8ikyHWJS5Oxmw84wo5jnJV26jaLmwe2Lupq7Xf1lqej8f5LJtuv7cQR +xfzp1vM65KJFFJHp6WqjGqJ6HSSZOpVDsnQYcXQjQCdpyAmaSWd3p+FqYSZ1mQmD +bFNI7jqpczWSZhTdotQ7p7Hn9TVCehflP3yGIB3bQ+wCcCB85dOBz201L+YgaIck +Sz43A4NvWaQIRLRDw7s9GW4jY5T0Jv282WIeAlVpVxLIwu48r4R4yGTIx9Ydowvq +57+Y5iPPjAXxu0V9t00oS3bYxDaKh2DUfc/5zowq8QKBgQDYNVPXmaG0aIH4vjQ9 +7fRdw/UDkYcQbn6CnglQOu77/S8ogQzpKCVJgJgkZNqOVtQMEPzekGEcLTbje1gU +8Bky2k+PL9UwbFy0emnOVh4rqrNXHsRvJcehNT/PRb5hjF3MUMFV/0iD4b+naFaE +jrSWiZ2ZXj2qfwAK52GFbtOuBQKBgQDJYQuGiY0r22E4waJmCSKczoBT3cwlVzWj +V2ljgA9RHLNTVkvNNYQLGu2qngFrtwpeaSnsMDerVG4wKAQWyCnYzxVrlnC4uDrJ +HXuFEltBWi9Ffbgfsnd3749AT0oBP1NT2tMleguyf5DFgjCR3VRJLdrVaaZ8row/ +LqKcFMqnOwKBgB+OIO99l7E584Y3VG6ZdSneOLtNmRXX2pT7tcZE465ZdHGH7Dd3 +SYHhx9K/+Xn+yDH+pLli/xlarAEldmSP6k2WuTfftlC78AfTOfAId5zN7CDR9791 +Fx67I9X/itq33tS8EIuZl57P6uXm/4GXRloWOa8xpvRkVsBApuYPl8t1AoGATQDS +y2sllDObBXzlgGbV2WgNIgSZ311toTv3jJiXQsjauW8yJRHln+l4H9mzaWDgkiFc +ang1kUoDqF5k0eFQPxtQcYdhKwEnWWfwp33RbzfxA32DPnubuzzbZhfrkHaKgnIW +cyor9uFYlm2l7ODZLfJez2RKyTplXnOSsmQw6akCgYAz3dj9Hskyj+HVJ+ht1OcE +c7ai/ESkSA7Vajp0tjJp0EKjW/zq8DvUSXOtcdnJgkKycFluLwbmnaN4txBds1C1 +Qr8Rt2sUCCBNZe1L6DHe3XBdbkJe9sgZVNTjtUSQrzy8UhvsCqG4YWeCu07Szcbc +rdPUV9/uQkdx8VrShxlD8A== +-----END PRIVATE KEY----- diff --git a/src/jaegertracing/thrift/tutorial/go/src/client.go b/src/jaegertracing/thrift/tutorial/go/src/client.go new file mode 100644 index 000000000..e3ebe00df --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/go/src/client.go @@ -0,0 +1,108 @@ +package main + +/* + * 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. + */ + +import ( + "context" + "crypto/tls" + "fmt" + "tutorial" + + "github.com/apache/thrift/lib/go/thrift" +) + +var defaultCtx = context.Background() + +func handleClient(client *tutorial.CalculatorClient) (err error) { + client.Ping(defaultCtx) + fmt.Println("ping()") + + sum, _ := client.Add(defaultCtx, 1, 1) + fmt.Print("1+1=", sum, "\n") + + work := tutorial.NewWork() + work.Op = tutorial.Operation_DIVIDE + work.Num1 = 1 + work.Num2 = 0 + quotient, err := client.Calculate(defaultCtx, 1, work) + if err != nil { + switch v := err.(type) { + case *tutorial.InvalidOperation: + fmt.Println("Invalid operation:", v) + default: + fmt.Println("Error during operation:", err) + } + return err + } else { + fmt.Println("Whoa we can divide by 0 with new value:", quotient) + } + + work.Op = tutorial.Operation_SUBTRACT + work.Num1 = 15 + work.Num2 = 10 + diff, err := client.Calculate(defaultCtx, 1, work) + if err != nil { + switch v := err.(type) { + case *tutorial.InvalidOperation: + fmt.Println("Invalid operation:", v) + default: + fmt.Println("Error during operation:", err) + } + return err + } else { + fmt.Print("15-10=", diff, "\n") + } + + log, err := client.GetStruct(defaultCtx, 1) + if err != nil { + fmt.Println("Unable to get struct:", err) + return err + } else { + fmt.Println("Check log:", log.Value) + } + return err +} + +func runClient(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory, addr string, secure bool) error { + var transport thrift.TTransport + var err error + if secure { + cfg := new(tls.Config) + cfg.InsecureSkipVerify = true + transport, err = thrift.NewTSSLSocket(addr, cfg) + } else { + transport, err = thrift.NewTSocket(addr) + } + if err != nil { + fmt.Println("Error opening socket:", err) + return err + } + transport, err = transportFactory.GetTransport(transport) + if err != nil { + return err + } + defer transport.Close() + if err := transport.Open(); err != nil { + return err + } + iprot := protocolFactory.GetProtocol(transport) + oprot := protocolFactory.GetProtocol(transport) + return handleClient(tutorial.NewCalculatorClient(thrift.NewTStandardClient(iprot, oprot))) +} diff --git a/src/jaegertracing/thrift/tutorial/go/src/handler.go b/src/jaegertracing/thrift/tutorial/go/src/handler.go new file mode 100644 index 000000000..5c0eed006 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/go/src/handler.go @@ -0,0 +1,102 @@ +package main + +/* + * 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. + */ + +import ( + "context" + "fmt" + "shared" + "strconv" + "tutorial" +) + +type CalculatorHandler struct { + log map[int]*shared.SharedStruct +} + +func NewCalculatorHandler() *CalculatorHandler { + return &CalculatorHandler{log: make(map[int]*shared.SharedStruct)} +} + +func (p *CalculatorHandler) Ping(ctx context.Context) (err error) { + fmt.Print("ping()\n") + return nil +} + +func (p *CalculatorHandler) Add(ctx context.Context, num1 int32, num2 int32) (retval17 int32, err error) { + fmt.Print("add(", num1, ",", num2, ")\n") + return num1 + num2, nil +} + +func (p *CalculatorHandler) Calculate(ctx context.Context, logid int32, w *tutorial.Work) (val int32, err error) { + fmt.Print("calculate(", logid, ", {", w.Op, ",", w.Num1, ",", w.Num2, "})\n") + switch w.Op { + case tutorial.Operation_ADD: + val = w.Num1 + w.Num2 + break + case tutorial.Operation_SUBTRACT: + val = w.Num1 - w.Num2 + break + case tutorial.Operation_MULTIPLY: + val = w.Num1 * w.Num2 + break + case tutorial.Operation_DIVIDE: + if w.Num2 == 0 { + ouch := tutorial.NewInvalidOperation() + ouch.WhatOp = int32(w.Op) + ouch.Why = "Cannot divide by 0" + err = ouch + return + } + val = w.Num1 / w.Num2 + break + default: + ouch := tutorial.NewInvalidOperation() + ouch.WhatOp = int32(w.Op) + ouch.Why = "Unknown operation" + err = ouch + return + } + entry := shared.NewSharedStruct() + entry.Key = logid + entry.Value = strconv.Itoa(int(val)) + k := int(logid) + /* + oldvalue, exists := p.log[k] + if exists { + fmt.Print("Replacing ", oldvalue, " with ", entry, " for key ", k, "\n") + } else { + fmt.Print("Adding ", entry, " for key ", k, "\n") + } + */ + p.log[k] = entry + return val, err +} + +func (p *CalculatorHandler) GetStruct(ctx context.Context, key int32) (*shared.SharedStruct, error) { + fmt.Print("getStruct(", key, ")\n") + v, _ := p.log[int(key)] + return v, nil +} + +func (p *CalculatorHandler) Zip(ctx context.Context) (err error) { + fmt.Print("zip()\n") + return nil +} diff --git a/src/jaegertracing/thrift/tutorial/go/src/main.go b/src/jaegertracing/thrift/tutorial/go/src/main.go new file mode 100644 index 000000000..7730d7b32 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/go/src/main.go @@ -0,0 +1,82 @@ +package main + +/* + * 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. + */ + +import ( + "flag" + "fmt" + "github.com/apache/thrift/lib/go/thrift" + "os" +) + +func Usage() { + fmt.Fprint(os.Stderr, "Usage of ", os.Args[0], ":\n") + flag.PrintDefaults() + fmt.Fprint(os.Stderr, "\n") +} + +func main() { + flag.Usage = Usage + server := flag.Bool("server", false, "Run server") + protocol := flag.String("P", "binary", "Specify the protocol (binary, compact, json, simplejson)") + framed := flag.Bool("framed", false, "Use framed transport") + buffered := flag.Bool("buffered", false, "Use buffered transport") + addr := flag.String("addr", "localhost:9090", "Address to listen to") + secure := flag.Bool("secure", false, "Use tls secure transport") + + flag.Parse() + + var protocolFactory thrift.TProtocolFactory + switch *protocol { + case "compact": + protocolFactory = thrift.NewTCompactProtocolFactory() + case "simplejson": + protocolFactory = thrift.NewTSimpleJSONProtocolFactory() + case "json": + protocolFactory = thrift.NewTJSONProtocolFactory() + case "binary", "": + protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() + default: + fmt.Fprint(os.Stderr, "Invalid protocol specified", protocol, "\n") + Usage() + os.Exit(1) + } + + var transportFactory thrift.TTransportFactory + if *buffered { + transportFactory = thrift.NewTBufferedTransportFactory(8192) + } else { + transportFactory = thrift.NewTTransportFactory() + } + + if *framed { + transportFactory = thrift.NewTFramedTransportFactory(transportFactory) + } + + if *server { + if err := runServer(transportFactory, protocolFactory, *addr, *secure); err != nil { + fmt.Println("error running server:", err) + } + } else { + if err := runClient(transportFactory, protocolFactory, *addr, *secure); err != nil { + fmt.Println("error running client:", err) + } + } +} diff --git a/src/jaegertracing/thrift/tutorial/go/src/server.go b/src/jaegertracing/thrift/tutorial/go/src/server.go new file mode 100644 index 000000000..95708eb87 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/go/src/server.go @@ -0,0 +1,54 @@ +package main + +/* + * 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. + */ + +import ( + "crypto/tls" + "fmt" + "github.com/apache/thrift/lib/go/thrift" + "tutorial" +) + +func runServer(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory, addr string, secure bool) error { + var transport thrift.TServerTransport + var err error + if secure { + cfg := new(tls.Config) + if cert, err := tls.LoadX509KeyPair("server.crt", "server.key"); err == nil { + cfg.Certificates = append(cfg.Certificates, cert) + } else { + return err + } + transport, err = thrift.NewTSSLServerSocket(addr, cfg) + } else { + transport, err = thrift.NewTServerSocket(addr) + } + + if err != nil { + return err + } + fmt.Printf("%T\n", transport) + handler := NewCalculatorHandler() + processor := tutorial.NewCalculatorProcessor(handler) + server := thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory) + + fmt.Println("Starting the simple server... on ", addr) + return server.Serve() +} diff --git a/src/jaegertracing/thrift/tutorial/haxe/Makefile.am b/src/jaegertracing/thrift/tutorial/haxe/Makefile.am new file mode 100644 index 000000000..e6f271346 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/Makefile.am @@ -0,0 +1,97 @@ +# +# 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. +# + +BIN_CPP = bin/Main-debug +BIN_PHP = bin/php/Main-debug.php +BIN_PHP_WEB = bin/php-web-server/Main-debug.php + +gen-haxe/tutorial/calculator.hx gen-haxe/shared/shared_service.hx: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen haxe -r $< + +all-local: $(BIN_CPP) $(BIN_PHP) $(BIN_PHP_WEB) + +check: gen-haxe/tutorial/calculator.hx + +$(BIN_CPP): \ + src/*.hx \ + ../../lib/haxe/src/org/apache/thrift/**/*.hx \ + gen-haxe/tutorial/calculator.hx + $(HAXE) --cwd . cpp.hxml + +$(BIN_PHP): \ + src/*.hx \ + ../../lib/haxe/src/org/apache/thrift/**/*.hx \ + gen-haxe/tutorial/calculator.hx + $(HAXE) --cwd . php.hxml + +$(BIN_PHP_WEB): \ + src/*.hx \ + ../../lib/haxe/src/org/apache/thrift/**/*.hx \ + gen-haxe/tutorial/calculator.hx + $(HAXE) --cwd . php-web-server.hxml + +tutorialserver: all + $(BIN_CPP) server + +tutorialserver_php: all + php -f $(BIN_PHP) server + +tutorialclient: all + $(BIN_CPP) + +tutorialclient_php: all + php -f $(BIN_PHP) + +tutorialsecureserver: all + $(BIN_CPP) server secure + +tutorialsecureserver_php: all + php -f $(BIN_PHP) server secure + +tutorialsecureclient: all + $(BIN_CPP) secure + +tutorialsecureclient_php: all + php -f $(BIN_PHP) secure + +tutorialserver_php_http: all + php -S 127.0.0.1:9090 router.php + +tutorialclient_http: all + $(BIN_CPP) client http + +clean-local: + $(RM) -r gen-haxe bin + +EXTRA_DIST = \ + src \ + cpp.hxml \ + csharp.hxml \ + flash.hxml \ + java.hxml \ + javascript.hxml \ + php-web-server.hxml \ + neko.hxml \ + php.hxml \ + python.hxml \ + router.php \ + project.hide \ + Tutorial.hxproj \ + make_all.bat \ + make_all.sh diff --git a/src/jaegertracing/thrift/tutorial/haxe/Tutorial.hxproj b/src/jaegertracing/thrift/tutorial/haxe/Tutorial.hxproj new file mode 100644 index 000000000..796f648a5 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/Tutorial.hxproj @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="utf-8"?> +<project version="2"> + <!-- Output SWF options --> + <output> + <movie outputType="Application" /> + <movie input="" /> + <movie path="bin/HaxeTutorial" /> + <movie fps="30" /> + <movie width="800" /> + <movie height="600" /> + <movie version="1" /> + <movie minorVersion="0" /> + <movie platform="C++" /> + <movie background="#FFFFFF" /> + </output> + <!-- Other classes to be compiled into your SWF --> + <classpaths> + <class path="src" /> + <class path="gen-haxe" /> + <class path="../../lib/haxe/src" /> + </classpaths> + <!-- Build options --> + <build> + <option directives="" /> + <option flashStrict="False" /> + <option noInlineOnDebug="False" /> + <option mainClass="Main" /> + <option enabledebug="False" /> + <option additional="" /> + </build> + <!-- haxelib libraries --> + <haxelib> + <!-- example: <library name="..." /> --> + </haxelib> + <!-- Class files to compile (other referenced classes will automatically be included) --> + <compileTargets> + <!-- example: <compile path="..." /> --> + </compileTargets> + <!-- Paths to exclude from the Project Explorer tree --> + <hiddenPaths> + <hidden path="obj" /> + <hidden path="cpp.hxml" /> + <hidden path="csharp.hxml" /> + <hidden path="flash.hxml" /> + <hidden path="java.hxml" /> + <hidden path="javascript.hxml" /> + <hidden path="make_all.bat" /> + <hidden path="make_all.sh" /> + <hidden path="Makefile.am" /> + <hidden path="neko.hxml" /> + <hidden path="php.hxml" /> + <hidden path="project.hide" /> + <hidden path="python.hxml" /> + </hiddenPaths> + <!-- Executed before build --> + <preBuildCommand>thrift -r -gen haxe ../tutorial.thrift</preBuildCommand> + <!-- Executed after build --> + <postBuildCommand alwaysRun="False" /> + <!-- Other project options --> + <options> + <option showHiddenPaths="False" /> + <option testMovie="Unknown" /> + <option testMovieCommand="" /> + </options> + <!-- Plugin storage --> + <storage /> +</project>
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/haxe/cpp.hxml b/src/jaegertracing/thrift/tutorial/haxe/cpp.hxml new file mode 100644 index 000000000..6adb52d7e --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/cpp.hxml @@ -0,0 +1,41 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#CPP target +-cpp bin + +#To produce 64 bit binaries the file should define the HXCPP_M64 compile variable: +#-D HXCPP_M64 + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/haxe/csharp.hxml b/src/jaegertracing/thrift/tutorial/haxe/csharp.hxml new file mode 100644 index 000000000..295c017e7 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/csharp.hxml @@ -0,0 +1,38 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#CSHARP target +-cs bin/Tutorial.exe + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/haxe/flash.hxml b/src/jaegertracing/thrift/tutorial/haxe/flash.hxml new file mode 100644 index 000000000..a1f0568ad --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/flash.hxml @@ -0,0 +1,41 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#Flash target +-swf bin/Tutorial.swf + +#Add debug information +-debug + +# we need some goodies from sys.net +# --macro allowPackage("sys") + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/haxe/java.hxml b/src/jaegertracing/thrift/tutorial/haxe/java.hxml new file mode 100644 index 000000000..c615565a9 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/java.hxml @@ -0,0 +1,38 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#Java target +-java bin/Tutorial.jar + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/haxe/javascript.hxml b/src/jaegertracing/thrift/tutorial/haxe/javascript.hxml new file mode 100644 index 000000000..b2b3876cf --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/javascript.hxml @@ -0,0 +1,44 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#JavaScript target +-js bin/Tutorial.js + +#You can use -D source-map-content (requires Haxe 3.1+) to have the .hx +#files directly embedded into the map file, this way you only have to +#upload it, and it will be always in sync with the compiled .js even if +#you modify your .hx files. +-D source-map-content + +#Generate source map and add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/haxe/make_all.bat b/src/jaegertracing/thrift/tutorial/haxe/make_all.bat new file mode 100644 index 000000000..656dd1530 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/make_all.bat @@ -0,0 +1,68 @@ +@echo off +rem /* +rem * Licensed to the Apache Software Foundation (ASF) under one +rem * or more contributor license agreements. See the NOTICE file +rem * distributed with this work for additional information +rem * regarding copyright ownership. The ASF licenses this file +rem * to you under the Apache License, Version 2.0 (the +rem * "License"); you may not use this file except in compliance +rem * with the License. You may obtain a copy of the License at +rem * +rem * http://www.apache.org/licenses/LICENSE-2.0 +rem * +rem * Unless required by applicable law or agreed to in writing, +rem * software distributed under the License is distributed on an +rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem * KIND, either express or implied. See the License for the +rem * specific language governing permissions and limitations +rem * under the License. +rem */ + +setlocal +if "%HOMEDRIVE%"=="" goto MISSINGVARS +if "%HOMEPATH%"=="" goto MISSINGVARS +if "%HAXEPATH%"=="" goto NOTINSTALLED + +set path=%HAXEPATH%;%HAXEPATH%\..\neko;%path% + +rem # invoke Thrift comnpiler +thrift -r -gen haxe ..\tutorial.thrift +if errorlevel 1 goto STOP + +rem # invoke Haxe compiler for all targets +for %%a in (*.hxml) do ( + rem * filter Python, as it is not supported by Haxe 3.1.3 (but will be in 3.1.4) + if not "%%a"=="python.hxml" ( + echo -------------------------- + echo Building %%a ... + echo -------------------------- + haxe --cwd . %%a + ) +) + + +echo. +echo done. +pause +goto eof + +:NOTINSTALLED +echo FATAL: Either Haxe is not installed, or the HAXEPATH variable is not set. +pause +goto eof + +:MISSINGVARS +echo FATAL: Unable to locate home folder. +echo. +echo Both HOMEDRIVE and HOMEPATH need to be set to point to your Home folder. +echo The current values are: +echo HOMEDRIVE=%HOMEDRIVE% +echo HOMEPATH=%HOMEPATH% +pause +goto eof + +:STOP +pause +goto eof + +:eof diff --git a/src/jaegertracing/thrift/tutorial/haxe/make_all.sh b/src/jaegertracing/thrift/tutorial/haxe/make_all.sh new file mode 100644 index 000000000..2ee650dce --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/make_all.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# +# 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. +# + +# invoke Thrift comnpiler +thrift -r -gen haxe ../tutorial.thrift + +# output folder +if [ ! -d bin ]; then + mkdir bin +fi + +# invoke Haxe compoiler +for target in *.hxml; do + echo -------------------------- + echo Building ${target} ... + echo -------------------------- + if [ ! -d bin/${target} ]; then + mkdir bin/${target} + fi + haxe --cwd . ${target} +done + + +#eof diff --git a/src/jaegertracing/thrift/tutorial/haxe/neko.hxml b/src/jaegertracing/thrift/tutorial/haxe/neko.hxml new file mode 100644 index 000000000..6161f6977 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/neko.hxml @@ -0,0 +1,38 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#neko target +-neko bin/Tutorial.n + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/haxe/php-web-server.hxml b/src/jaegertracing/thrift/tutorial/haxe/php-web-server.hxml new file mode 100644 index 000000000..395a8521e --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/php-web-server.hxml @@ -0,0 +1,43 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#PHP target +-php bin/php-web-server/ +--php-front Main-debug.php + +#defines +-D phpwebserver + + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full diff --git a/src/jaegertracing/thrift/tutorial/haxe/php.hxml b/src/jaegertracing/thrift/tutorial/haxe/php.hxml new file mode 100644 index 000000000..c2f68878e --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/php.hxml @@ -0,0 +1,39 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#PHP target +-php bin/php/ +--php-front Main-debug.php + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full diff --git a/src/jaegertracing/thrift/tutorial/haxe/project.hide b/src/jaegertracing/thrift/tutorial/haxe/project.hide new file mode 100644 index 000000000..8d5d4ec56 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/project.hide @@ -0,0 +1,105 @@ +{ + "type" : 0 + ,"target" : 4 + ,"name" : "Apache Thrift Tutorial" + ,"main" : null + ,"projectPackage" : "" + ,"company" : "Apache Software Foundation (ASF)" + ,"license" : "Apache License, Version 2.0" + ,"url" : "http://www.apache.org/licenses/LICENSE-2.0" + ,"targetData" : [ + { + "pathToHxml" : "flash.hxml" + ,"runActionType" : 1 + ,"runActionText" : "bin/Tutorial.swf" + } + ,{ + "pathToHxml" : "javascript.hxml" + ,"runActionType" : 1 + ,"runActionText" : "bin\\index.html" + } + ,{ + "pathToHxml" : "neko.hxml" + ,"runActionType" : 2 + ,"runActionText" : "neko bin/Tutorial.n" + } + ,{ + "pathToHxml" : "php.hxml" + } + ,{ + "pathToHxml" : "cpp.hxml" + ,"runActionType" : 2 + ,"runActionText" : "bin/Main-debug.exe" + } + ,{ + "pathToHxml" : "java.hxml" + } + ,{ + "pathToHxml" : "csharp.hxml" + ,"runActionType" : 2 + ,"runActionText" : "bin\\Tutorial.exe\\bin\\Main-Debug.exe" + } + ,{ + "pathToHxml" : "python.hxml" + ,"runActionType" : 2 + ,"runActionText" : "python bin/Tutorial.py" + } + ] + ,"files" : [ + { + "path" : "src\\org\\apache\\thrift\\server\\TServer.hx" + ,"useTabs" : true + ,"indentSize" : 4 + ,"foldedRegions" : [ + + ] + ,"activeLine" : 76 + } + ,{ + "path" : "src\\org\\apache\\thrift\\server\\TSimpleServer.hx" + ,"useTabs" : true + ,"indentSize" : 4 + ,"foldedRegions" : [ + + ] + ,"activeLine" : 100 + } + ,{ + "path" : "src\\shared\\SharedServiceProcessor.hx" + ,"useTabs" : true + ,"indentSize" : 4 + ,"foldedRegions" : [ + + ] + ,"activeLine" : 20 + } + ,{ + "path" : "src\\tutorial\\CalculatorProcessor.hx" + ,"useTabs" : true + ,"indentSize" : 4 + ,"foldedRegions" : [ + + ] + ,"activeLine" : 79 + } + ,{ + "path" : "src\\Main.hx" + ,"useTabs" : true + ,"indentSize" : 4 + ,"foldedRegions" : [ + + ] + ,"activeLine" : 0 + } + ] + ,"activeFile" : "src\\Main.hx" + ,"openFLTarget" : null + ,"openFLBuildMode" : "Debug" + ,"runActionType" : null + ,"runActionText" : null + ,"buildActionCommand" : null + ,"hiddenItems" : [ + + ] + ,"showHiddenItems" : false +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/haxe/python.hxml b/src/jaegertracing/thrift/tutorial/haxe/python.hxml new file mode 100644 index 000000000..f2c19fa93 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/python.hxml @@ -0,0 +1,38 @@ +# +# 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. +# + +#integrate files to classpath +-cp src +-cp gen-haxe +-cp ../../lib/haxe/src + +#this class wil be used as entry point for your app. +-main Main + +#Python target +-python bin/Tutorial.py + +#Add debug information +-debug + +#dead code elimination : remove unused code +#"-dce no" : do not remove unused code +#"-dce std" : remove unused code in the std lib (default) +#"-dce full" : remove all unused code +-dce full
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/haxe/router.php b/src/jaegertracing/thrift/tutorial/haxe/router.php new file mode 100644 index 000000000..e34135cc9 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/router.php @@ -0,0 +1,31 @@ +<?php +/* + * 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. + * + * @package thrift + */ + + + +//router file to run testing web server + +//set_time_limit(1); + +require_once dirname(__FILE__) . '/bin/php-web-server/Main-debug.php'; + + diff --git a/src/jaegertracing/thrift/tutorial/haxe/src/CalculatorHandler.hx b/src/jaegertracing/thrift/tutorial/haxe/src/CalculatorHandler.hx new file mode 100644 index 000000000..e9752db9f --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/src/CalculatorHandler.hx @@ -0,0 +1,101 @@ +/* + * 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. + */ + +package; + +import haxe.ds.IntMap; + +import org.apache.thrift.*; +import org.apache.thrift.protocol.*; +import org.apache.thrift.transport.*; +import org.apache.thrift.server.*; +import org.apache.thrift.meta_data.*; + +import tutorial.*; +import shared.*; + + +class CalculatorHandler implements Calculator { + + private var log = new IntMap<SharedStruct>(); + + public function new() { + } + + public function ping() : Void { + trace("ping()"); + } + + + public function add( num1 : haxe.Int32, num2 : haxe.Int32) : haxe.Int32 { + trace('add( $num1, $num2)'); + return num1 + num2; + } + + public function calculate( logid : haxe.Int32, work : Work) : haxe.Int32 { + trace('calculate( $logid, '+work.op+","+work.num1+","+work.num2+")"); + + var val : haxe.Int32 = 0; + switch (work.op) + { + case Operation.ADD: + val = work.num1 + work.num2; + + case Operation.SUBTRACT: + val = work.num1 - work.num2; + + case Operation.MULTIPLY: + val = work.num1 * work.num2; + + case Operation.DIVIDE: + if (work.num2 == 0) + { + var io = new InvalidOperation(); + io.whatOp = work.op; + io.why = "Cannot divide by 0"; + throw io; + } + val = Std.int( work.num1 / work.num2); + + default: + var io = new InvalidOperation(); + io.whatOp = work.op; + io.why = "Unknown operation"; + throw io; + } + + var entry = new SharedStruct(); + entry.key = logid; + entry.value = '$val'; + log.set(logid, entry); + + return val; + } + + public function getStruct( key : haxe.Int32) : SharedStruct { + trace('getStruct($key)'); + return log.get(key); + } + + // oneway method, no args + public function zip() : Void { + trace("zip()"); + } + +} diff --git a/src/jaegertracing/thrift/tutorial/haxe/src/Main.hx b/src/jaegertracing/thrift/tutorial/haxe/src/Main.hx new file mode 100644 index 000000000..6bebe7164 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/haxe/src/Main.hx @@ -0,0 +1,375 @@ +/* + * 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. + */ + +package; + +import org.apache.thrift.*; +import org.apache.thrift.protocol.*; +import org.apache.thrift.transport.*; +import org.apache.thrift.server.*; +import org.apache.thrift.meta_data.*; + +import tutorial.*; +import shared.*; + + +enum Prot { + binary; + json; +} + +enum Trns { + socket; + http; +} + +class Main { + + private static var server : Bool = false; + private static var framed : Bool = false; + private static var buffered : Bool = false; + private static var prot : Prot = binary; + private static var trns : Trns = socket; + + private static var targetHost : String = "localhost"; + private static var targetPort : Int = 9090; + + static function main() { + + #if ! (flash || js || phpwebserver) + try { + ParseArgs(); + } catch (e : String) { + trace(e); + trace(GetHelp()); + return; + } + + #elseif phpwebserver + //forcing server + server = true; + trns = http; + initPhpWebServer(); + //check method + if(php.Web.getMethod() != 'POST') { + Sys.println('http endpoint for thrift test server'); + return; + } + #end + + try { + if (server) + RunServer(); + else + RunClient(); + } catch (e : String) { + trace(e); + } + + trace("Completed."); + } + + #if phpwebserver + private static function initPhpWebServer() + { + //remap trace to error log + haxe.Log.trace = function(v:Dynamic, ?infos:haxe.PosInfos) + { + // handle trace + var newValue : Dynamic; + if (infos != null && infos.customParams!=null) { + var extra:String = ""; + for( v in infos.customParams ) + extra += "," + v; + newValue = v + extra; + } + else { + newValue = v; + } + var msg = infos != null ? infos.fileName + ':' + infos.lineNumber + ': ' : ''; + Sys.stderr().writeString('${msg}${newValue}\n'); + } + } + #end + + + #if ! (flash || js) + + private static function GetHelp() : String { + return Sys.executablePath()+" modus trnsOption transport protocol\n" + +"Options:\n" + +" modus: client, server (default: client)\n" + +" trnsOption: framed, buffered (default: none)\n" + +" transport: socket, http (default: socket)\n" + +" protocol: binary, json (default: binary)\n" + +"\n" + +"All arguments are optional.\n"; + } + + + private static function ParseArgs() : Void { + var step = 0; + for (arg in Sys.args()) { + + // server|client + switch(step) { + case 0: + ++step; + if ( arg == "client") + server = false; + else if ( arg == "server") + server = true; + else + throw "First argument must be 'server' or 'client'"; + + case 1: + if ( arg == "framed") { + framed = true; + } else if ( arg == "buffered") { + buffered = true; + } else if ( arg == "socket") { + trns = socket; + ++step; + } else if ( arg == "http") { + trns = http; + ++step; + } else { + throw "Unknown transport "+arg; + } + + case 2: + if ( arg == "binary") { + prot = binary; + ++step; + } else if ( arg == "json") { + prot = json; + ++step; + } else { + throw "Unknown protocol "+arg; + } + + default: + throw "Unexpected argument "+arg; + } + + if ( framed && buffered) + { + trace("WN: framed supersedes buffered"); + } + + } + } + + #end + + private static function ClientSetup() : Calculator { + trace("Client configuration:"); + + // endpoint transport + var transport : TTransport; + switch(trns) + { + case socket: + trace('- socket transport $targetHost:$targetPort'); + transport = new TSocket( targetHost, targetPort); + case http: + var uri = 'http://${targetHost}:${targetPort}'; + trace('- HTTP transport $uri'); + transport = new THttpClient(uri); + default: + throw "Unhandled transport"; + } + + + // optinal layered transport + if ( framed) { + trace("- framed transport"); + transport = new TFramedTransport(transport); + } else if ( buffered) { + trace("- buffered transport"); + transport = new TBufferedTransport(transport); + } + + + // protocol + var protocol : TProtocol; + switch(prot) + { + case binary: + trace("- binary protocol"); + protocol = new TBinaryProtocol( transport); + case json: + trace("- JSON protocol"); + protocol = new TJSONProtocol( transport); + default: + throw "Unhandled protocol"; + } + + + // put everything together + transport.open(); + return new CalculatorImpl(protocol,protocol); + } + + + private static function RunClient() : Void { + var client = ClientSetup(); + + try { + client.ping(); + trace("ping() successful"); + } catch(error : TException) { + trace('ping() failed: $error'); + } catch(error : Dynamic) { + trace('ping() failed: $error'); + } + + try { + var sum = client.add( 1, 1); + trace('1+1=$sum'); + } catch(error : TException) { + trace('add() failed: $error'); + } catch(error : Dynamic) { + trace('add() failed: $error'); + } + + + var work = new tutorial.Work(); + work.op = tutorial.Operation.DIVIDE; + work.num1 = 1; + work.num2 = 0; + try { + var quotient = client.calculate( 1, work); + trace('Whoa we can divide by 0! Result = $quotient'); + } catch(error : TException) { + trace('calculate() failed: $error'); + } catch(error : Dynamic) { + trace('calculate() failed: $error'); + } + + work.op = tutorial.Operation.SUBTRACT; + work.num1 = 15; + work.num2 = 10; + try { + var diff = client.calculate( 1, work); + trace('15-10=$diff'); + } catch(error : TException) { + trace('calculate() failed: $error'); + } catch(error : Dynamic) { + trace('calculate() failed: $error'); + } + + + try { + var log : SharedStruct = client.getStruct( 1); + var logval = log.value; + trace('Check log: $logval'); + } catch(error : TException) { + trace('getStruct() failed: $error'); + } catch(error : Dynamic) { + trace('getStruct() failed: $error'); + } + } + + + private static function ServerSetup() : TServer { + trace("Server configuration:"); + + // endpoint transport + var transport : TServerTransport = null; + switch(trns) + { + case socket: + #if (flash || js) + throw 'current platform does not support socket servers'; + #else + trace('- socket transport port $targetPort'); + transport = new TServerSocket( targetPort); + #end + case http: + #if !phpwebserver + throw "HTTP server not implemented yet"; + //trace("- http transport"); + //transport = new THttpClient( targetHost); + #else + trace("- http transport"); + transport = new TWrappingServerTransport( + new TStreamTransport( + new TFileStream("php://input", Read), + new TFileStream("php://output", Append) + ) + ); + + #end + default: + throw "Unhandled transport"; + } + + // optional: layered transport + var transfactory : TTransportFactory = null; + if ( framed) { + trace("- framed transport"); + transfactory = new TFramedTransportFactory(); + } else if ( buffered) { + trace("- buffered transport"); + transfactory = new TBufferedTransportFactory(); + } + + // protocol + var protfactory : TProtocolFactory = null; + switch(prot) + { + case binary: + trace("- binary protocol"); + protfactory = new TBinaryProtocolFactory(); + case json: + trace("- JSON protocol"); + protfactory = new TJSONProtocolFactory(); + default: + throw "Unhandled protocol"; + } + + var handler = new CalculatorHandler(); + var processor = new CalculatorProcessor(handler); + var server = new TSimpleServer( processor, transport, transfactory, protfactory); + #if phpwebserver + server.runOnce = true; + #end + + return server; + } + + + private static function RunServer() : Void { + try + { + var server = ServerSetup(); + + trace("\nStarting the server..."); + server.Serve(); + } + catch( e : Dynamic) + { + trace('RunServer() failed: $e'); + } + trace("done."); + } + +} + diff --git a/src/jaegertracing/thrift/tutorial/hs/HaskellClient.hs b/src/jaegertracing/thrift/tutorial/hs/HaskellClient.hs new file mode 100644 index 000000000..bd29df06d --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/hs/HaskellClient.hs @@ -0,0 +1,76 @@ +-- +-- 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. +-- + +import qualified Calculator +import qualified Calculator_Client as Client +import qualified SharedService_Client as SClient +import Tutorial_Types +import SharedService_Iface +import Shared_Types + +import Thrift +import Thrift.Protocol.Binary +import Thrift.Transport +import Thrift.Transport.Handle +import Thrift.Server + +import Control.Exception +import Data.Maybe +import Data.Text.Lazy +import Text.Printf +import Network + +main = do + transport <- hOpen ("localhost", PortNumber 9090) + let binProto = BinaryProtocol transport + let client = (binProto, binProto) + + Client.ping client + print "ping()" + + sum <- Client.add client 1 1 + printf "1+1=%d\n" sum + + + let work = Work { work_op = DIVIDE, + work_num1 = 1, + work_num2 = 0, + work_comment = Nothing + } + + Control.Exception.catch (printf "1/0=%d\n" =<< Client.calculate client 1 work) + (\e -> printf "InvalidOperation %s\n" (show (e :: InvalidOperation))) + + + let work = Work { work_op = SUBTRACT, + work_num1 = 15, + work_num2 = 10, + work_comment = Nothing + } + + diff <- Client.calculate client 1 work + printf "15-10=%d\n" diff + + log <- SClient.getStruct client 1 + printf "Check log: %s\n" $ unpack $ sharedStruct_value log + + -- Close! + tClose transport + + diff --git a/src/jaegertracing/thrift/tutorial/hs/HaskellServer.hs b/src/jaegertracing/thrift/tutorial/hs/HaskellServer.hs new file mode 100644 index 000000000..cfe13441d --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/hs/HaskellServer.hs @@ -0,0 +1,103 @@ +-- +-- 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. +-- + +{-# LANGUAGE OverloadedStrings #-} + +import qualified Calculator +import Calculator_Iface +import Tutorial_Types +import SharedService_Iface +import Shared_Types + +import Thrift +import Thrift.Protocol.Binary +import Thrift.Transport +import Thrift.Server + +import Data.Int +import Data.String +import Data.Maybe +import Text.Printf +import Control.Exception (throw) +import Control.Concurrent.MVar +import qualified Data.Map as M +import Data.Map ((!)) +import Data.Monoid + +data CalculatorHandler = CalculatorHandler {mathLog :: MVar (M.Map Int32 SharedStruct)} + +newCalculatorHandler = do + log <- newMVar mempty + return $ CalculatorHandler log + +instance SharedService_Iface CalculatorHandler where + getStruct self k = do + myLog <- readMVar (mathLog self) + return $ (myLog ! k) + + +instance Calculator_Iface CalculatorHandler where + ping _ = + print "ping()" + + add _ n1 n2 = do + printf "add(%d,%d)\n" n1 n2 + return (n1 + n2) + + calculate self mlogid mwork = do + printf "calculate(%d, %s)\n" logid (show work) + + let val = case op work of + ADD -> + num1 work + num2 work + SUBTRACT -> + num1 work - num2 work + MULTIPLY -> + num1 work * num2 work + DIVIDE -> + if num2 work == 0 then + throw $ + InvalidOperation { + invalidOperation_whatOp = fromIntegral $ fromEnum $ op work, + invalidOperation_why = "Cannot divide by 0" + } + else + num1 work `div` num2 work + + let logEntry = SharedStruct logid (fromString $ show $ val) + modifyMVar_ (mathLog self) $ return .(M.insert logid logEntry) + + return $! val + + where + -- stupid dynamic languages f'ing it up + num1 = work_num1 + num2 = work_num2 + op = work_op + logid = mlogid + work = mwork + + zip _ = + print "zip()" + +main = do + handler <- newCalculatorHandler + print "Starting the server..." + runBasicServer handler Calculator.process 9090 + print "done." diff --git a/src/jaegertracing/thrift/tutorial/hs/LICENSE b/src/jaegertracing/thrift/tutorial/hs/LICENSE new file mode 100644 index 000000000..3b6d7d74c --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/hs/LICENSE @@ -0,0 +1,239 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + +-------------------------------------------------- +SOFTWARE DISTRIBUTED WITH THRIFT: + +The Apache Thrift software includes a number of subcomponents with +separate copyright notices and license terms. Your use of the source +code for the these subcomponents is subject to the terms and +conditions of the following licenses. + +-------------------------------------------------- +Portions of the following files are licensed under the MIT License: + + lib/erl/src/Makefile.am + +Please see doc/otp-base-license.txt for the full terms of this license. + +-------------------------------------------------- +For the aclocal/ax_boost_base.m4 and contrib/fb303/aclocal/ax_boost_base.m4 components: + +# Copyright (c) 2007 Thomas Porschberg <thomas@randspringer.de> +# +# Copying and distribution of this file, with or without +# modification, are permitted in any medium without royalty provided +# the copyright notice and this notice are preserved. + +-------------------------------------------------- +For the lib/nodejs/lib/thrift/json_parse.js: + +/* + json_parse.js + 2015-05-02 + Public Domain. + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + +*/ +(By Douglas Crockford <douglas@crockford.com>) +-------------------------------------------------- diff --git a/src/jaegertracing/thrift/tutorial/hs/Makefile.am b/src/jaegertracing/thrift/tutorial/hs/Makefile.am new file mode 100755 index 000000000..9c6fd8308 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/hs/Makefile.am @@ -0,0 +1,47 @@ +# +# 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. +# + +all-local: + $(top_builddir)/compiler/cpp/thrift --gen hs -r $(top_srcdir)/tutorial/tutorial.thrift + $(CABAL) install + +install-exec-hook: + $(CABAL) install + +# Make sure this doesn't fail if Haskell is not configured. +clean-local: + $(CABAL) clean + $(RM) -r dist/ + $(RM) -r gen-*/ + +dist-hook: + $(RM) -r $(distdir)/dist/ + $(RM) -r $(distdir)/gen-*/ + +check-local: + $(CABAL) check + +tutorialserver: all + dist/build/HaskellServer/HaskellServer + +tutorialclient: all + dist/build/HaskellClient/HaskellClient + +EXTRA_DIST = \ + LICENSE diff --git a/src/jaegertracing/thrift/tutorial/hs/Setup.lhs b/src/jaegertracing/thrift/tutorial/hs/Setup.lhs new file mode 100644 index 000000000..c7df182d3 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/hs/Setup.lhs @@ -0,0 +1,21 @@ +#!/usr/bin/env runhaskell + +> -- 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. + +> import Distribution.Simple +> main = defaultMain diff --git a/src/jaegertracing/thrift/tutorial/hs/ThriftTutorial.cabal b/src/jaegertracing/thrift/tutorial/hs/ThriftTutorial.cabal new file mode 100755 index 000000000..b6a612216 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/hs/ThriftTutorial.cabal @@ -0,0 +1,73 @@ +-- +-- 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. +-- + +Name: ThriftTutorial +Version: 0.13.0 +Cabal-Version: >= 1.4 +License: OtherLicense +Category: Foreign +Build-Type: Simple +Synopsis: Thrift Tutorial library package +Homepage: http://thrift.apache.org +Bug-Reports: https://issues.apache.org/jira/browse/THRIFT +Maintainer: dev@thrift.apache.org +License-File: LICENSE + +Description: + Haskell tutorial for the Apache Thrift RPC system. Requires the use of the thrift code generator. + +flag network-uri + description: Get Network.URI from the network-uri package + default: True + +Executable HaskellServer + Main-is: HaskellServer.hs + Hs-Source-Dirs: + ., gen-hs/ + Build-Depends: + base >= 4, base < 5, ghc-prim, containers, thrift, vector, unordered-containers, text, hashable, bytestring, QuickCheck + Extensions: + DeriveDataTypeable, + ExistentialQuantification, + FlexibleInstances, + KindSignatures, + MagicHash, + RankNTypes, + ScopedTypeVariables, + TypeSynonymInstances + +Executable HaskellClient + Main-is: HaskellClient.hs + Hs-Source-Dirs: + ., gen-hs/ + Build-Depends: + base >= 4, base < 5, ghc-prim, containers, thrift, vector, QuickCheck + if flag(network-uri) + build-depends: network-uri >= 2.6, network >= 2.6 + else + build-depends: network < 2.6 + Extensions: + DeriveDataTypeable, + ExistentialQuantification, + FlexibleInstances, + KindSignatures, + MagicHash, + RankNTypes, + ScopedTypeVariables, + TypeSynonymInstances diff --git a/src/jaegertracing/thrift/tutorial/java/Makefile.am b/src/jaegertracing/thrift/tutorial/java/Makefile.am new file mode 100755 index 000000000..95908b154 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/java/Makefile.am @@ -0,0 +1,45 @@ +# +# 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. +# + +export CLASSPATH + +# Make sure this doesn't fail if ant is not configured. +clean-local: + ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ + $$ANT $(ANT_FLAGS) clean + +all-local: + $(ANT) $(ANT_FLAGS) compile + +check-local: all + $(ANT) $(ANT_FLAGS) test + +tutorial: all + $(ANT) $(ANT_FLAGS) tutorial + +tutorialserver: all + $(ANT) $(ANT_FLAGS) tutorialserver + +tutorialclient: all + $(ANT) $(ANT_FLAGS) tutorialclient + +EXTRA_DIST = \ + build.xml \ + src \ + README.md diff --git a/src/jaegertracing/thrift/tutorial/java/README.md b/src/jaegertracing/thrift/tutorial/java/README.md new file mode 100644 index 000000000..f109fea4a --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/java/README.md @@ -0,0 +1,24 @@ +Thrift Java Tutorial +================================================== +1) Compile the Java library + + thrift/lib/java$ make +or: + + thrift/lib/java$ ant + +4) Run the tutorial: + +start server and client with one step: + + thrift/tutorial/java$ make tutorial + +or: + + thrift/tutorial/java$ make tutorialserver + thrift/tutorial/java$ make tutorialclient + +or: + + thrift/tutorial/java$ ant tutorialserver + thrift/tutorial/java$ ant tutorialclient diff --git a/src/jaegertracing/thrift/tutorial/java/build.xml b/src/jaegertracing/thrift/tutorial/java/build.xml new file mode 100644 index 000000000..55cdb8fab --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/java/build.xml @@ -0,0 +1,115 @@ +<!-- + 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. +--> +<project name="tutorial" default="tutorial" basedir="."> + + <description>Thrift Java Tutorial</description> + + <property name="src" location="src" /> + <property name="gen" location="gen-java" /> + <property name="build" location="build" /> + + <path id="libs.classpath"> + <fileset dir="../../lib/java/build/libs"> + <include name="libthrift*.jar" /> + <exclude name="libthrift*test.jar" /> + <exclude name="libthrift*javadoc.jar" /> + <exclude name="libthrift*sources.jar" /> + </fileset> + <fileset dir="../../lib/java/build/deps"> + <include name="*.jar" /> + </fileset> + </path> + <path id="build.classpath"> + <path refid="libs.classpath" /> + <pathelement path="${gen}" /> + </path> + <path id="tutorial.classpath"> + <path refid="build.classpath" /> + <pathelement path="${build}" /> + <pathelement path="tutorial.jar" /> + </path> + + <target name="init"> + <tstamp /> + <mkdir dir="${build}"/> + <mkdir dir="${build}/log"/> + </target> + + <target name="compile" depends="init, generate"> + <javac compiler="modern" includeantruntime="false" srcdir="${gen}" destdir="${build}" classpathref="libs.classpath" /> + <javac compiler="modern" includeantruntime="false" srcdir="${src}" destdir="${build}" classpathref="build.classpath" /> + </target> + + <target name="test" depends="tutorial" /> + + <target name="tutorial" description="Run the tutorial" depends="compile"> + <jar jarfile="tutorial.jar" basedir="${build}"/> + <parallel> + <java classname="JavaServer" fork="true" timeout="10000" + classpathref="tutorial.classpath" failonerror="false" output="${build}/log/tutorial.log"> + </java> + <sequential> + <sleep seconds="2"/> + <echo>tutorial client simple:</echo> + <java classname="JavaClient" + classpathref="tutorial.classpath" failonerror="true"> + <arg line="simple"/> + </java> + <echo>tutorial client secure:</echo> + <java classname="JavaClient" + classpathref="tutorial.classpath" failonerror="true"> + <arg line="secure"/> + </java> + </sequential> + </parallel> + </target> + + <target name="generate"> + <!-- Generate the thrift gen-java source --> + <exec executable="../../compiler/cpp/thrift" failonerror="true"> + <arg line="--gen java -r ../tutorial.thrift"/> + </exec> + </target> + + <target name="tutorialclient" description="Run a tutorial client" depends="compile"> + <echo>tutorial client simple:</echo> + <java classname="JavaClient" + classpathref="tutorial.classpath" failonerror="true"> + <arg line="simple"/> + </java> + <echo>tutorial client secure:</echo> + <java classname="JavaClient" + classpathref="tutorial.classpath" failonerror="true"> + <arg line="secure"/> + </java> + </target> + + <target name="tutorialserver" description="Run a tutorial server" depends="compile"> + <java classname="JavaServer" fork="true" + classpathref="tutorial.classpath" failonerror="false" output="${build}/log/tutorial.log"> + </java> + </target> + + <target name="clean"> + <delete dir="${build}" /> + <delete dir="${gen}"/> + <delete file="tutorial.jar" /> + </target> + +</project> diff --git a/src/jaegertracing/thrift/tutorial/java/src/CalculatorHandler.java b/src/jaegertracing/thrift/tutorial/java/src/CalculatorHandler.java new file mode 100644 index 000000000..92944b07f --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/java/src/CalculatorHandler.java @@ -0,0 +1,92 @@ +/* + * 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. + */ + +import org.apache.thrift.TException; + +// Generated code +import tutorial.*; +import shared.*; + +import java.util.HashMap; + +public class CalculatorHandler implements Calculator.Iface { + + private HashMap<Integer,SharedStruct> log; + + public CalculatorHandler() { + log = new HashMap<Integer, SharedStruct>(); + } + + public void ping() { + System.out.println("ping()"); + } + + public int add(int n1, int n2) { + System.out.println("add(" + n1 + "," + n2 + ")"); + return n1 + n2; + } + + public int calculate(int logid, Work work) throws InvalidOperation { + System.out.println("calculate(" + logid + ", {" + work.op + "," + work.num1 + "," + work.num2 + "})"); + int val = 0; + switch (work.op) { + case ADD: + val = work.num1 + work.num2; + break; + case SUBTRACT: + val = work.num1 - work.num2; + break; + case MULTIPLY: + val = work.num1 * work.num2; + break; + case DIVIDE: + if (work.num2 == 0) { + InvalidOperation io = new InvalidOperation(); + io.whatOp = work.op.getValue(); + io.why = "Cannot divide by 0"; + throw io; + } + val = work.num1 / work.num2; + break; + default: + InvalidOperation io = new InvalidOperation(); + io.whatOp = work.op.getValue(); + io.why = "Unknown operation"; + throw io; + } + + SharedStruct entry = new SharedStruct(); + entry.key = logid; + entry.value = Integer.toString(val); + log.put(logid, entry); + + return val; + } + + public SharedStruct getStruct(int key) { + System.out.println("getStruct(" + key + ")"); + return log.get(key); + } + + public void zip() { + System.out.println("zip()"); + } + +} + diff --git a/src/jaegertracing/thrift/tutorial/java/src/JavaClient.java b/src/jaegertracing/thrift/tutorial/java/src/JavaClient.java new file mode 100644 index 000000000..2e35d412a --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/java/src/JavaClient.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +// Generated code +import tutorial.*; +import shared.*; + +import org.apache.thrift.TException; +import org.apache.thrift.transport.TSSLTransportFactory; +import org.apache.thrift.transport.TTransport; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TProtocol; + +public class JavaClient { + public static void main(String [] args) { + + if (args.length != 1) { + System.out.println("Please enter 'simple' or 'secure'"); + System.exit(0); + } + + try { + TTransport transport; + if (args[0].contains("simple")) { + transport = new TSocket("localhost", 9090); + transport.open(); + } + else { + /* + * Similar to the server, you can use the parameters to setup client parameters or + * use the default settings. On the client side, you will need a TrustStore which + * contains the trusted certificate along with the public key. + * For this example it's a self-signed cert. + */ + TSSLTransportParameters params = new TSSLTransportParameters(); + params.setTrustStore("../../lib/java/test/.truststore", "thrift", "SunX509", "JKS"); + /* + * Get a client transport instead of a server transport. The connection is opened on + * invocation of the factory method, no need to specifically call open() + */ + transport = TSSLTransportFactory.getClientSocket("localhost", 9091, 0, params); + } + + TProtocol protocol = new TBinaryProtocol(transport); + Calculator.Client client = new Calculator.Client(protocol); + + perform(client); + + transport.close(); + } catch (TException x) { + x.printStackTrace(); + } + } + + private static void perform(Calculator.Client client) throws TException + { + client.ping(); + System.out.println("ping()"); + + int sum = client.add(1,1); + System.out.println("1+1=" + sum); + + Work work = new Work(); + + work.op = Operation.DIVIDE; + work.num1 = 1; + work.num2 = 0; + try { + int quotient = client.calculate(1, work); + System.out.println("Whoa we can divide by 0"); + } catch (InvalidOperation io) { + System.out.println("Invalid operation: " + io.why); + } + + work.op = Operation.SUBTRACT; + work.num1 = 15; + work.num2 = 10; + try { + int diff = client.calculate(1, work); + System.out.println("15-10=" + diff); + } catch (InvalidOperation io) { + System.out.println("Invalid operation: " + io.why); + } + + SharedStruct log = client.getStruct(1); + System.out.println("Check log: " + log.value); + } +} diff --git a/src/jaegertracing/thrift/tutorial/java/src/JavaServer.java b/src/jaegertracing/thrift/tutorial/java/src/JavaServer.java new file mode 100644 index 000000000..788473a8d --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/java/src/JavaServer.java @@ -0,0 +1,110 @@ +/* + * 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. + */ + +import org.apache.thrift.server.TServer; +import org.apache.thrift.server.TServer.Args; +import org.apache.thrift.server.TSimpleServer; +import org.apache.thrift.server.TThreadPoolServer; +import org.apache.thrift.transport.TSSLTransportFactory; +import org.apache.thrift.transport.TServerSocket; +import org.apache.thrift.transport.TServerTransport; +import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters; + +// Generated code +import tutorial.*; +import shared.*; + +import java.util.HashMap; + +public class JavaServer { + + public static CalculatorHandler handler; + + public static Calculator.Processor processor; + + public static void main(String [] args) { + try { + handler = new CalculatorHandler(); + processor = new Calculator.Processor(handler); + + Runnable simple = new Runnable() { + public void run() { + simple(processor); + } + }; + Runnable secure = new Runnable() { + public void run() { + secure(processor); + } + }; + + new Thread(simple).start(); + new Thread(secure).start(); + } catch (Exception x) { + x.printStackTrace(); + } + } + + public static void simple(Calculator.Processor processor) { + try { + TServerTransport serverTransport = new TServerSocket(9090); + TServer server = new TSimpleServer(new Args(serverTransport).processor(processor)); + + // Use this for a multithreaded server + // TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor)); + + System.out.println("Starting the simple server..."); + server.serve(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void secure(Calculator.Processor processor) { + try { + /* + * Use TSSLTransportParameters to setup the required SSL parameters. In this example + * we are setting the keystore and the keystore password. Other things like algorithms, + * cipher suites, client auth etc can be set. + */ + TSSLTransportParameters params = new TSSLTransportParameters(); + // The Keystore contains the private key + params.setKeyStore("../../lib/java/test/.keystore", "thrift", null, null); + + /* + * Use any of the TSSLTransportFactory to get a server transport with the appropriate + * SSL configuration. You can use the default settings if properties are set in the command line. + * Ex: -Djavax.net.ssl.keyStore=.keystore and -Djavax.net.ssl.keyStorePassword=thrift + * + * Note: You need not explicitly call open(). The underlying server socket is bound on return + * from the factory class. + */ + TServerTransport serverTransport = TSSLTransportFactory.getServerSocket(9091, 0, null, params); + TServer server = new TSimpleServer(new Args(serverTransport).processor(processor)); + + // Use this for a multi threaded server + // TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor)); + + System.out.println("Starting the secure server..."); + server.serve(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/jaegertracing/thrift/tutorial/js/Makefile.am b/src/jaegertracing/thrift/tutorial/js/Makefile.am new file mode 100755 index 000000000..3fe088842 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/js/Makefile.am @@ -0,0 +1,39 @@ +# +# 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. +# + +export CLASSPATH + +# Make sure this doesn't fail if ant is not configured. +clean-local: + ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ + $$ANT $(ANT_FLAGS) clean + +all-local: + $(ANT) $(ANT_FLAGS) compile + +check-local: all + $(ANT) $(ANT_FLAGS) test + +tutorialserver: all + $(ANT) $(ANT_FLAGS) tutorialserver + +EXTRA_DIST = \ + build.xml \ + src \ + tutorial.html diff --git a/src/jaegertracing/thrift/tutorial/js/build.xml b/src/jaegertracing/thrift/tutorial/js/build.xml new file mode 100644 index 000000000..03a6e7c64 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/js/build.xml @@ -0,0 +1,92 @@ +<!-- + 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. +--> +<project name="tutorial" default="test" basedir="."> + + <description>Thrift JavaScript Tutorial</description> + + <property name="src" location="src" /> + <property name="javasrc" location="../java/src" /> + <property name="gen" location="../java/gen-java" /> + <property name="build" location="build" /> + + <!-- the root directory, where you unpack thrift distibution (e.g. thrift-0.x.x.tar.gz) --> + <property name="thrift.dir" location="../../" /> + <!-- JavaScript tutorial depends on the java tutorial thrift handler and server infrastructure --> + <property name="thrift.java.dir" location="${thrift.dir}/lib/java" /> + + <path id="libs.classpath"> + <fileset dir="${thrift.java.dir}/build/libs"> + <include name="libthrift*.jar" /> + <exclude name="libthrift*test.jar" /> + <exclude name="libthrift*javadoc.jar" /> + <exclude name="libthrift*sources.jar" /> + </fileset> + <fileset dir="${thrift.java.dir}/build/deps"> + <include name="*.jar" /> + </fileset> + </path> + <path id="build.classpath"> + <path refid="libs.classpath" /> + <pathelement path="${gen}" /> + <pathelement path="${build}" /> + </path> + + <target name="init"> + <tstamp /> + <mkdir dir="${build}"/> + </target> + + <target name="compile" depends="init"> + <javac compiler="modern" includeantruntime="false" srcdir="${gen}" destdir="${build}" classpathref="libs.classpath" /> + <javac compiler="modern" includeantruntime="false" srcdir="${javasrc}" destdir="${build}" classpathref="build.classpath"> + <exclude name="JavaClient.java"/> + <exclude name="JavaServer.java"/> + <include name="CalculatorHandler.java"/> + </javac> + <javac compiler="modern" includeantruntime="false" srcdir="${src}" destdir="${build}" classpathref="build.classpath"> + <compilerarg value="-Xlint:all"/> + </javac> + </target> + + <target name="test" depends="tutorial" /> + + <target name="tutorial" depends="compile"> + <jar jarfile="tutorial-js.jar" basedir="${build}"/> + </target> + + <target name="tutorialserver" description="run the test server" depends="tutorial, generate"> + <java classname="Httpd" fork="true" + classpathref="build.classpath" failonerror="true"> + <arg value="../../" /> + </java> + </target> + + <target name="generate"> + <exec executable="../../compiler/cpp/thrift" failonerror="true"> + <arg line="--gen js -r ../tutorial.thrift"/> + </exec> + </target> + + <target name="clean"> + <delete dir="${build}" /> + <delete dir="gen-js"/> + <delete file="tutorial-js.jar" /> + </target> + +</project> diff --git a/src/jaegertracing/thrift/tutorial/js/src/Httpd.java b/src/jaegertracing/thrift/tutorial/js/src/Httpd.java new file mode 100644 index 000000000..4985471a7 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/js/src/Httpd.java @@ -0,0 +1,299 @@ +/* + * ==================================================================== + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * <http://www.apache.org/>. + * + */ + +import java.io.File; +import java.io.IOException; +import java.io.InterruptedIOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URLDecoder; +import java.util.Locale; + +import org.apache.http.ConnectionClosedException; +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.HttpServerConnection; +import org.apache.http.HttpStatus; +import org.apache.http.MethodNotSupportedException; +import org.apache.http.entity.ContentProducer; +import org.apache.http.entity.EntityTemplate; +import org.apache.http.entity.FileEntity; +import org.apache.http.impl.DefaultHttpResponseFactory; +import org.apache.http.impl.DefaultHttpServerConnection; +import org.apache.http.impl.NoConnectionReuseStrategy; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.CoreConnectionPNames; +import org.apache.http.params.CoreProtocolPNames; +import org.apache.http.params.HttpParams; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.BasicHttpProcessor; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.HttpProcessor; +import org.apache.http.protocol.HttpRequestHandler; +import org.apache.http.protocol.HttpRequestHandlerRegistry; +import org.apache.http.protocol.HttpService; +import org.apache.http.util.EntityUtils; +import org.apache.thrift.TProcessor; +import org.apache.thrift.protocol.TJSONProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.TMemoryBuffer; + +// Generated code +import tutorial.*; +import shared.*; + +import java.util.HashMap; + +/** + * Basic, yet fully functional and spec compliant, HTTP/1.1 file server. + * <p> + * Please note the purpose of this application is demonstrate the usage of + * HttpCore APIs. It is NOT intended to demonstrate the most efficient way of + * building an HTTP file server. + * + * + */ +public class Httpd { + + public static void main(String[] args) throws Exception { + if (args.length < 1) { + System.err.println("Please specify document root directory"); + System.exit(1); + } + Thread t = new RequestListenerThread(8088, args[0]); + t.setDaemon(false); + t.start(); + } + + static class HttpFileHandler implements HttpRequestHandler { + + private final String docRoot; + + public HttpFileHandler(final String docRoot) { + super(); + this.docRoot = docRoot; + } + + public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) throws HttpException, IOException { + + String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH); + if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) { + throw new MethodNotSupportedException(method + " method not supported"); + } + String target = request.getRequestLine().getUri(); + + if (request instanceof HttpEntityEnclosingRequest && target.equals("/thrift/service/tutorial/")) { + HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity(); + byte[] entityContent = EntityUtils.toByteArray(entity); + System.out.println("Incoming content: " + new String(entityContent)); + + final String output = this.thriftRequest(entityContent); + + System.out.println("Outgoing content: "+output); + + EntityTemplate body = new EntityTemplate(new ContentProducer() { + + public void writeTo(final OutputStream outstream) throws IOException { + OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); + writer.write(output); + writer.flush(); + } + + }); + body.setContentType("text/html; charset=UTF-8"); + response.setEntity(body); + } else { + final File file = new File(this.docRoot, URLDecoder.decode(target, "UTF-8")); + if (!file.exists()) { + + response.setStatusCode(HttpStatus.SC_NOT_FOUND); + EntityTemplate body = new EntityTemplate(new ContentProducer() { + + public void writeTo(final OutputStream outstream) throws IOException { + OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); + writer.write("<html><body><h1>"); + writer.write("File "); + writer.write(file.getPath()); + writer.write(" not found"); + writer.write("</h1></body></html>"); + writer.flush(); + } + + }); + body.setContentType("text/html; charset=UTF-8"); + response.setEntity(body); + System.out.println("File " + file.getPath() + " not found"); + + } else if (!file.canRead() || file.isDirectory()) { + + response.setStatusCode(HttpStatus.SC_FORBIDDEN); + EntityTemplate body = new EntityTemplate(new ContentProducer() { + + public void writeTo(final OutputStream outstream) throws IOException { + OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); + writer.write("<html><body><h1>"); + writer.write("Access denied"); + writer.write("</h1></body></html>"); + writer.flush(); + } + + }); + body.setContentType("text/html; charset=UTF-8"); + response.setEntity(body); + System.out.println("Cannot read file " + file.getPath()); + + } else { + + response.setStatusCode(HttpStatus.SC_OK); + FileEntity body = new FileEntity(file, "text/html"); + response.setEntity(body); + System.out.println("Serving file " + file.getPath()); + + } + } + } + + private String thriftRequest(byte[] input){ + try{ + + //Input + TMemoryBuffer inbuffer = new TMemoryBuffer(input.length); + inbuffer.write(input); + TProtocol inprotocol = new TJSONProtocol(inbuffer); + + //Output + TMemoryBuffer outbuffer = new TMemoryBuffer(100); + TProtocol outprotocol = new TJSONProtocol(outbuffer); + + TProcessor processor = new Calculator.Processor(new CalculatorHandler()); + processor.process(inprotocol, outprotocol); + + byte[] output = new byte[outbuffer.length()]; + outbuffer.readAll(output, 0, output.length); + + return new String(output,"UTF-8"); + }catch(Throwable t){ + return "Error:"+t.getMessage(); + } + + + } + + } + + static class RequestListenerThread extends Thread { + + private final ServerSocket serversocket; + private final HttpParams params; + private final HttpService httpService; + + public RequestListenerThread(int port, final String docroot) throws IOException { + this.serversocket = new ServerSocket(port); + this.params = new BasicHttpParams(); + this.params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 1000).setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024) + .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false).setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true) + .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1"); + + // Set up the HTTP protocol processor + HttpProcessor httpproc = new BasicHttpProcessor(); + + // Set up request handlers + HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry(); + reqistry.register("*", new HttpFileHandler(docroot)); + + // Set up the HTTP service + this.httpService = new HttpService(httpproc, new NoConnectionReuseStrategy(), new DefaultHttpResponseFactory()); + this.httpService.setParams(this.params); + this.httpService.setHandlerResolver(reqistry); + } + + public void run() { + System.out.println("Listening on port " + this.serversocket.getLocalPort()); + System.out.println("Point your browser to http://localhost:8088/tutorial/js/tutorial.html"); + + while (!Thread.interrupted()) { + try { + // Set up HTTP connection + Socket socket = this.serversocket.accept(); + DefaultHttpServerConnection conn = new DefaultHttpServerConnection(); + System.out.println("Incoming connection from " + socket.getInetAddress()); + conn.bind(socket, this.params); + + // Start worker thread + Thread t = new WorkerThread(this.httpService, conn); + t.setDaemon(true); + t.start(); + } catch (InterruptedIOException ex) { + break; + } catch (IOException e) { + System.err.println("I/O error initialising connection thread: " + e.getMessage()); + break; + } + } + } + } + + static class WorkerThread extends Thread { + + private final HttpService httpservice; + private final HttpServerConnection conn; + + public WorkerThread(final HttpService httpservice, final HttpServerConnection conn) { + super(); + this.httpservice = httpservice; + this.conn = conn; + } + + public void run() { + System.out.println("New connection thread"); + HttpContext context = new BasicHttpContext(null); + try { + while (!Thread.interrupted() && this.conn.isOpen()) { + this.httpservice.handleRequest(this.conn, context); + } + } catch (ConnectionClosedException ex) { + System.err.println("Client closed connection"); + } catch (IOException ex) { + System.err.println("I/O error: " + ex.getMessage()); + } catch (HttpException ex) { + System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage()); + } finally { + try { + this.conn.shutdown(); + } catch (IOException ignore) { + } + } + } + + } + +} diff --git a/src/jaegertracing/thrift/tutorial/js/tutorial.html b/src/jaegertracing/thrift/tutorial/js/tutorial.html new file mode 100755 index 000000000..d020bed37 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/js/tutorial.html @@ -0,0 +1,109 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<!-- + 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. +--> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <title>Thrift Javascript Bindings - Tutorial Example</title> + + <script src="../../lib/js/src/thrift.js" type="text/javascript"></script> + <script src="gen-js/tutorial_types.js" type="text/javascript"></script> + <script src="gen-js/shared_types.js" type="text/javascript"></script> + <script src="gen-js/SharedService.js" type="text/javascript"></script> + <script src="gen-js/Calculator.js" type="text/javascript"></script> + + <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> + + + <script type="text/javascript" charset="utf-8"> + //<![CDATA[ + $(document).ready(function(){ + // remove pseudo child required for valid xhtml strict + $("#op").children().remove(); + // add operations to it's dropdown menu + $.each(Operation, function(key, value) { + $('#op').append($("<option></option>").attr("value",value).text(key)); + }); + + $('table.calculator').attr('width', 500); + }); + + function calc() { + var transport = new Thrift.Transport("/thrift/service/tutorial/"); + var protocol = new Thrift.Protocol(transport); + var client = new CalculatorClient(protocol); + + var work = new Work(); + work.num1 = $("#num1").val(); + work.num2 = $("#num2").val(); + work.op = $("#op").val(); + + try { + result = client.calculate(1, work); + $('#result').val(result); + $('#result').css('color', 'black'); + } catch(ouch){ + $('#result').val(ouch.why); + $('#result').css('color', 'red'); + } + } + + function auto_calc() { + if ($('#autoupdate:checked').val() !== undefined) { + calc(); + } + } + //]]> + </script> + +</head> +<body> + <h2>Thrift Javascript Bindings</h2> + <form action=""> + <table class="calculator"> + <tr> + <td>num1</td> + <td><input type="text" id="num1" value="20" onkeyup="javascript:auto_calc();"/></td> + </tr> + <tr> + <td>Operation</td> + <td><select id="op" size="1" onchange="javascript:auto_calc();"><option></option></select></td> + </tr> + <tr> + <td>num2</td> + <td><input type="text" id="num2" value="5" onkeyup="javascript:auto_calc();"/></td></tr> + <tr> + <td>result</td> + <td><input type="text" id="result" value=""/></td></tr> + <tr> + <td><input type="checkbox" id="autoupdate" checked="checked"/>autoupdate</td> + <td><input type="button" id="calculate" value="calculate" onclick="javascript:calc();"/></td> + </tr> + </table> + </form> + + <p>This Java Script example uses <a href="https://github.com/apache/thrift/blob/master/tutorial/tutorial.thrift">tutorial.thrift</a> and a Thrift server using JSON protocol and HTTP transport. + </p> + <p> + <a href="http://validator.w3.org/check/referer"><img + src="http://www.w3.org/Icons/valid-xhtml10" + alt="Valid XHTML 1.0!" height="31" width="88" /></a> + </p> +</body> +</html> diff --git a/src/jaegertracing/thrift/tutorial/netcore/.gitignore b/src/jaegertracing/thrift/tutorial/netcore/.gitignore new file mode 100644 index 000000000..9938bb237 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/.gitignore @@ -0,0 +1 @@ +!**/*.pfx
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netcore/Client/Client.csproj b/src/jaegertracing/thrift/tutorial/netcore/Client/Client.csproj new file mode 100644 index 000000000..911272d3f --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Client/Client.csproj @@ -0,0 +1,19 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netcoreapp2.0</TargetFramework> + <AssemblyName>Client</AssemblyName> + <PackageId>Client</PackageId> + <OutputType>Exe</OutputType> + <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> + <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> + <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> + <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\Interfaces\Interfaces.csproj" /> + <ProjectReference Include="..\..\..\lib\netcore\Thrift\Thrift.csproj" /> + </ItemGroup> + +</Project> diff --git a/src/jaegertracing/thrift/tutorial/netcore/Client/Program.cs b/src/jaegertracing/thrift/tutorial/netcore/Client/Program.cs new file mode 100644 index 000000000..ce5d8c7e4 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Client/Program.cs @@ -0,0 +1,355 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Protocols; +using Thrift.Transports; +using Thrift.Transports.Client; +using tutorial; +using shared; + +namespace Client +{ + public class Program + { + private static readonly ILogger Logger = new LoggerFactory().AddConsole().AddDebug().CreateLogger(nameof(Client)); + + private static void DisplayHelp() + { + Logger.LogInformation(@" +Usage: + Client.exe -help + will diplay help information + + Client.exe -tr:<transport> -pr:<protocol> -mc:<numClients> + will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client + +Options: + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (address - ""http://localhost:9090"") + tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) + framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + multiplexed - multiplexed protocol will be used + + -mc (multiple clients): + <numClients> - number of multiple clients to connect to server (max 100, default 1) + +Sample: + Client.exe -tr:tcp -p:binary +"); + } + + public static void Main(string[] args) + { + args = args ?? new string[0]; + + if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) + { + DisplayHelp(); + return; + } + + Logger.LogInformation("Starting client..."); + + using (var source = new CancellationTokenSource()) + { + RunAsync(args, source.Token).GetAwaiter().GetResult(); + } + } + + private static async Task RunAsync(string[] args, CancellationToken cancellationToken) + { + var numClients = GetNumberOfClients(args); + + Logger.LogInformation($"Selected # of clients: {numClients}"); + + var transports = new TClientTransport[numClients]; + for (int i = 0; i < numClients; i++) + { + var t = GetTransport(args); + transports[i] = t; + } + + Logger.LogInformation($"Selected client transport: {transports[0]}"); + + var protocols = new Tuple<Protocol, TProtocol>[numClients]; + for (int i = 0; i < numClients; i++) + { + var p = GetProtocol(args, transports[i]); + protocols[i] = p; + } + + Logger.LogInformation($"Selected client protocol: {protocols[0].Item1}"); + + var tasks = new Task[numClients]; + for (int i = 0; i < numClients; i++) + { + var task = RunClientAsync(protocols[i], cancellationToken); + tasks[i] = task; + } + + Task.WaitAll(tasks); + + await Task.CompletedTask; + } + + private static TClientTransport GetTransport(string[] args) + { + var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; + + Transport selectedTransport; + if (Enum.TryParse(transport, true, out selectedTransport)) + { + switch (selectedTransport) + { + case Transport.Tcp: + return new TSocketClientTransport(IPAddress.Loopback, 9090); + case Transport.NamedPipe: + return new TNamedPipeClientTransport(".test"); + case Transport.Http: + return new THttpClientTransport(new Uri("http://localhost:9090"), null); + case Transport.TcpBuffered: + return new TBufferedClientTransport(new TSocketClientTransport(IPAddress.Loopback, 9090)); + case Transport.TcpTls: + return new TTlsSocketClientTransport(IPAddress.Loopback, 9090, GetCertificate(), CertValidator, LocalCertificateSelectionCallback); + case Transport.Framed: + return new TFramedClientTransport(new TSocketClientTransport(IPAddress.Loopback, 9090)); + } + } + + return new TSocketClientTransport(IPAddress.Loopback, 9090); + } + + private static int GetNumberOfClients(string[] args) + { + var numClients = args.FirstOrDefault(x => x.StartsWith("-mc"))?.Split(':')?[1]; + + Logger.LogInformation($"Selected # of clients: {numClients}"); + + int c; + if( int.TryParse(numClients, out c) && (0 < c) && (c <= 100)) + return c; + else + return 1; + } + + private static X509Certificate2 GetCertificate() + { + // due to files location in net core better to take certs from top folder + var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory())); + return new X509Certificate2(certFile, "ThriftTest"); + } + + private static string GetCertPath(DirectoryInfo di, int maxCount = 6) + { + var topDir = di; + var certFile = + topDir.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories) + .FirstOrDefault(); + if (certFile == null) + { + if (maxCount == 0) + throw new FileNotFoundException("Cannot find file in directories"); + return GetCertPath(di.Parent, maxCount - 1); + } + + return certFile.FullName; + } + + private static X509Certificate LocalCertificateSelectionCallback(object sender, + string targetHost, X509CertificateCollection localCertificates, + X509Certificate remoteCertificate, string[] acceptableIssuers) + { + return GetCertificate(); + } + + private static bool CertValidator(object sender, X509Certificate certificate, + X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + return true; + } + + private static Tuple<Protocol, TProtocol> GetProtocol(string[] args, TClientTransport transport) + { + var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; + + Protocol selectedProtocol; + if (Enum.TryParse(protocol, true, out selectedProtocol)) + { + switch (selectedProtocol) + { + case Protocol.Binary: + return new Tuple<Protocol, TProtocol>(selectedProtocol, new TBinaryProtocol(transport)); + case Protocol.Compact: + return new Tuple<Protocol, TProtocol>(selectedProtocol, new TCompactProtocol(transport)); + case Protocol.Json: + return new Tuple<Protocol, TProtocol>(selectedProtocol, new TJsonProtocol(transport)); + case Protocol.Multiplexed: + // it returns BinaryProtocol to avoid making wrapped protocol as public in TProtocolDecorator (in RunClientAsync it will be wrapped into Multiplexed protocol) + return new Tuple<Protocol, TProtocol>(selectedProtocol, new TBinaryProtocol(transport)); + } + } + + return new Tuple<Protocol, TProtocol>(selectedProtocol, new TBinaryProtocol(transport)); + } + + private static async Task RunClientAsync(Tuple<Protocol, TProtocol> protocolTuple, CancellationToken cancellationToken) + { + try + { + var protocol = protocolTuple.Item2; + var protocolType = protocolTuple.Item1; + + TBaseClient client = null; + + try + { + if (protocolType != Protocol.Multiplexed) + { + + client = new Calculator.Client(protocol); + await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client); + } + else + { + // it uses binary protocol there to create Multiplexed protocols + var multiplex = new TMultiplexedProtocol(protocol, nameof(Calculator)); + client = new Calculator.Client(multiplex); + await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client); + + multiplex = new TMultiplexedProtocol(protocol, nameof(SharedService)); + client = new SharedService.Client(multiplex); + await ExecuteSharedServiceClientOperations(cancellationToken, (SharedService.Client)client); + } + } + catch (Exception ex) + { + Logger.LogError($"{client?.ClientId} " + ex); + } + finally + { + protocol.Transport.Close(); + } + } + catch (TApplicationException x) + { + Logger.LogError(x.ToString()); + } + } + + private static async Task ExecuteCalculatorClientOperations(CancellationToken cancellationToken, Calculator.Client client) + { + await client.OpenTransportAsync(cancellationToken); + + // Async version + + Logger.LogInformation($"{client.ClientId} PingAsync()"); + await client.pingAsync(cancellationToken); + + Logger.LogInformation($"{client.ClientId} AddAsync(1,1)"); + var sum = await client.addAsync(1, 1, cancellationToken); + Logger.LogInformation($"{client.ClientId} AddAsync(1,1)={sum}"); + + var work = new Work + { + Op = Operation.DIVIDE, + Num1 = 1, + Num2 = 0 + }; + + try + { + Logger.LogInformation($"{client.ClientId} CalculateAsync(1)"); + await client.calculateAsync(1, work, cancellationToken); + Logger.LogInformation($"{client.ClientId} Whoa we can divide by 0"); + } + catch (InvalidOperation io) + { + Logger.LogInformation($"{client.ClientId} Invalid operation: " + io); + } + + work.Op = Operation.SUBTRACT; + work.Num1 = 15; + work.Num2 = 10; + + try + { + Logger.LogInformation($"{client.ClientId} CalculateAsync(1)"); + var diff = await client.calculateAsync(1, work, cancellationToken); + Logger.LogInformation($"{client.ClientId} 15-10={diff}"); + } + catch (InvalidOperation io) + { + Logger.LogInformation($"{client.ClientId} Invalid operation: " + io); + } + + Logger.LogInformation($"{client.ClientId} GetStructAsync(1)"); + var log = await client.getStructAsync(1, cancellationToken); + Logger.LogInformation($"{client.ClientId} Check log: {log.Value}"); + + Logger.LogInformation($"{client.ClientId} ZipAsync() with delay 100mc on server side"); + await client.zipAsync(cancellationToken); + } + private static async Task ExecuteSharedServiceClientOperations(CancellationToken cancellationToken, SharedService.Client client) + { + await client.OpenTransportAsync(cancellationToken); + + // Async version + + Logger.LogInformation($"{client.ClientId} SharedService GetStructAsync(1)"); + var log = await client.getStructAsync(1, cancellationToken); + Logger.LogInformation($"{client.ClientId} SharedService Value: {log.Value}"); + } + + + private enum Transport + { + Tcp, + NamedPipe, + Http, + TcpBuffered, + Framed, + TcpTls + } + + private enum Protocol + { + Binary, + Compact, + Json, + Multiplexed + } + } +} diff --git a/src/jaegertracing/thrift/tutorial/netcore/Client/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/tutorial/netcore/Client/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..568382e66 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Client/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// 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. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("de78a01b-f7c6-49d1-97da-669d2ed37641")]
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netcore/Client/Properties/launchSettings.json b/src/jaegertracing/thrift/tutorial/netcore/Client/Properties/launchSettings.json new file mode 100644 index 000000000..6b7b60d78 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Client/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Client": { + "commandName": "Project", + "commandLineArgs": "-p:multiplexed" + } + } +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netcore/Client/ThriftTest.pfx b/src/jaegertracing/thrift/tutorial/netcore/Client/ThriftTest.pfx Binary files differnew file mode 100644 index 000000000..f0ded2817 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Client/ThriftTest.pfx diff --git a/src/jaegertracing/thrift/tutorial/netcore/Interfaces/.gitignore b/src/jaegertracing/thrift/tutorial/netcore/Interfaces/.gitignore new file mode 100644 index 000000000..2e7446e33 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Interfaces/.gitignore @@ -0,0 +1,3 @@ +# ignore for autogenerated files +/shared +/tutorial diff --git a/src/jaegertracing/thrift/tutorial/netcore/Interfaces/Interfaces.csproj b/src/jaegertracing/thrift/tutorial/netcore/Interfaces/Interfaces.csproj new file mode 100644 index 000000000..4297a0654 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Interfaces/Interfaces.csproj @@ -0,0 +1,30 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + <AssemblyName>Interfaces</AssemblyName> + <PackageId>Interfaces</PackageId> + <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> + <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> + <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> + <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="../../../lib/netcore/Thrift/Thrift.csproj" /> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="System.ServiceModel.Primitives" Version="[4.4,)" /> + </ItemGroup> + + <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile"> + <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true"> + <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" /> + </Exec> + <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../tutorial.thrift" /> + <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../tutorial.thrift" /> + <Exec Condition="Exists('./../../../compiler/cpp/thrift')" Command="./../../../compiler/cpp/thrift -out $(ProjectDir) -gen netcore:wcf,union,serial,hashcode -r ./../../tutorial.thrift" /> + </Target> + +</Project> diff --git a/src/jaegertracing/thrift/tutorial/netcore/Interfaces/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/tutorial/netcore/Interfaces/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..9126b173e --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Interfaces/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// 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. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("4d13163d-9067-4c9c-8af0-64e08451397d")]
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netcore/Makefile.am b/src/jaegertracing/thrift/tutorial/netcore/Makefile.am new file mode 100644 index 000000000..bd19dfe6a --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Makefile.am @@ -0,0 +1,51 @@ +# +# 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. +# + +SUBDIRS = . + +all-local: + $(DOTNETCORE) build + +clean-local: + $(RM) Interfaces.dll + $(RM) -r Client/bin + $(RM) -r Client/obj + $(RM) -r Server/bin + $(RM) -r Server/obj + $(RM) -r Interfaces/bin + $(RM) -r Interfaces/obj + +dist-hook: + $(RM) $(distdir)/Interfaces.dll + $(RM) -r $(distdir)/Client/bin + $(RM) -r $(distdir)/Client/obj + $(RM) -r $(distdir)/Server/bin + $(RM) -r $(distdir)/Server/obj + $(RM) -r $(distdir)/Interfaces/bin + $(RM) -r $(distdir)/Interfaces/obj + +EXTRA_DIST = \ + Client \ + Interfaces \ + README.md \ + Server \ + Tutorial.sln \ + build.cmd \ + build.sh + diff --git a/src/jaegertracing/thrift/tutorial/netcore/README.md b/src/jaegertracing/thrift/tutorial/netcore/README.md new file mode 100644 index 000000000..626ef9212 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/README.md @@ -0,0 +1,278 @@ +# Building of samples for different platforms + +# Reused components +- NET Core Standard 2.0 +- NET Core App 2.0 + +# How to build +- Download and install the latest .NET Core SDK for your platform https://www.microsoft.com/net/core#windowsvs2015 (archive for SDK 1.0.0-preview2-003121 located by: https://github.com/dotnet/core/blob/master/release-notes/download-archive.md) +- Ensure that you have thrift.exe which supports netcore lib and it added to PATH +- Go to current folder +- Run **build.sh** or **build.cmd** from the root of cloned repository +- Check tests in **src/Tests** folder +- Continue with /tutorials/netcore + +# How to run + +Notes: dotnet run supports passing arguments to app after -- symbols (https://docs.microsoft.com/en-us/dotnet/articles/core/tools/dotnet-run) - example: **dotnet run -- -h** will show help for app + +- build +- go to folder (Client/Server) +- run with specifying of correct parameters **dotnet run -tr:tcp -pr:multiplexed**, **dotnet run -help** (later, after migration to csproj and latest SDK will be possibility to use more usable form **dotnet run -- arguments**) + +#Notes +- Possible adding additional platforms after stabilization of .NET Core (runtimes, platforms (Red Hat Linux, OpenSuse, etc.) + +#Known issues +- In trace logging mode you can see some not important internal exceptions + +# Running of samples +Please install Thrift C# .NET Core library or copy sources and build them to correcly build and run samples + +# NetCore Server + +Usage: + + Server.exe -h + will diplay help information + + Server.exe -tr:<transport> -pr:<protocol> + will run server with specified arguments (tcp transport and binary protocol by default) + +Options: + + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (http address - ""localhost:9090"") + tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) + framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + +Sample: + + Server.exe -tr:tcp + +**Remarks**: + + For TcpTls mode certificate's file ThriftTest.pfx should be in directory with binaries in case of command line usage (or at project level in case of debugging from IDE). + Password for certificate - "ThriftTest". + + + +# NetCore Client + +Usage: + + Client.exe -h + will diplay help information + + Client.exe -tr:<transport> -pr:<protocol> -mc:<numClients> + will run client with specified arguments (tcp transport and binary protocol by default) + +Options: + + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (address - ""http://localhost:9090"") + tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) + framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + + -mc (multiple clients): + <numClients> - number of multiple clients to connect to server (max 100, default 1) + +Sample: + + Client.exe -tr:tcp -pr:binary -mc:10 + +Remarks: + + For TcpTls mode certificate's file ThriftTest.pfx should be in directory + with binaries in case of command line usage (or at project level in case of debugging from IDE). + Password for certificate - "ThriftTest". + +# How to test communication between NetCore and Python + +* Generate code with the latest **thrift.exe** util +* Ensure that **thrift.exe** util generated folder **gen-py** with generated code for Python +* Create **client.py** and **server.py** from the code examples below and save them to the folder with previosly generated folder **gen-py** +* Run netcore samples (client and server) and python samples (client and server) + +Remarks: + +Samples of client and server code below use correct methods (operations) +and fields (properties) according to generated contracts from *.thrift files + +At Windows 10 add record **127.0.0.1 testserver** to **C:\Windows\System32\drivers\etc\hosts** file +for correct work of python server + + +**Python Client:** + +```python +import sys +import glob +sys.path.append('gen-py') + +from tutorial import Calculator +from tutorial.ttypes import InvalidOperation, Operation, Work + +from thrift import Thrift +from thrift.transport import TSocket +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol + + +def main(): + # Make socket + transport = TSocket.TSocket('127.0.0.1', 9090) + + # Buffering is critical. Raw sockets are very slow + transport = TTransport.TBufferedTransport(transport) + + # Wrap in a protocol + protocol = TBinaryProtocol.TBinaryProtocol(transport) + + # Create a client to use the protocol encoder + client = Calculator.Client(protocol) + + # Connect! + transport.open() + + client.Ping() + print('ping()') + + sum = client.Add(1, 1) + print(('1+1=%d' % (sum))) + + work = Work() + + work.Op = Operation.Divide + work.Num1 = 1 + work.Num2 = 0 + + try: + quotient = client.Calculate(1, work) + print('Whoa? You know how to divide by zero?') + print('FYI the answer is %d' % quotient) + except InvalidOperation as e: + print(('InvalidOperation: %r' % e)) + + work.Op = Operation.Substract + work.Num1 = 15 + work.Num2 = 10 + + diff = client.Calculate(1, work) + print(('15-10=%d' % (diff))) + + log = client.GetStruct(1) + print(('Check log: %s' % (log.Value))) + + client.Zip() + print('zip()') + + # Close! + transport.close() + +if __name__ == '__main__': + try: + main() + except Thrift.TException as tx: + print('%s' % tx.message) +``` + + +**Python Server:** + + +```python +import glob +import sys +sys.path.append('gen-py') + +from tutorial import Calculator +from tutorial.ttypes import InvalidOperation, Operation + +from shared.ttypes import SharedStruct + +from thrift.transport import TSocket +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol +from thrift.server import TServer + + +class CalculatorHandler: + def __init__(self): + self.log = {} + + def Ping(self): + print('ping()') + + def Add(self, n1, n2): + print('add(%d,%d)' % (n1, n2)) + return n1 + n2 + + def Calculate(self, logid, work): + print('calculate(%d, %r)' % (logid, work)) + + if work.Op == Operation.Add: + val = work.Num1 + work.Num2 + elif work.Op == Operation.Substract: + val = work.Num1 - work.Num2 + elif work.Op == Operation.Multiply: + val = work.Num1 * work.Num2 + elif work.Op == Operation.Divide: + if work.Num2 == 0: + x = InvalidOperation() + x.WhatOp = work.Op + x.Why = 'Cannot divide by 0' + raise x + val = work.Num1 / work.Num2 + else: + x = InvalidOperation() + x.WhatOp = work.Op + x.Why = 'Invalid operation' + raise x + + log = SharedStruct() + log.Key = logid + log.Value = '%d' % (val) + self.log[logid] = log + + return val + + def GetStruct(self, key): + print('getStruct(%d)' % (key)) + return self.log[key] + + def Zip(self): + print('zip()') + +if __name__ == '__main__': + handler = CalculatorHandler() + processor = Calculator.Processor(handler) + transport = TSocket.TServerSocket(host="testserver", port=9090) + tfactory = TTransport.TBufferedTransportFactory() + pfactory = TBinaryProtocol.TBinaryProtocolFactory() + + server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) + print('Starting the server...') + server.serve() + print('done.') + + # You could do one of these for a multithreaded server + # server = TServer.TThreadedServer(processor, transport, tfactory, pfactory) + # server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory) +``` diff --git a/src/jaegertracing/thrift/tutorial/netcore/Server/Program.cs b/src/jaegertracing/thrift/tutorial/netcore/Server/Program.cs new file mode 100644 index 000000000..6a181bab7 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Server/Program.cs @@ -0,0 +1,428 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Protocols; +using Thrift.Server; +using Thrift.Transports; +using Thrift.Transports.Server; +using tutorial; +using shared; + +namespace Server +{ + public class Program + { + private static readonly ILogger Logger = new LoggerFactory().AddConsole(LogLevel.Trace).AddDebug(LogLevel.Trace).CreateLogger(nameof(Server)); + + public static void Main(string[] args) + { + args = args ?? new string[0]; + + if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) + { + DisplayHelp(); + return; + } + + using (var source = new CancellationTokenSource()) + { + RunAsync(args, source.Token).GetAwaiter().GetResult(); + + Logger.LogInformation("Press any key to stop..."); + + Console.ReadLine(); + source.Cancel(); + } + + Logger.LogInformation("Server stopped"); + } + + private static void DisplayHelp() + { + Logger.LogInformation(@" +Usage: + Server.exe -help + will diplay help information + + Server.exe -tr:<transport> -pr:<protocol> + will run server with specified arguments (tcp transport and binary protocol by default) + +Options: + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (http address - ""localhost:9090"") + tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) + framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + multiplexed - multiplexed protocol will be used + +Sample: + Server.exe -tr:tcp +"); + } + + private static async Task RunAsync(string[] args, CancellationToken cancellationToken) + { + var selectedTransport = GetTransport(args); + var selectedProtocol = GetProtocol(args); + + if (selectedTransport == Transport.Http) + { + new HttpServerSample().Run(cancellationToken); + } + else + { + await RunSelectedConfigurationAsync(selectedTransport, selectedProtocol, cancellationToken); + } + } + + private static Protocol GetProtocol(string[] args) + { + var transport = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; + + Enum.TryParse(transport, true, out Protocol selectedProtocol); + + return selectedProtocol; + } + + private static Transport GetTransport(string[] args) + { + var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; + + Enum.TryParse(transport, true, out Transport selectedTransport); + + return selectedTransport; + } + + private static async Task RunSelectedConfigurationAsync(Transport transport, Protocol protocol, CancellationToken cancellationToken) + { + var fabric = new LoggerFactory().AddConsole(LogLevel.Trace).AddDebug(LogLevel.Trace); + var handler = new CalculatorAsyncHandler(); + ITAsyncProcessor processor = null; + + TServerTransport serverTransport = null; + + switch (transport) + { + case Transport.Tcp: + serverTransport = new TServerSocketTransport(9090); + break; + case Transport.TcpBuffered: + serverTransport = new TServerSocketTransport(port: 9090, clientTimeout: 10000, useBufferedSockets: true); + break; + case Transport.NamedPipe: + serverTransport = new TNamedPipeServerTransport(".test"); + break; + case Transport.TcpTls: + serverTransport = new TTlsServerSocketTransport(9090, false, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback); + break; + case Transport.Framed: + serverTransport = new TServerFramedTransport(9090); + break; + } + + ITProtocolFactory inputProtocolFactory; + ITProtocolFactory outputProtocolFactory; + + switch (protocol) + { + case Protocol.Binary: + { + inputProtocolFactory = new TBinaryProtocol.Factory(); + outputProtocolFactory = new TBinaryProtocol.Factory(); + processor = new Calculator.AsyncProcessor(handler); + } + break; + case Protocol.Compact: + { + inputProtocolFactory = new TCompactProtocol.Factory(); + outputProtocolFactory = new TCompactProtocol.Factory(); + processor = new Calculator.AsyncProcessor(handler); + } + break; + case Protocol.Json: + { + inputProtocolFactory = new TJsonProtocol.Factory(); + outputProtocolFactory = new TJsonProtocol.Factory(); + processor = new Calculator.AsyncProcessor(handler); + } + break; + case Protocol.Multiplexed: + { + inputProtocolFactory = new TBinaryProtocol.Factory(); + outputProtocolFactory = new TBinaryProtocol.Factory(); + + var calcHandler = new CalculatorAsyncHandler(); + var calcProcessor = new Calculator.AsyncProcessor(calcHandler); + + var sharedServiceHandler = new SharedServiceAsyncHandler(); + var sharedServiceProcessor = new SharedService.AsyncProcessor(sharedServiceHandler); + + var multiplexedProcessor = new TMultiplexedProcessor(); + multiplexedProcessor.RegisterProcessor(nameof(Calculator), calcProcessor); + multiplexedProcessor.RegisterProcessor(nameof(SharedService), sharedServiceProcessor); + + processor = multiplexedProcessor; + } + break; + default: + throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null); + } + + try + { + Logger.LogInformation( + $"Selected TAsyncServer with {serverTransport} transport, {processor} processor and {inputProtocolFactory} protocol factories"); + + var server = new AsyncBaseServer(processor, serverTransport, inputProtocolFactory, outputProtocolFactory, fabric); + + Logger.LogInformation("Starting the server..."); + await server.ServeAsync(cancellationToken); + } + catch (Exception x) + { + Logger.LogInformation(x.ToString()); + } + } + + private static X509Certificate2 GetCertificate() + { + // due to files location in net core better to take certs from top folder + var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory())); + return new X509Certificate2(certFile, "ThriftTest"); + } + + private static string GetCertPath(DirectoryInfo di, int maxCount = 6) + { + var topDir = di; + var certFile = + topDir.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories) + .FirstOrDefault(); + if (certFile == null) + { + if (maxCount == 0) + throw new FileNotFoundException("Cannot find file in directories"); + return GetCertPath(di.Parent, maxCount - 1); + } + + return certFile.FullName; + } + + private static X509Certificate LocalCertificateSelectionCallback(object sender, + string targetHost, X509CertificateCollection localCertificates, + X509Certificate remoteCertificate, string[] acceptableIssuers) + { + return GetCertificate(); + } + + private static bool ClientCertValidator(object sender, X509Certificate certificate, + X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + return true; + } + + private enum Transport + { + Tcp, + TcpBuffered, + NamedPipe, + Http, + TcpTls, + Framed + } + + private enum Protocol + { + Binary, + Compact, + Json, + Multiplexed + } + + public class HttpServerSample + { + public void Run(CancellationToken cancellationToken) + { + var config = new ConfigurationBuilder() + .AddEnvironmentVariables(prefix: "ASPNETCORE_") + .Build(); + + var host = new WebHostBuilder() + .UseConfiguration(config) + .UseKestrel() + .UseUrls("http://localhost:9090") + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseStartup<Startup>() + .Build(); + + host.RunAsync(cancellationToken).GetAwaiter().GetResult(); + } + + public class Startup + { + public Startup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddEnvironmentVariables(); + + Configuration = builder.Build(); + } + + public IConfigurationRoot Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddTransient<Calculator.IAsync, CalculatorAsyncHandler>(); + services.AddTransient<ITAsyncProcessor, Calculator.AsyncProcessor>(); + services.AddTransient<THttpServerTransport, THttpServerTransport>(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, + ILoggerFactory loggerFactory) + { + app.UseMiddleware<THttpServerTransport>(); + } + } + } + + public class CalculatorAsyncHandler : Calculator.IAsync + { + private readonly Dictionary<int, SharedStruct> _log = new Dictionary<int, SharedStruct>(); + + public CalculatorAsyncHandler() + { + } + + public async Task<SharedStruct> getStructAsync(int key, + CancellationToken cancellationToken) + { + Logger.LogInformation("GetStructAsync({0})", key); + return await Task.FromResult(_log[key]); + } + + public async Task pingAsync(CancellationToken cancellationToken) + { + Logger.LogInformation("PingAsync()"); + await Task.CompletedTask; + } + + public async Task<int> addAsync(int num1, int num2, CancellationToken cancellationToken) + { + Logger.LogInformation($"AddAsync({num1},{num2})"); + return await Task.FromResult(num1 + num2); + } + + public async Task<int> calculateAsync(int logid, Work w, CancellationToken cancellationToken) + { + Logger.LogInformation($"CalculateAsync({logid}, [{w.Op},{w.Num1},{w.Num2}])"); + + var val = 0; + switch (w.Op) + { + case Operation.ADD: + val = w.Num1 + w.Num2; + break; + + case Operation.SUBTRACT: + val = w.Num1 - w.Num2; + break; + + case Operation.MULTIPLY: + val = w.Num1 * w.Num2; + break; + + case Operation.DIVIDE: + if (w.Num2 == 0) + { + var io = new InvalidOperation + { + WhatOp = (int) w.Op, + Why = "Cannot divide by 0" + }; + + throw io; + } + val = w.Num1 / w.Num2; + break; + + default: + { + var io = new InvalidOperation + { + WhatOp = (int) w.Op, + Why = "Unknown operation" + }; + + throw io; + } + } + + var entry = new SharedStruct + { + Key = logid, + Value = val.ToString() + }; + + _log[logid] = entry; + + return await Task.FromResult(val); + } + + public async Task zipAsync(CancellationToken cancellationToken) + { + Logger.LogInformation("ZipAsync() with delay 100mc"); + await Task.Delay(100, CancellationToken.None); + } + } + + public class SharedServiceAsyncHandler : SharedService.IAsync + { + public async Task<SharedStruct> getStructAsync(int key, CancellationToken cancellationToken) + { + Logger.LogInformation("GetStructAsync({0})", key); + return await Task.FromResult(new SharedStruct() + { + Key = key, + Value = "GetStructAsync" + }); + } + } + } +} diff --git a/src/jaegertracing/thrift/tutorial/netcore/Server/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/tutorial/netcore/Server/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..a0442350b --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Server/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// 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. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("e210fc10-5aff-4b04-ac21-58afc7b74b0c")]
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netcore/Server/Properties/launchSettings.json b/src/jaegertracing/thrift/tutorial/netcore/Server/Properties/launchSettings.json new file mode 100644 index 000000000..78076ff7c --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Server/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Server": { + "commandName": "Project", + "commandLineArgs": "-p:multiplexed" + } + } +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netcore/Server/Server.csproj b/src/jaegertracing/thrift/tutorial/netcore/Server/Server.csproj new file mode 100644 index 000000000..0fbd30323 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Server/Server.csproj @@ -0,0 +1,26 @@ +<Project Sdk="Microsoft.NET.Sdk.Web"> + + <PropertyGroup> + <TargetFramework>netcoreapp2.0</TargetFramework> + <AssemblyName>Server</AssemblyName> + <PackageId>Server</PackageId> + <OutputType>Exe</OutputType> + <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> + <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> + <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> + <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="../Interfaces/Interfaces.csproj" /> + <ProjectReference Include="../../../lib/netcore/Thrift/Thrift.csproj" /> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.AspNetCore" Version="[2.0,)" /> + <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="[2.0,)" /> + <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="[2.0,)" /> + <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="[2.0,)" /> + </ItemGroup> + +</Project> diff --git a/src/jaegertracing/thrift/tutorial/netcore/Server/ThriftTest.pfx b/src/jaegertracing/thrift/tutorial/netcore/Server/ThriftTest.pfx Binary files differnew file mode 100644 index 000000000..f0ded2817 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Server/ThriftTest.pfx diff --git a/src/jaegertracing/thrift/tutorial/netcore/Tutorial.sln b/src/jaegertracing/thrift/tutorial/netcore/Tutorial.sln new file mode 100644 index 000000000..2ddcd4617 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/Tutorial.sln @@ -0,0 +1,78 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26114.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netcore\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Interfaces", "Interfaces\Interfaces.csproj", "{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.ActiveCfg = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.Build.0 = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.ActiveCfg = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.Build.0 = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.Build.0 = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.ActiveCfg = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.Build.0 = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.ActiveCfg = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.Build.0 = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.ActiveCfg = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.Build.0 = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.ActiveCfg = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.Build.0 = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.Build.0 = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.ActiveCfg = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.Build.0 = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.ActiveCfg = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.Build.0 = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.ActiveCfg = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.Build.0 = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.ActiveCfg = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.Build.0 = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.Build.0 = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.ActiveCfg = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.Build.0 = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.ActiveCfg = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {070A5D1D-B29D-4603-999D-693DB444AD0D} + EndGlobalSection +EndGlobal diff --git a/src/jaegertracing/thrift/tutorial/netcore/build.cmd b/src/jaegertracing/thrift/tutorial/netcore/build.cmd new file mode 100644 index 000000000..9b84ef276 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/build.cmd @@ -0,0 +1,25 @@ +@echo off +rem /* +rem * Licensed to the Apache Software Foundation (ASF) under one +rem * or more contributor license agreements. See the NOTICE file +rem * distributed with this work for additional information +rem * regarding copyright ownership. The ASF licenses this file +rem * to you under the Apache License, Version 2.0 (the +rem * "License"); you may not use this file except in compliance +rem * with the License. You may obtain a copy of the License at +rem * +rem * http://www.apache.org/licenses/LICENSE-2.0 +rem * +rem * Unless required by applicable law or agreed to in writing, +rem * software distributed under the License is distributed on an +rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem * KIND, either express or implied. See the License for the +rem * specific language governing permissions and limitations +rem * under the License. +rem */ +setlocal + +dotnet --info +dotnet build + +:eof diff --git a/src/jaegertracing/thrift/tutorial/netcore/build.sh b/src/jaegertracing/thrift/tutorial/netcore/build.sh new file mode 100755 index 000000000..c97e310f0 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netcore/build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# +# 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. +# + +#exit if any command fails +set -e + +dotnet --info +dotnet build diff --git a/src/jaegertracing/thrift/tutorial/netstd/.gitignore b/src/jaegertracing/thrift/tutorial/netstd/.gitignore new file mode 100644 index 000000000..9938bb237 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/.gitignore @@ -0,0 +1 @@ +!**/*.pfx
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netstd/Client/Client.csproj b/src/jaegertracing/thrift/tutorial/netstd/Client/Client.csproj new file mode 100644 index 000000000..a1470a9d3 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Client/Client.csproj @@ -0,0 +1,41 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <!-- + 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. + --> + + <PropertyGroup> + <TargetFramework>netcoreapp2.0</TargetFramework> + <AssemblyName>Client</AssemblyName> + <PackageId>Client</PackageId> + <OutputType>Exe</OutputType> + <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> + <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> + <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> + <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> + </PropertyGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\Interfaces\Interfaces.csproj" /> + <ProjectReference Include="..\..\..\lib\netstd\Thrift\Thrift.csproj" /> + </ItemGroup> + +</Project> diff --git a/src/jaegertracing/thrift/tutorial/netstd/Client/Program.cs b/src/jaegertracing/thrift/tutorial/netstd/Client/Program.cs new file mode 100644 index 000000000..f9509fa2d --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Client/Program.cs @@ -0,0 +1,409 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Protocol; +using Thrift.Transport; +using Thrift.Transport.Client; +using tutorial; +using shared; +using Microsoft.Extensions.DependencyInjection; +using System.Diagnostics; + +namespace Client +{ + public class Program + { + private static ServiceCollection ServiceCollection = new ServiceCollection(); + private static ILogger Logger; + + private static void DisplayHelp() + { + Logger.LogInformation(@" +Usage: + Client.exe -help + will diplay help information + + Client.exe -tr:<transport> -bf:<buffering> -pr:<protocol> -mc:<numClients> + will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client + +Options: + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (address - ""http://localhost:9090"") + tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) + + -bf (buffering): + none - (default) no buffering will be used + buffered - buffered transport will be used + framed - framed transport will be used + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + multiplexed - multiplexed protocol will be used + + -mc (multiple clients): + <numClients> - number of multiple clients to connect to server (max 100, default 1) + +Sample: + Client.exe -tr:tcp -p:binary +"); + } + + public static void Main(string[] args) + { + args = args ?? new string[0]; + + ServiceCollection.AddLogging(logging => ConfigureLogging(logging)); + Logger = ServiceCollection.BuildServiceProvider().GetService<ILoggerFactory>().CreateLogger(nameof(Client)); + + if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) + { + DisplayHelp(); + return; + } + + Logger.LogInformation("Starting client..."); + + using (var source = new CancellationTokenSource()) + { + RunAsync(args, source.Token).GetAwaiter().GetResult(); + } + } + + private static void ConfigureLogging(ILoggingBuilder logging) + { + logging.SetMinimumLevel(LogLevel.Trace); + logging.AddConsole(); + logging.AddDebug(); + } + + private static async Task RunAsync(string[] args, CancellationToken cancellationToken) + { + var numClients = GetNumberOfClients(args); + + Logger.LogInformation($"Selected # of clients: {numClients}"); + + var transports = new TTransport[numClients]; + for (int i = 0; i < numClients; i++) + { + var t = GetTransport(args); + transports[i] = t; + } + + Logger.LogInformation($"Selected client transport: {transports[0]}"); + + var protocols = new Tuple<Protocol, TProtocol>[numClients]; + for (int i = 0; i < numClients; i++) + { + var p = GetProtocol(args, transports[i]); + protocols[i] = p; + } + + Logger.LogInformation($"Selected client protocol: {protocols[0].Item1}"); + + var tasks = new Task[numClients]; + for (int i = 0; i < numClients; i++) + { + var task = RunClientAsync(protocols[i], cancellationToken); + tasks[i] = task; + } + + Task.WaitAll(tasks); + + await Task.CompletedTask; + } + + private static TTransport GetTransport(string[] args) + { + TTransport transport = new TSocketTransport(IPAddress.Loopback, 9090); + + // construct endpoint transport + var transportArg = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; + if (Enum.TryParse(transportArg, true, out Transport selectedTransport)) + { + switch (selectedTransport) + { + case Transport.Tcp: + transport = new TSocketTransport(IPAddress.Loopback, 9090); + break; + + case Transport.NamedPipe: + transport = new TNamedPipeTransport(".test"); + break; + + case Transport.Http: + transport = new THttpTransport(new Uri("http://localhost:9090"), null); + break; + + case Transport.TcpTls: + transport = new TTlsSocketTransport(IPAddress.Loopback, 9090, GetCertificate(), CertValidator, LocalCertificateSelectionCallback); + break; + + default: + Debug.Assert(false, "unhandled case"); + break; + } + } + + // optionally add layered transport(s) + var bufferingArg = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(':')?[1]; + if (Enum.TryParse<Buffering>(bufferingArg, out var selectedBuffering)) + { + switch (selectedBuffering) + { + case Buffering.Buffered: + transport = new TBufferedTransport(transport); + break; + + case Buffering.Framed: + transport = new TFramedTransport(transport); + break; + + default: // layered transport(s) are optional + Debug.Assert(selectedBuffering == Buffering.None, "unhandled case"); + break; + } + } + + return transport; + } + + private static int GetNumberOfClients(string[] args) + { + var numClients = args.FirstOrDefault(x => x.StartsWith("-mc"))?.Split(':')?[1]; + + Logger.LogInformation($"Selected # of clients: {numClients}"); + + int c; + if( int.TryParse(numClients, out c) && (0 < c) && (c <= 100)) + return c; + else + return 1; + } + + private static X509Certificate2 GetCertificate() + { + // due to files location in net core better to take certs from top folder + var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory())); + return new X509Certificate2(certFile, "ThriftTest"); + } + + private static string GetCertPath(DirectoryInfo di, int maxCount = 6) + { + var topDir = di; + var certFile = + topDir.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories) + .FirstOrDefault(); + if (certFile == null) + { + if (maxCount == 0) + throw new FileNotFoundException("Cannot find file in directories"); + return GetCertPath(di.Parent, maxCount - 1); + } + + return certFile.FullName; + } + + private static X509Certificate LocalCertificateSelectionCallback(object sender, + string targetHost, X509CertificateCollection localCertificates, + X509Certificate remoteCertificate, string[] acceptableIssuers) + { + return GetCertificate(); + } + + private static bool CertValidator(object sender, X509Certificate certificate, + X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + return true; + } + + private static Tuple<Protocol, TProtocol> GetProtocol(string[] args, TTransport transport) + { + var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; + + Protocol selectedProtocol; + if (Enum.TryParse(protocol, true, out selectedProtocol)) + { + switch (selectedProtocol) + { + case Protocol.Binary: + return new Tuple<Protocol, TProtocol>(selectedProtocol, new TBinaryProtocol(transport)); + case Protocol.Compact: + return new Tuple<Protocol, TProtocol>(selectedProtocol, new TCompactProtocol(transport)); + case Protocol.Json: + return new Tuple<Protocol, TProtocol>(selectedProtocol, new TJsonProtocol(transport)); + case Protocol.Multiplexed: + // it returns BinaryProtocol to avoid making wrapped protocol as public in TProtocolDecorator (in RunClientAsync it will be wrapped into Multiplexed protocol) + return new Tuple<Protocol, TProtocol>(selectedProtocol, new TBinaryProtocol(transport)); + default: + Debug.Assert(false, "unhandled case"); + break; + } + } + + return new Tuple<Protocol, TProtocol>(selectedProtocol, new TBinaryProtocol(transport)); + } + + private static async Task RunClientAsync(Tuple<Protocol, TProtocol> protocolTuple, CancellationToken cancellationToken) + { + try + { + var protocol = protocolTuple.Item2; + var protocolType = protocolTuple.Item1; + + TBaseClient client = null; + + try + { + if (protocolType != Protocol.Multiplexed) + { + + client = new Calculator.Client(protocol); + await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client); + } + else + { + // it uses binary protocol there to create Multiplexed protocols + var multiplex = new TMultiplexedProtocol(protocol, nameof(Calculator)); + client = new Calculator.Client(multiplex); + await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client); + + multiplex = new TMultiplexedProtocol(protocol, nameof(SharedService)); + client = new SharedService.Client(multiplex); + await ExecuteSharedServiceClientOperations(cancellationToken, (SharedService.Client)client); + } + } + catch (Exception ex) + { + Logger.LogError($"{client?.ClientId} " + ex); + } + finally + { + protocol.Transport.Close(); + } + } + catch (TApplicationException x) + { + Logger.LogError(x.ToString()); + } + } + + private static async Task ExecuteCalculatorClientOperations(CancellationToken cancellationToken, Calculator.Client client) + { + await client.OpenTransportAsync(cancellationToken); + + // Async version + + Logger.LogInformation($"{client.ClientId} PingAsync()"); + await client.pingAsync(cancellationToken); + + Logger.LogInformation($"{client.ClientId} AddAsync(1,1)"); + var sum = await client.addAsync(1, 1, cancellationToken); + Logger.LogInformation($"{client.ClientId} AddAsync(1,1)={sum}"); + + var work = new Work + { + Op = Operation.DIVIDE, + Num1 = 1, + Num2 = 0 + }; + + try + { + Logger.LogInformation($"{client.ClientId} CalculateAsync(1)"); + await client.calculateAsync(1, work, cancellationToken); + Logger.LogInformation($"{client.ClientId} Whoa we can divide by 0"); + } + catch (InvalidOperation io) + { + Logger.LogInformation($"{client.ClientId} Invalid operation: " + io); + } + + work.Op = Operation.SUBTRACT; + work.Num1 = 15; + work.Num2 = 10; + + try + { + Logger.LogInformation($"{client.ClientId} CalculateAsync(1)"); + var diff = await client.calculateAsync(1, work, cancellationToken); + Logger.LogInformation($"{client.ClientId} 15-10={diff}"); + } + catch (InvalidOperation io) + { + Logger.LogInformation($"{client.ClientId} Invalid operation: " + io); + } + + Logger.LogInformation($"{client.ClientId} GetStructAsync(1)"); + var log = await client.getStructAsync(1, cancellationToken); + Logger.LogInformation($"{client.ClientId} Check log: {log.Value}"); + + Logger.LogInformation($"{client.ClientId} ZipAsync() with delay 100mc on server side"); + await client.zipAsync(cancellationToken); + } + private static async Task ExecuteSharedServiceClientOperations(CancellationToken cancellationToken, SharedService.Client client) + { + await client.OpenTransportAsync(cancellationToken); + + // Async version + + Logger.LogInformation($"{client.ClientId} SharedService GetStructAsync(1)"); + var log = await client.getStructAsync(1, cancellationToken); + Logger.LogInformation($"{client.ClientId} SharedService Value: {log.Value}"); + } + + + private enum Transport + { + Tcp, + NamedPipe, + Http, + TcpBuffered, + Framed, + TcpTls + } + + private enum Protocol + { + Binary, + Compact, + Json, + Multiplexed + } + + private enum Buffering + { + None, + Buffered, + Framed + } + } +} diff --git a/src/jaegertracing/thrift/tutorial/netstd/Client/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/tutorial/netstd/Client/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..568382e66 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Client/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// 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. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("de78a01b-f7c6-49d1-97da-669d2ed37641")]
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netstd/Client/Properties/launchSettings.json b/src/jaegertracing/thrift/tutorial/netstd/Client/Properties/launchSettings.json new file mode 100644 index 000000000..6b7b60d78 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Client/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Client": { + "commandName": "Project", + "commandLineArgs": "-p:multiplexed" + } + } +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netstd/Client/ThriftTest.pfx b/src/jaegertracing/thrift/tutorial/netstd/Client/ThriftTest.pfx Binary files differnew file mode 100644 index 000000000..f0ded2817 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Client/ThriftTest.pfx diff --git a/src/jaegertracing/thrift/tutorial/netstd/Interfaces/.gitignore b/src/jaegertracing/thrift/tutorial/netstd/Interfaces/.gitignore new file mode 100644 index 000000000..2e7446e33 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Interfaces/.gitignore @@ -0,0 +1,3 @@ +# ignore for autogenerated files +/shared +/tutorial diff --git a/src/jaegertracing/thrift/tutorial/netstd/Interfaces/Interfaces.csproj b/src/jaegertracing/thrift/tutorial/netstd/Interfaces/Interfaces.csproj new file mode 100644 index 000000000..4ebeb4f42 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Interfaces/Interfaces.csproj @@ -0,0 +1,48 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <!-- + 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. + --> + + <PropertyGroup> + <TargetFramework>netstandard2.0</TargetFramework> + <AssemblyName>Interfaces</AssemblyName> + <PackageId>Interfaces</PackageId> + <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> + <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> + <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> + <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="../../../lib/netstd/Thrift/Thrift.csproj" /> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="System.ServiceModel.Primitives" Version="4.5.3" /> + </ItemGroup> + + <Target Name="PreBuild" BeforeTargets="_GenerateRestoreProjectSpec;Restore;Compile"> + <Exec Condition="'$(OS)' == 'Windows_NT'" Command="where thrift" ConsoleToMSBuild="true"> + <Output TaskParameter="ConsoleOutput" PropertyName="PathToThrift" /> + </Exec> + <Exec Condition="Exists('$(PathToThrift)')" Command="$(PathToThrift) -out $(ProjectDir) -gen netstd:wcf,union,serial -r ./../../tutorial.thrift" /> + <Exec Condition="Exists('thrift')" Command="thrift -out $(ProjectDir) -gen netstd:wcf,union,serial -r ./../../tutorial.thrift" /> + <Exec Condition="Exists('./../../../compiler/cpp/thrift')" Command="./../../../compiler/cpp/thrift -out $(ProjectDir) -gen netstd:wcf,union,serial -r ./../../tutorial.thrift" /> + </Target> + +</Project> diff --git a/src/jaegertracing/thrift/tutorial/netstd/Interfaces/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/tutorial/netstd/Interfaces/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..9126b173e --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Interfaces/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// 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. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("4d13163d-9067-4c9c-8af0-64e08451397d")]
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netstd/Makefile.am b/src/jaegertracing/thrift/tutorial/netstd/Makefile.am new file mode 100644 index 000000000..e30555655 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Makefile.am @@ -0,0 +1,42 @@ +# +# 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. +# + +SUBDIRS = . + +all-local: + $(DOTNETCORE) build + +clean-local: + $(RM) Interfaces.dll + $(RM) -r Client/bin + $(RM) -r Client/obj + $(RM) -r Server/bin + $(RM) -r Server/obj + $(RM) -r Interfaces/bin + $(RM) -r Interfaces/obj + +EXTRA_DIST = \ + Client \ + Interfaces \ + README.md \ + Server \ + Tutorial.sln \ + build.cmd \ + build.sh + diff --git a/src/jaegertracing/thrift/tutorial/netstd/README.md b/src/jaegertracing/thrift/tutorial/netstd/README.md new file mode 100644 index 000000000..b1dea4ecb --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/README.md @@ -0,0 +1,284 @@ +# Building of samples for different platforms + +# Reused components +- NET Core Standard 2.0 +- NET Core App 2.0 + +# How to build +- Download and install the latest .NET Core SDK for your platform https://www.microsoft.com/net/core#windowsvs2015 (archive for SDK 1.0.0-preview2-003121 located by: https://github.com/dotnet/core/blob/master/release-notes/download-archive.md) +- Ensure that you have thrift.exe which supports netstd lib and it added to PATH +- Go to current folder +- Run **build.sh** or **build.cmd** from the root of cloned repository +- Check tests in **src/Tests** folder +- Continue with /tutorials/netstd + +# How to run + +Notes: dotnet run supports passing arguments to app after -- symbols (https://docs.microsoft.com/en-us/dotnet/articles/core/tools/dotnet-run) - example: **dotnet run -- -h** will show help for app + +- build +- go to folder (Client/Server) +- run with specifying of correct parameters **dotnet run -tr:tcp -pr:multiplexed**, **dotnet run -help** (later, after migration to csproj and latest SDK will be possibility to use more usable form **dotnet run -- arguments**) + +#Notes +- Possible adding additional platforms after stabilization of .NET Core (runtimes, platforms (Red Hat Linux, OpenSuse, etc.) + +#Known issues +- In trace logging mode you can see some not important internal exceptions + +# Running of samples +Please install Thrift C# .NET Core library or copy sources and build them to correcly build and run samples + +# NetCore Server + +Usage: + + Server.exe -h + will diplay help information + + Server.exe -tr:<transport> -pr:<protocol> + will run server with specified arguments (tcp transport and binary protocol by default) + +Options: + + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (http address - ""localhost:9090"") + tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) + + -bf (buffering): + none - (default) no transport factory will be used + buffered - buffered transport factory will be used + framed - framed transport factory will be used (this must match the client) + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + +Sample: + + Server.exe -tr:tcp + +**Remarks**: + + For TcpTls mode certificate's file ThriftTest.pfx should be in directory with binaries in case of command line usage (or at project level in case of debugging from IDE). + Password for certificate - "ThriftTest". + + + +# NetCore Client + +Usage: + + Client.exe -h + will diplay help information + + Client.exe -tr:<transport> -pr:<protocol> -mc:<numClients> + will run client with specified arguments (tcp transport and binary protocol by default) + +Options: + + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (address - ""http://localhost:9090"") + tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) + + -bf (buffering): + none - (default) no transport factory will be used + buffered - buffered transport factory will be used + framed - framed transport factory will be used (this must match the client) + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + + -mc (multiple clients): + <numClients> - number of multiple clients to connect to server (max 100, default 1) + +Sample: + + Client.exe -tr:tcp -pr:binary -mc:10 + +Remarks: + + For TcpTls mode certificate's file ThriftTest.pfx should be in directory + with binaries in case of command line usage (or at project level in case of debugging from IDE). + Password for certificate - "ThriftTest". + +# How to test communication between NetCore and Python + +* Generate code with the latest **thrift.exe** util +* Ensure that **thrift.exe** util generated folder **gen-py** with generated code for Python +* Create **client.py** and **server.py** from the code examples below and save them to the folder with previosly generated folder **gen-py** +* Run netstd samples (client and server) and python samples (client and server) + +Remarks: + +Samples of client and server code below use correct methods (operations) +and fields (properties) according to generated contracts from *.thrift files + +At Windows 10 add record **127.0.0.1 testserver** to **C:\Windows\System32\drivers\etc\hosts** file +for correct work of python server + + +**Python Client:** + +```python +import sys +import glob +sys.path.append('gen-py') + +from tutorial import Calculator +from tutorial.ttypes import InvalidOperation, Operation, Work + +from thrift import Thrift +from thrift.transport import TSocket +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol + + +def main(): + # Make socket + transport = TSocket.TSocket('127.0.0.1', 9090) + + # Buffering is critical. Raw sockets are very slow + transport = TTransport.TBufferedTransport(transport) + + # Wrap in a protocol + protocol = TBinaryProtocol.TBinaryProtocol(transport) + + # Create a client to use the protocol encoder + client = Calculator.Client(protocol) + + # Connect! + transport.open() + + client.Ping() + print('ping()') + + sum = client.Add(1, 1) + print(('1+1=%d' % (sum))) + + work = Work() + + work.Op = Operation.Divide + work.Num1 = 1 + work.Num2 = 0 + + try: + quotient = client.Calculate(1, work) + print('Whoa? You know how to divide by zero?') + print('FYI the answer is %d' % quotient) + except InvalidOperation as e: + print(('InvalidOperation: %r' % e)) + + work.Op = Operation.Substract + work.Num1 = 15 + work.Num2 = 10 + + diff = client.Calculate(1, work) + print(('15-10=%d' % (diff))) + + log = client.GetStruct(1) + print(('Check log: %s' % (log.Value))) + + client.Zip() + print('zip()') + + # Close! + transport.close() + +if __name__ == '__main__': + try: + main() + except Thrift.TException as tx: + print('%s' % tx.message) +``` + + +**Python Server:** + + +```python +import glob +import sys +sys.path.append('gen-py') + +from tutorial import Calculator +from tutorial.ttypes import InvalidOperation, Operation + +from shared.ttypes import SharedStruct + +from thrift.transport import TSocket +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol +from thrift.server import TServer + + +class CalculatorHandler: + def __init__(self): + self.log = {} + + def Ping(self): + print('ping()') + + def Add(self, n1, n2): + print('add(%d,%d)' % (n1, n2)) + return n1 + n2 + + def Calculate(self, logid, work): + print('calculate(%d, %r)' % (logid, work)) + + if work.Op == Operation.Add: + val = work.Num1 + work.Num2 + elif work.Op == Operation.Substract: + val = work.Num1 - work.Num2 + elif work.Op == Operation.Multiply: + val = work.Num1 * work.Num2 + elif work.Op == Operation.Divide: + if work.Num2 == 0: + x = InvalidOperation() + x.WhatOp = work.Op + x.Why = 'Cannot divide by 0' + raise x + val = work.Num1 / work.Num2 + else: + x = InvalidOperation() + x.WhatOp = work.Op + x.Why = 'Invalid operation' + raise x + + log = SharedStruct() + log.Key = logid + log.Value = '%d' % (val) + self.log[logid] = log + + return val + + def GetStruct(self, key): + print('getStruct(%d)' % (key)) + return self.log[key] + + def Zip(self): + print('zip()') + +if __name__ == '__main__': + handler = CalculatorHandler() + processor = Calculator.Processor(handler) + transport = TSocket.TServerSocket(host="testserver", port=9090) + tfactory = TTransport.TBufferedTransportFactory() + pfactory = TBinaryProtocol.TBinaryProtocolFactory() + + server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) + print('Starting the server...') + server.serve() + print('done.') + + # You could do one of these for a multithreaded server + # server = TServer.TThreadedServer(processor, transport, tfactory, pfactory) + # server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory) +``` diff --git a/src/jaegertracing/thrift/tutorial/netstd/Server/Program.cs b/src/jaegertracing/thrift/tutorial/netstd/Server/Program.cs new file mode 100644 index 000000000..25e7daeed --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Server/Program.cs @@ -0,0 +1,479 @@ +// 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. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Protocol; +using Thrift.Server; +using Thrift.Transport; +using Thrift.Transport.Server; +using tutorial; +using shared; +using Thrift.Processor; +using System.Diagnostics; + +namespace Server +{ + public class Program + { + private static ServiceCollection ServiceCollection = new ServiceCollection(); + private static ILogger Logger; + + public static void Main(string[] args) + { + args = args ?? new string[0]; + + ServiceCollection.AddLogging(logging => ConfigureLogging(logging)); + Logger = ServiceCollection.BuildServiceProvider().GetService<ILoggerFactory>().CreateLogger(nameof(Server)); + + + if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) + { + DisplayHelp(); + return; + } + + using (var source = new CancellationTokenSource()) + { + RunAsync(args, source.Token).GetAwaiter().GetResult(); + + Logger.LogInformation("Press any key to stop..."); + + Console.ReadLine(); + source.Cancel(); + } + + Logger.LogInformation("Server stopped"); + } + + private static void ConfigureLogging(ILoggingBuilder logging) + { + logging.SetMinimumLevel(LogLevel.Trace); + logging.AddConsole(); + logging.AddDebug(); + } + + private static void DisplayHelp() + { + Logger.LogInformation(@" +Usage: + Server.exe -help + will diplay help information + + Server.exe -tr:<transport> -bf:<buffering> -pr:<protocol> + will run server with specified arguments (tcp transport, no buffering, and binary protocol by default) + +Options: + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (http address - ""localhost:9090"") + tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) + + -bf (buffering): + none - (default) no buffering will be used + buffered - buffered transport will be used + framed - framed transport will be used + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + multiplexed - multiplexed protocol will be used + +Sample: + Server.exe -tr:tcp +"); + } + + private static async Task RunAsync(string[] args, CancellationToken cancellationToken) + { + var selectedTransport = GetTransport(args); + var selectedBuffering = GetBuffering(args); + var selectedProtocol = GetProtocol(args); + + if (selectedTransport == Transport.Http) + { + new HttpServerSample().Run(cancellationToken); + } + else + { + await RunSelectedConfigurationAsync(selectedTransport, selectedBuffering, selectedProtocol, cancellationToken); + } + } + + private static Protocol GetProtocol(string[] args) + { + var transport = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; + + Enum.TryParse(transport, true, out Protocol selectedProtocol); + + return selectedProtocol; + } + + private static Buffering GetBuffering(string[] args) + { + var buffering = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(":")?[1]; + + Enum.TryParse<Buffering>(buffering, out var selectedBuffering); + + return selectedBuffering; + } + + private static Transport GetTransport(string[] args) + { + var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; + + Enum.TryParse(transport, true, out Transport selectedTransport); + + return selectedTransport; + } + + private static async Task RunSelectedConfigurationAsync(Transport transport, Buffering buffering, Protocol protocol, CancellationToken cancellationToken) + { + var handler = new CalculatorAsyncHandler(); + + TServerTransport serverTransport = null; + switch (transport) + { + case Transport.Tcp: + serverTransport = new TServerSocketTransport(9090); + break; + case Transport.NamedPipe: + serverTransport = new TNamedPipeServerTransport(".test"); + break; + case Transport.TcpTls: + serverTransport = new TTlsServerSocketTransport(9090, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback); + break; + } + + TTransportFactory inputTransportFactory = null; + TTransportFactory outputTransportFactory = null; + switch (buffering) + { + case Buffering.Buffered: + inputTransportFactory = new TBufferedTransport.Factory(); + outputTransportFactory = new TBufferedTransport.Factory(); + break; + + case Buffering.Framed: + inputTransportFactory = new TFramedTransport.Factory(); + outputTransportFactory = new TFramedTransport.Factory(); + break; + + default: // layered transport(s) are optional + Debug.Assert(buffering == Buffering.None, "unhandled case"); + break; + } + + TProtocolFactory inputProtocolFactory = null; + TProtocolFactory outputProtocolFactory = null; + ITAsyncProcessor processor = null; + switch (protocol) + { + case Protocol.Binary: + inputProtocolFactory = new TBinaryProtocol.Factory(); + outputProtocolFactory = new TBinaryProtocol.Factory(); + processor = new Calculator.AsyncProcessor(handler); + break; + + case Protocol.Compact: + inputProtocolFactory = new TCompactProtocol.Factory(); + outputProtocolFactory = new TCompactProtocol.Factory(); + processor = new Calculator.AsyncProcessor(handler); + break; + + case Protocol.Json: + inputProtocolFactory = new TJsonProtocol.Factory(); + outputProtocolFactory = new TJsonProtocol.Factory(); + processor = new Calculator.AsyncProcessor(handler); + break; + + case Protocol.Multiplexed: + inputProtocolFactory = new TBinaryProtocol.Factory(); + outputProtocolFactory = new TBinaryProtocol.Factory(); + + var calcHandler = new CalculatorAsyncHandler(); + var calcProcessor = new Calculator.AsyncProcessor(calcHandler); + + var sharedServiceHandler = new SharedServiceAsyncHandler(); + var sharedServiceProcessor = new SharedService.AsyncProcessor(sharedServiceHandler); + + var multiplexedProcessor = new TMultiplexedProcessor(); + multiplexedProcessor.RegisterProcessor(nameof(Calculator), calcProcessor); + multiplexedProcessor.RegisterProcessor(nameof(SharedService), sharedServiceProcessor); + + processor = multiplexedProcessor; + break; + + default: + throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null); + } + + + try + { + Logger.LogInformation( + $"Selected TAsyncServer with {serverTransport} transport, {processor} processor and {inputProtocolFactory} protocol factories"); + + var loggerFactory = ServiceCollection.BuildServiceProvider().GetService<ILoggerFactory>(); + + var server = new TSimpleAsyncServer( + itProcessorFactory: new TSingletonProcessorFactory(processor), + serverTransport: serverTransport, + inputTransportFactory: inputTransportFactory, + outputTransportFactory: outputTransportFactory, + inputProtocolFactory: inputProtocolFactory, + outputProtocolFactory: outputProtocolFactory, + logger: loggerFactory.CreateLogger<TSimpleAsyncServer>()); + + Logger.LogInformation("Starting the server..."); + + await server.ServeAsync(cancellationToken); + } + catch (Exception x) + { + Logger.LogInformation(x.ToString()); + } + } + + private static X509Certificate2 GetCertificate() + { + // due to files location in net core better to take certs from top folder + var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory())); + return new X509Certificate2(certFile, "ThriftTest"); + } + + private static string GetCertPath(DirectoryInfo di, int maxCount = 6) + { + var topDir = di; + var certFile = + topDir.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories) + .FirstOrDefault(); + if (certFile == null) + { + if (maxCount == 0) + throw new FileNotFoundException("Cannot find file in directories"); + return GetCertPath(di.Parent, maxCount - 1); + } + + return certFile.FullName; + } + + private static X509Certificate LocalCertificateSelectionCallback(object sender, + string targetHost, X509CertificateCollection localCertificates, + X509Certificate remoteCertificate, string[] acceptableIssuers) + { + return GetCertificate(); + } + + private static bool ClientCertValidator(object sender, X509Certificate certificate, + X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + return true; + } + + private enum Transport + { + Tcp, + NamedPipe, + Http, + TcpTls, + } + + private enum Buffering + { + None, + Buffered, + Framed, + } + + private enum Protocol + { + Binary, + Compact, + Json, + Multiplexed + } + + public class HttpServerSample + { + public void Run(CancellationToken cancellationToken) + { + var config = new ConfigurationBuilder() + .AddEnvironmentVariables(prefix: "ASPNETCORE_") + .Build(); + + var host = new WebHostBuilder() + .UseConfiguration(config) + .UseKestrel() + .UseUrls("http://localhost:9090") + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseStartup<Startup>() + .ConfigureLogging((ctx,logging) => ConfigureLogging(logging)) + .Build(); + + Logger.LogTrace("test"); + Logger.LogCritical("test"); + host.RunAsync(cancellationToken).GetAwaiter().GetResult(); + } + + public class Startup + { + public Startup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddEnvironmentVariables(); + + Configuration = builder.Build(); + } + + public IConfigurationRoot Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddTransient<Calculator.IAsync, CalculatorAsyncHandler>(); + services.AddTransient<ITAsyncProcessor, Calculator.AsyncProcessor>(); + services.AddTransient<THttpServerTransport, THttpServerTransport>(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + app.UseMiddleware<THttpServerTransport>(); + } + } + } + + public class CalculatorAsyncHandler : Calculator.IAsync + { + private readonly Dictionary<int, SharedStruct> _log = new Dictionary<int, SharedStruct>(); + + public CalculatorAsyncHandler() + { + } + + public async Task<SharedStruct> getStructAsync(int key, + CancellationToken cancellationToken) + { + Logger.LogInformation("GetStructAsync({0})", key); + return await Task.FromResult(_log[key]); + } + + public async Task pingAsync(CancellationToken cancellationToken) + { + Logger.LogInformation("PingAsync()"); + await Task.CompletedTask; + } + + public async Task<int> addAsync(int num1, int num2, CancellationToken cancellationToken) + { + Logger.LogInformation($"AddAsync({num1},{num2})"); + return await Task.FromResult(num1 + num2); + } + + public async Task<int> calculateAsync(int logid, Work w, CancellationToken cancellationToken) + { + Logger.LogInformation($"CalculateAsync({logid}, [{w.Op},{w.Num1},{w.Num2}])"); + + var val = 0; + switch (w.Op) + { + case Operation.ADD: + val = w.Num1 + w.Num2; + break; + + case Operation.SUBTRACT: + val = w.Num1 - w.Num2; + break; + + case Operation.MULTIPLY: + val = w.Num1 * w.Num2; + break; + + case Operation.DIVIDE: + if (w.Num2 == 0) + { + var io = new InvalidOperation + { + WhatOp = (int) w.Op, + Why = "Cannot divide by 0" + }; + + throw io; + } + val = w.Num1 / w.Num2; + break; + + default: + { + var io = new InvalidOperation + { + WhatOp = (int) w.Op, + Why = "Unknown operation" + }; + + throw io; + } + } + + var entry = new SharedStruct + { + Key = logid, + Value = val.ToString() + }; + + _log[logid] = entry; + + return await Task.FromResult(val); + } + + public async Task zipAsync(CancellationToken cancellationToken) + { + Logger.LogInformation("ZipAsync() with delay 100mc"); + await Task.Delay(100, CancellationToken.None); + } + } + + public class SharedServiceAsyncHandler : SharedService.IAsync + { + public async Task<SharedStruct> getStructAsync(int key, CancellationToken cancellationToken) + { + Logger.LogInformation("GetStructAsync({0})", key); + return await Task.FromResult(new SharedStruct() + { + Key = key, + Value = "GetStructAsync" + }); + } + } + } +} diff --git a/src/jaegertracing/thrift/tutorial/netstd/Server/Properties/AssemblyInfo.cs b/src/jaegertracing/thrift/tutorial/netstd/Server/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..a0442350b --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Server/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// 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. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("e210fc10-5aff-4b04-ac21-58afc7b74b0c")]
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netstd/Server/Properties/launchSettings.json b/src/jaegertracing/thrift/tutorial/netstd/Server/Properties/launchSettings.json new file mode 100644 index 000000000..78076ff7c --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Server/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Server": { + "commandName": "Project", + "commandLineArgs": "-p:multiplexed" + } + } +}
\ No newline at end of file diff --git a/src/jaegertracing/thrift/tutorial/netstd/Server/Server.csproj b/src/jaegertracing/thrift/tutorial/netstd/Server/Server.csproj new file mode 100644 index 000000000..fbc2c0370 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Server/Server.csproj @@ -0,0 +1,44 @@ +<Project Sdk="Microsoft.NET.Sdk.Web"> + <!-- + 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. + --> + + <PropertyGroup> + <TargetFramework>netcoreapp2.0</TargetFramework> + <AssemblyName>Server</AssemblyName> + <PackageId>Server</PackageId> + <OutputType>Exe</OutputType> + <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> + <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> + <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> + <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="../Interfaces/Interfaces.csproj" /> + <ProjectReference Include="../../../lib/netstd/Thrift/Thrift.csproj" /> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" /> + <PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="2.2.1" /> + <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" /> + <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.2.0" /> + </ItemGroup> + +</Project> diff --git a/src/jaegertracing/thrift/tutorial/netstd/Server/ThriftTest.pfx b/src/jaegertracing/thrift/tutorial/netstd/Server/ThriftTest.pfx Binary files differnew file mode 100644 index 000000000..f0ded2817 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Server/ThriftTest.pfx diff --git a/src/jaegertracing/thrift/tutorial/netstd/Tutorial.sln b/src/jaegertracing/thrift/tutorial/netstd/Tutorial.sln new file mode 100644 index 000000000..84b257902 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/Tutorial.sln @@ -0,0 +1,78 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26114.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netstd\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Interfaces", "Interfaces\Interfaces.csproj", "{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.ActiveCfg = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.Build.0 = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.ActiveCfg = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.Build.0 = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.Build.0 = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.ActiveCfg = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.Build.0 = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.ActiveCfg = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.Build.0 = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.ActiveCfg = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.Build.0 = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.ActiveCfg = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.Build.0 = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.Build.0 = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.ActiveCfg = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.Build.0 = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.ActiveCfg = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.Build.0 = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.ActiveCfg = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.Build.0 = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.ActiveCfg = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.Build.0 = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.Build.0 = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.ActiveCfg = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.Build.0 = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.ActiveCfg = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {070A5D1D-B29D-4603-999D-693DB444AD0D} + EndGlobalSection +EndGlobal diff --git a/src/jaegertracing/thrift/tutorial/netstd/build.cmd b/src/jaegertracing/thrift/tutorial/netstd/build.cmd new file mode 100644 index 000000000..9b84ef276 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/build.cmd @@ -0,0 +1,25 @@ +@echo off +rem /* +rem * Licensed to the Apache Software Foundation (ASF) under one +rem * or more contributor license agreements. See the NOTICE file +rem * distributed with this work for additional information +rem * regarding copyright ownership. The ASF licenses this file +rem * to you under the Apache License, Version 2.0 (the +rem * "License"); you may not use this file except in compliance +rem * with the License. You may obtain a copy of the License at +rem * +rem * http://www.apache.org/licenses/LICENSE-2.0 +rem * +rem * Unless required by applicable law or agreed to in writing, +rem * software distributed under the License is distributed on an +rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem * KIND, either express or implied. See the License for the +rem * specific language governing permissions and limitations +rem * under the License. +rem */ +setlocal + +dotnet --info +dotnet build + +:eof diff --git a/src/jaegertracing/thrift/tutorial/netstd/build.sh b/src/jaegertracing/thrift/tutorial/netstd/build.sh new file mode 100644 index 000000000..c97e310f0 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/netstd/build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# +# 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. +# + +#exit if any command fails +set -e + +dotnet --info +dotnet build diff --git a/src/jaegertracing/thrift/tutorial/nodejs/Makefile.am b/src/jaegertracing/thrift/tutorial/nodejs/Makefile.am new file mode 100644 index 000000000..1516fec2c --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/nodejs/Makefile.am @@ -0,0 +1,45 @@ +# +# 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. +# + +gen-nodejs/Calculator.js gen-nodejs/SharedService.js: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen js:node -r $< + +all-local: gen-nodejs/Calculator.js + +tutorialserver: all + NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeServer.js + +tutorialclient: all + NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeClient.js + +tutorialserver_promise: all + NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeServerPromise.js + +tutorialclient_promise: all + NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeClientPromise.js + + +clean-local: + $(RM) -r gen-* + +EXTRA_DIST = \ + NodeServer.js \ + NodeClient.js \ + NodeServerPromise.js \ + NodeClientPromise.js diff --git a/src/jaegertracing/thrift/tutorial/nodejs/NodeClient.js b/src/jaegertracing/thrift/tutorial/nodejs/NodeClient.js new file mode 100644 index 000000000..b4886e826 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/nodejs/NodeClient.js @@ -0,0 +1,77 @@ +/* + * 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. + */ + +var thrift = require('thrift'); +var Calculator = require('./gen-nodejs/Calculator'); +var ttypes = require('./gen-nodejs/tutorial_types'); +const assert = require('assert'); + +var transport = thrift.TBufferedTransport; +var protocol = thrift.TBinaryProtocol; + +var connection = thrift.createConnection("localhost", 9090, { + transport : transport, + protocol : protocol +}); + +connection.on('error', function(err) { + assert(false, err); +}); + +// Create a Calculator client with the connection +var client = thrift.createClient(Calculator, connection); + + +client.ping(function(err, response) { + console.log('ping()'); +}); + + +client.add(1,1, function(err, response) { + console.log("1+1=" + response); +}); + + +work = new ttypes.Work(); +work.op = ttypes.Operation.DIVIDE; +work.num1 = 1; +work.num2 = 0; + +client.calculate(1, work, function(err, message) { + if (err) { + console.log("InvalidOperation " + err); + } else { + console.log('Whoa? You know how to divide by zero?'); + } +}); + +work.op = ttypes.Operation.SUBTRACT; +work.num1 = 15; +work.num2 = 10; + +client.calculate(1, work, function(err, message) { + console.log('15-10=' + message); + + client.getStruct(1, function(err, message){ + console.log('Check log: ' + message.value); + + //close the connection once we're done + connection.end(); + }); +}); diff --git a/src/jaegertracing/thrift/tutorial/nodejs/NodeClientPromise.js b/src/jaegertracing/thrift/tutorial/nodejs/NodeClientPromise.js new file mode 100644 index 000000000..2cdc184f9 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/nodejs/NodeClientPromise.js @@ -0,0 +1,80 @@ +/* + * 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. + */ + +var thrift = require('thrift'); +var Calculator = require('./gen-nodejs/Calculator'); +var ttypes = require('./gen-nodejs/tutorial_types'); +const assert = require('assert'); + +var transport = thrift.TBufferedTransport; +var protocol = thrift.TBinaryProtocol; + +var connection = thrift.createConnection("localhost", 9090, { + transport : transport, + protocol : protocol +}); + +connection.on('error', function(err) { + assert(false, err); +}); + +// Create a Calculator client with the connection +var client = thrift.createClient(Calculator, connection); + + +client.ping() + .then(function() { + console.log('ping()'); + }); + +client.add(1,1) + .then(function(response) { + console.log("1+1=" + response); + }); + +work = new ttypes.Work(); +work.op = ttypes.Operation.DIVIDE; +work.num1 = 1; +work.num2 = 0; + +client.calculate(1, work) + .then(function(message) { + console.log('Whoa? You know how to divide by zero?'); + }) + .fail(function(err) { + console.log("InvalidOperation " + err); + }); + + +work.op = ttypes.Operation.SUBTRACT; +work.num1 = 15; +work.num2 = 10; + +client.calculate(1, work) + .then(function(value) { + console.log('15-10=' + value); + return client.getStruct(1); + }) + .then(function(message) { + console.log('Check log: ' + message.value); + }) + .fin(function() { + //close the connection once we're done + connection.end(); + }); diff --git a/src/jaegertracing/thrift/tutorial/nodejs/NodeServer.js b/src/jaegertracing/thrift/tutorial/nodejs/NodeServer.js new file mode 100644 index 000000000..2e198825c --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/nodejs/NodeServer.js @@ -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. + */ + +var thrift = require("thrift"); +var Calculator = require("./gen-nodejs/Calculator"); +var ttypes = require("./gen-nodejs/tutorial_types"); +var SharedStruct = require("./gen-nodejs/shared_types").SharedStruct; + +var data = {}; + +var server = thrift.createServer(Calculator, { + ping: function(result) { + console.log("ping()"); + result(null); + }, + + add: function(n1, n2, result) { + console.log("add(", n1, ",", n2, ")"); + result(null, n1 + n2); + }, + + calculate: function(logid, work, result) { + console.log("calculate(", logid, ",", work, ")"); + + var val = 0; + if (work.op == ttypes.Operation.ADD) { + val = work.num1 + work.num2; + } else if (work.op === ttypes.Operation.SUBTRACT) { + val = work.num1 - work.num2; + } else if (work.op === ttypes.Operation.MULTIPLY) { + val = work.num1 * work.num2; + } else if (work.op === ttypes.Operation.DIVIDE) { + if (work.num2 === 0) { + var x = new ttypes.InvalidOperation(); + x.whatOp = work.op; + x.why = 'Cannot divide by 0'; + result(x); + return; + } + val = work.num1 / work.num2; + } else { + var x = new ttypes.InvalidOperation(); + x.whatOp = work.op; + x.why = 'Invalid operation'; + result(x); + return; + } + + var entry = new SharedStruct(); + entry.key = logid; + entry.value = ""+val; + data[logid] = entry; + + result(null, val); + }, + + getStruct: function(key, result) { + console.log("getStruct(", key, ")"); + result(null, data[key]); + }, + + zip: function() { + console.log("zip()"); + } + +}); + +server.listen(9090); diff --git a/src/jaegertracing/thrift/tutorial/nodejs/NodeServerPromise.js b/src/jaegertracing/thrift/tutorial/nodejs/NodeServerPromise.js new file mode 100644 index 000000000..bff287b18 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/nodejs/NodeServerPromise.js @@ -0,0 +1,80 @@ +/* + * 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. + */ + +var thrift = require("thrift"); +var Calculator = require("./gen-nodejs/Calculator"); +var ttypes = require("./gen-nodejs/tutorial_types"); +var SharedStruct = require("./gen-nodejs/shared_types").SharedStruct; + +var data = {}; + +var server = thrift.createServer(Calculator, { + ping: function() { + console.log("ping()"); + }, + + add: function(n1, n2) { + console.log("add(", n1, ",", n2, ")"); + return n1 + n2; + }, + + calculate: function(logid, work) { + console.log("calculate(", logid, ",", work, ")"); + + var val = 0; + if (work.op == ttypes.Operation.ADD) { + val = work.num1 + work.num2; + } else if (work.op === ttypes.Operation.SUBTRACT) { + val = work.num1 - work.num2; + } else if (work.op === ttypes.Operation.MULTIPLY) { + val = work.num1 * work.num2; + } else if (work.op === ttypes.Operation.DIVIDE) { + if (work.num2 === 0) { + var x = new ttypes.InvalidOperation(); + x.whatOp = work.op; + x.why = 'Cannot divide by 0'; + throw x; + } + val = work.num1 / work.num2; + } else { + var x = new ttypes.InvalidOperation(); + x.whatOp = work.op; + x.why = 'Invalid operation'; + throw x; + } + + var entry = new SharedStruct(); + entry.key = logid; + entry.value = ""+val; + data[logid] = entry; + return val; + }, + + getStruct: function(key) { + console.log("getStruct(", key, ")"); + return data[key]; + }, + + zip: function() { + console.log("zip()"); + } + +}); + +server.listen(9090); diff --git a/src/jaegertracing/thrift/tutorial/ocaml/CalcClient.ml b/src/jaegertracing/thrift/tutorial/ocaml/CalcClient.ml new file mode 100755 index 000000000..5a8467be2 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/ocaml/CalcClient.ml @@ -0,0 +1,74 @@ +(* + 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. +*) + +open Arg +open Thrift +open Tutorial_types +open Shared_types + +exception Die;; +let sod = function + Some v -> v + | None -> raise Die;; + +type connection = { + trans : Transport.t ; + proto : Thrift.Protocol.t; + calc : Calculator.client ; +} + +let connect ~host port = + let tx = new TSocket.t host port in + let proto = new TBinaryProtocol.t tx in + let calc = new Calculator.client proto proto in + tx#opn; + { trans = tx ; proto = proto; calc = calc } +;; + +let doclient () = + let cli = connect ~host:"127.0.0.1" 9090 in + try + cli.calc#ping ; + Printf.printf "ping()\n" ; flush stdout ; + (let sum = cli.calc#add (Int32.of_int 1) (Int32.of_int 1) in + Printf.printf "1+1=%ld\n" sum ; + flush stdout) ; + (let w = new work in + w#set_op Operation.DIVIDE ; + w#set_num1 (Int32.of_int 1) ; + w#set_num2 (Int32.of_int 0) ; + try + let quotient = cli.calc#calculate (Int32.of_int 1) w in + Printf.printf "Whoa? We can divide by zero!\n" ; flush stdout + with InvalidOperation io -> + Printf.printf "InvalidOperation: %s\n" io#grab_why ; flush stdout) ; + (let w = new work in + w#set_op Operation.SUBTRACT ; + w#set_num1 (Int32.of_int 15) ; + w#set_num2 (Int32.of_int 10) ; + let diff = cli.calc#calculate (Int32.of_int 1) w in + Printf.printf "15-10=%ld\n" diff ; flush stdout) ; + (let ss = cli.calc#getStruct (Int32.of_int 1) in + Printf.printf "Check log: %s\n" ss#grab_value ; flush stdout) ; + cli.trans#close + with Transport.E (_,what) -> + Printf.printf "ERROR: %s\n" what ; flush stdout +;; + +doclient();; diff --git a/src/jaegertracing/thrift/tutorial/ocaml/CalcServer.ml b/src/jaegertracing/thrift/tutorial/ocaml/CalcServer.ml new file mode 100755 index 000000000..b5facb79b --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/ocaml/CalcServer.ml @@ -0,0 +1,89 @@ +(* + 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. +*) + +open Arg +open Thrift +open Tutorial_types +open Shared_types + +exception Die;; +let sod = function + Some v -> v + | None -> raise Die;; + +class calc_handler = +object (self) + inherit Calculator.iface + val log = Hashtbl.create 23 + method ping = Printf.printf "ping()\n" ; flush stdout + method add a b = + Printf.printf"add(%ld,%ld)\n" (sod a) (sod b); flush stdout ; + Int32.add (sod a) (sod b) + method calculate logid w = + let w = sod w in + Printf.printf "calculate(%ld,{%ld,%ld,%ld})\n" (sod logid) (Operation.to_i w#grab_op) w#grab_num1 w#grab_num2; flush stdout ; + let rv = + match w#grab_op with + Operation.ADD -> + Int32.add w#grab_num1 w#grab_num2 + | Operation.SUBTRACT -> + Int32.sub w#grab_num1 w#grab_num2 + | Operation.MULTIPLY -> + Int32.mul w#grab_num1 w#grab_num2 + | Operation.DIVIDE -> + if w#grab_num2 = Int32.zero then + let io = new invalidOperation in + io#set_whatOp (Operation.to_i w#grab_op) ; + io#set_why "Cannot divide by 0" ; + raise (InvalidOperation io) + else + Int32.div w#grab_num1 w#grab_num2 in + + let ss = new sharedStruct in + ss#set_key (sod logid) ; + let buffer = Int32.to_string rv in + ss#set_value buffer ; + Hashtbl.add log (sod logid) ss ; + rv + + method zip = + Printf.printf "zip()\n"; flush stdout + + method getStruct logid = + Printf.printf "getStruct(%ld)\n" (sod logid) ; flush stdout ; + Hashtbl.find log (sod logid) + +end + +let doserver () = + let h = new calc_handler in + let proc = new Calculator.processor h in + let port = 9090 in + let pf = new TBinaryProtocol.factory in + let server = new TThreadedServer.t + proc + (new TServerSocket.t port) + (new Transport.factory) + pf + pf + in + server#serve +;; + +doserver();; diff --git a/src/jaegertracing/thrift/tutorial/ocaml/README.md b/src/jaegertracing/thrift/tutorial/ocaml/README.md new file mode 100644 index 000000000..f68e83525 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/ocaml/README.md @@ -0,0 +1,15 @@ + +This is the ocaml tutorial example. It assumes that you've already +built and installed the thrift ocaml runtime libraries in lib/ocaml. + +To compile this, you will need to generate the Thrift sources for +ocaml in this directory (due to limitations in the OASIS build-tool): + + % thrift -r --gen ocaml ../tutorial.thrift + % oasis setup + % make + +This will produce two executables Calc{Server,Client}.<type> where +<type> is one of "byte" or "native", depending on your ocaml +installation. Just run the server in the background, then the client +(as you would do for the C++ example). diff --git a/src/jaegertracing/thrift/tutorial/ocaml/_oasis b/src/jaegertracing/thrift/tutorial/ocaml/_oasis new file mode 100644 index 000000000..4a4f337b3 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/ocaml/_oasis @@ -0,0 +1,32 @@ +Name: tutorial +Version: 0.13.0 +OASISFormat: 0.3 +Synopsis: OCaml Tutorial example +Authors: Apache Thrift Developers <dev@thrift.apache.org> +License: Apache-2.0 +Homepage: http://thrift.apache.org +BuildTools: ocamlbuild +Plugins: META (0.3), + DevFiles (0.3) + +Library tutorial_thrift + Path: gen-ocaml + FindlibName: tutorial_thrift + buildTools: ocamlbuild + BuildDepends: threads,thrift + Modules: Calculator,Shared_consts,Tutorial_consts,SharedService,Shared_types,Tutorial_types + XMETARequires: threads + +Executable CalcClient + Path: . + MainIs: CalcClient.ml + Build$: true + CompiledObject: best + BuildDepends: thrift, tutorial_thrift, threads + +Executable CalcServer + Path: . + MainIs: CalcServer.ml + Build$: true + CompiledObject: best + BuildDepends: thrift, tutorial_thrift, threads diff --git a/src/jaegertracing/thrift/tutorial/perl/PerlClient.pl b/src/jaegertracing/thrift/tutorial/perl/PerlClient.pl new file mode 100644 index 000000000..7c23289ce --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/perl/PerlClient.pl @@ -0,0 +1,82 @@ +#!/usr/bin/env perl + +# +# 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. +# + +use strict; +use warnings; + +use lib '../../lib/perl/lib'; +use lib '../gen-perl'; + +use Thrift; +use Thrift::BinaryProtocol; +use Thrift::Socket; +use Thrift::BufferedTransport; + +use shared::SharedService; +use tutorial::Calculator; +use shared::Types; +use tutorial::Types; + +use Data::Dumper; + +my $socket = Thrift::Socket->new('localhost',9090); +my $transport = Thrift::BufferedTransport->new($socket,1024,1024); +my $protocol = Thrift::BinaryProtocol->new($transport); +my $client = tutorial::CalculatorClient->new($protocol); + + +eval{ + $transport->open(); + + $client->ping(); + print "ping()\n"; + + + my $sum = $client->add(1,1); + print "1+1=$sum\n"; + + my $work = tutorial::Work->new(); + + $work->op(tutorial::Operation::DIVIDE); + $work->num1(1); + $work->num2(0); + + eval { + $client->calculate(1, $work); + print "Whoa! We can divide by zero?\n"; + }; if($@) { + warn 'InvalidOperation: '.Dumper($@); + } + + $work->op(tutorial::Operation::SUBTRACT); + $work->num1(15); + $work->num2(10); + my $diff = $client->calculate(1, $work); + print "15-10=$diff\n"; + + my $log = $client->getStruct(1); + print "Log: $log->{value}\n"; + + $transport->close(); + +}; if($@){ + warn(Dumper($@)); +} diff --git a/src/jaegertracing/thrift/tutorial/perl/PerlServer.pl b/src/jaegertracing/thrift/tutorial/perl/PerlServer.pl new file mode 100644 index 000000000..ee5d93674 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/perl/PerlServer.pl @@ -0,0 +1,125 @@ +#!/usr/bin/env perl + +# +# 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. +# + +use strict; +use lib '../gen-perl'; +use Thrift::Socket; +use Thrift::Server; +use Thrift::ServerSocket; +use tutorial::Calculator; + +package CalculatorHandler; +use base qw(tutorial::CalculatorIf); + +sub new { + my $classname = shift; + my $self = {}; + + return bless($self,$classname); +} + + +sub ping +{ + print "ping()\n"; +} + +sub add +{ + my($self, $n1, $n2) = @_; + printf("add(%d,%d)\n", $n1, $n2); + return $n1 + $n2; +} + +sub calculate +{ + my($self, $logid, $work) = @_; + my $op = $work->{op}; + my $num1 = $work->{num1}; + my $num2 = $work->{num2}; + printf("calculate(%d, %d %d %d)\n", $logid, $num1, $num2, $op); + + my $val; + + if ($op == tutorial::Operation::ADD) { + $val = $num1 + $num2; + } elsif ($op == tutorial::Operation::SUBTRACT) { + $val = $num1 - $num2; + } elsif ($op == tutorial::Operation::MULTIPLY) { + $val = $num1 * $num2; + } elsif ($op == tutorial::Operation::DIVIDE) { + if ($num2 == 0) + { + my $x = tutorial::InvalidOperation->new(); + $x->whatOp($op); + $x->why('Cannot divide by 0'); + die $x; + } + $val = $num1 / $num2; + } else { + my $x = tutorial::InvalidOperation->new(); + $x->whatOp($op); + $x->why('Invalid operation'); + die $x; + } + + my $log = shared::SharedStruct->new(); + $log->key($logid); + $log->value(int($val)); + $self->{log}->{$logid} = $log; + + return $val; +} + +sub getStruct +{ + my($self, $key) = @_; + printf("getStruct(%d)\n", $key); + return $self->{log}->{$key}; +} + +sub zip +{ + my($self) = @_; + print "zip()\n"; +} + + + +eval { + my $handler = CalculatorHandler->new(); + my $processor = tutorial::CalculatorProcessor->new($handler); + my $serversocket = Thrift::ServerSocket->new(9090); + my $forkingserver = Thrift::ForkingServer->new($processor, $serversocket); + print "Starting the server...\n"; + $forkingserver->serve(); + print "done.\n"; +}; if ($@) { + if ($@ =~ m/TException/ and exists $@->{message}) { + my $message = $@->{message}; + my $code = $@->{code}; + my $out = $code . ':' . $message; + die $out; + } else { + die $@; + } +} + diff --git a/src/jaegertracing/thrift/tutorial/php/PhpClient.php b/src/jaegertracing/thrift/tutorial/php/PhpClient.php new file mode 100755 index 000000000..eb2c2e5ee --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/php/PhpClient.php @@ -0,0 +1,91 @@ +#!/usr/bin/env php +<?php + +namespace tutorial\php; + +error_reporting(E_ALL); + +require_once __DIR__.'/../../vendor/autoload.php'; + +use Thrift\ClassLoader\ThriftClassLoader; + +$GEN_DIR = realpath(dirname(__FILE__).'/..').'/gen-php'; + +$loader = new ThriftClassLoader(); +$loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib'); +$loader->registerNamespace('shared', $GEN_DIR); +$loader->registerNamespace('tutorial', $GEN_DIR); +$loader->register(); + +/* + * 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. + */ + +use Thrift\Protocol\TBinaryProtocol; +use Thrift\Transport\TSocket; +use Thrift\Transport\THttpClient; +use Thrift\Transport\TBufferedTransport; +use Thrift\Exception\TException; + +try { + if (array_search('--http', $argv)) { + $socket = new THttpClient('localhost', 8080, '/php/PhpServer.php'); + } else { + $socket = new TSocket('localhost', 9090); + } + $transport = new TBufferedTransport($socket, 1024, 1024); + $protocol = new TBinaryProtocol($transport); + $client = new \tutorial\CalculatorClient($protocol); + + $transport->open(); + + $client->ping(); + print "ping()\n"; + + $sum = $client->add(1,1); + print "1+1=$sum\n"; + + $work = new \tutorial\Work(); + + $work->op = \tutorial\Operation::DIVIDE; + $work->num1 = 1; + $work->num2 = 0; + + try { + $client->calculate(1, $work); + print "Whoa! We can divide by zero?\n"; + } catch (\tutorial\InvalidOperation $io) { + print "InvalidOperation: $io->why\n"; + } + + $work->op = \tutorial\Operation::SUBTRACT; + $work->num1 = 15; + $work->num2 = 10; + $diff = $client->calculate(1, $work); + print "15-10=$diff\n"; + + $log = $client->getStruct(1); + print "Log: $log->value\n"; + + $transport->close(); + +} catch (TException $tx) { + print 'TException: '.$tx->getMessage()."\n"; +} + +?> diff --git a/src/jaegertracing/thrift/tutorial/php/PhpServer.php b/src/jaegertracing/thrift/tutorial/php/PhpServer.php new file mode 100755 index 000000000..749da3a0b --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/php/PhpServer.php @@ -0,0 +1,130 @@ +#!/usr/bin/env php +<?php + +namespace tutorial\php; + +error_reporting(E_ALL); + +require_once __DIR__.'/../../vendor/autoload.php'; + +use Thrift\ClassLoader\ThriftClassLoader; + +$GEN_DIR = realpath(dirname(__FILE__).'/..').'/gen-php'; + +$loader = new ThriftClassLoader(); +$loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib'); +$loader->registerNamespace('shared', $GEN_DIR); +$loader->registerNamespace('tutorial', $GEN_DIR); +$loader->register(); + +/* + * 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. + */ + +/* + * This is not a stand-alone server. It should be run as a normal + * php web script (like through Apache's mod_php) or as a cgi script + * (like with the included runserver.py). You can connect to it with + * THttpClient in any language that supports it. The PHP tutorial client + * will work if you pass it the argument "--http". + */ + +if (php_sapi_name() == 'cli') { + ini_set("display_errors", "stderr"); +} + +use Thrift\Protocol\TBinaryProtocol; +use Thrift\Transport\TPhpStream; +use Thrift\Transport\TBufferedTransport; + +class CalculatorHandler implements \tutorial\CalculatorIf { + protected $log = array(); + + public function ping() { + error_log("ping()"); + } + + public function add($num1, $num2) { + error_log("add({$num1}, {$num2})"); + return $num1 + $num2; + } + + public function calculate($logid, \tutorial\Work $w) { + error_log("calculate({$logid}, {{$w->op}, {$w->num1}, {$w->num2}})"); + switch ($w->op) { + case \tutorial\Operation::ADD: + $val = $w->num1 + $w->num2; + break; + case \tutorial\Operation::SUBTRACT: + $val = $w->num1 - $w->num2; + break; + case \tutorial\Operation::MULTIPLY: + $val = $w->num1 * $w->num2; + break; + case \tutorial\Operation::DIVIDE: + if ($w->num2 == 0) { + $io = new \tutorial\InvalidOperation(); + $io->whatOp = $w->op; + $io->why = "Cannot divide by 0"; + throw $io; + } + $val = $w->num1 / $w->num2; + break; + default: + $io = new \tutorial\InvalidOperation(); + $io->whatOp = $w->op; + $io->why = "Invalid Operation"; + throw $io; + } + + $log = new \shared\SharedStruct(); + $log->key = $logid; + $log->value = (string)$val; + $this->log[$logid] = $log; + + return $val; + } + + public function getStruct($key) { + error_log("getStruct({$key})"); + // This actually doesn't work because the PHP interpreter is + // restarted for every request. + //return $this->log[$key]; + return new \shared\SharedStruct(array("key" => $key, "value" => "PHP is stateless!")); + } + + public function zip() { + error_log("zip()"); + } + +}; + +header('Content-Type', 'application/x-thrift'); +if (php_sapi_name() == 'cli') { + echo "\r\n"; +} + +$handler = new CalculatorHandler(); +$processor = new \tutorial\CalculatorProcessor($handler); + +$transport = new TBufferedTransport(new TPhpStream(TPhpStream::MODE_R | TPhpStream::MODE_W)); +$protocol = new TBinaryProtocol($transport, true, true); + +$transport->open(); +$processor->process($protocol, $protocol); +$transport->close(); diff --git a/src/jaegertracing/thrift/tutorial/php/runserver.py b/src/jaegertracing/thrift/tutorial/php/runserver.py new file mode 100755 index 000000000..8cc30fbe5 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/php/runserver.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python + +# +# 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. +# + +import os +import BaseHTTPServer +import CGIHTTPServer + +# chdir(2) into the tutorial directory. +os.chdir(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) + + +class Handler(CGIHTTPServer.CGIHTTPRequestHandler): + cgi_directories = ['/php'] + + +BaseHTTPServer.HTTPServer(('', 8080), Handler).serve_forever() diff --git a/src/jaegertracing/thrift/tutorial/py.tornado/Makefile.am b/src/jaegertracing/thrift/tutorial/py.tornado/Makefile.am new file mode 100755 index 000000000..4b73c1e72 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py.tornado/Makefile.am @@ -0,0 +1,36 @@ +# +# 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. +# + +gen-py.tornado/tutorial/Calculator.py gen-py.tornado/shared/SharedService.py: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen py:tornado -r $< + +all-local: gen-py.tornado/tutorial/Calculator.py + +tutorialserver: all + ${PYTHON} PythonServer.py + +tutorialclient: all + ${PYTHON} PythonClient.py + +clean-local: + $(RM) -r gen-* + +EXTRA_DIST = \ + PythonServer.py \ + PythonClient.py diff --git a/src/jaegertracing/thrift/tutorial/py.tornado/PythonClient.py b/src/jaegertracing/thrift/tutorial/py.tornado/PythonClient.py new file mode 100755 index 000000000..426146fc9 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py.tornado/PythonClient.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python + +# +# 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. +# + +import glob +import logging +import sys + +sys.path.append('gen-py.tornado') +sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) + +from tutorial import Calculator +from tutorial.ttypes import Operation, Work, InvalidOperation + +from thrift import TTornado +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol + +from tornado import gen +from tornado import ioloop + + +@gen.coroutine +def communicate(): + # create client + transport = TTornado.TTornadoStreamTransport('localhost', 9090) + # open the transport, bail on error + try: + yield transport.open() + print('Transport is opened') + except TTransport.TTransportException as ex: + logging.error(ex) + raise gen.Return() + + pfactory = TBinaryProtocol.TBinaryProtocolFactory() + client = Calculator.Client(transport, pfactory) + + # ping + yield client.ping() + print("ping()") + + # add + sum_ = yield client.add(1, 1) + print("1 + 1 = {0}".format(sum_)) + + # make a oneway call without a callback (schedule the write and continue + # without blocking) + client.zip() + print("zip() without callback") + + # make a oneway call with a callback (we'll wait for the stream write to + # complete before continuing) + client.zip() + print("zip() with callback") + + # calculate 1/0 + work = Work() + work.op = Operation.DIVIDE + work.num1 = 1 + work.num2 = 0 + + try: + quotient = yield client.calculate(1, work) + print("Whoa? You know how to divide by zero ? -> {0}".format(quotient)) + except InvalidOperation as io: + print("InvalidOperation: {0}".format(io)) + + # calculate 15-10 + work.op = Operation.SUBTRACT + work.num1 = 15 + work.num2 = 10 + + diff = yield client.calculate(1, work) + print("15 - 10 = {0}".format(diff)) + + # getStruct + log = yield client.getStruct(1) + print("Check log: {0}".format(log.value)) + + # close the transport + client._transport.close() + raise gen.Return() + + +def main(): + # create an ioloop, do the above, then stop + ioloop.IOLoop.current().run_sync(communicate) + + +if __name__ == "__main__": + main() diff --git a/src/jaegertracing/thrift/tutorial/py.tornado/PythonServer.py b/src/jaegertracing/thrift/tutorial/py.tornado/PythonServer.py new file mode 100755 index 000000000..e0229a26e --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py.tornado/PythonServer.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python + +# +# 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. +# + +import glob +import sys + +sys.path.append('gen-py.tornado') +sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) + +from tutorial import Calculator +from tutorial.ttypes import Operation, InvalidOperation + +from shared.ttypes import SharedStruct + +from thrift import TTornado +from thrift.protocol import TBinaryProtocol + +from tornado import ioloop + + +class CalculatorHandler(object): + def __init__(self): + self.log = {} + + def ping(self): + print("ping()") + + def add(self, n1, n2): + print("add({}, {})".format(n1, n2)) + return n1 + n2 + + def calculate(self, logid, work): + print("calculate({}, {})".format(logid, work)) + + if work.op == Operation.ADD: + val = work.num1 + work.num2 + elif work.op == Operation.SUBTRACT: + val = work.num1 - work.num2 + elif work.op == Operation.MULTIPLY: + val = work.num1 * work.num2 + elif work.op == Operation.DIVIDE: + if work.num2 == 0: + x = InvalidOperation() + x.whatOp = work.op + x.why = "Cannot divide by 0" + raise x + val = work.num1 / work.num2 + else: + x = InvalidOperation() + x.whatOp = work.op + x.why = "Invalid operation" + raise x + + log = SharedStruct() + log.key = logid + log.value = '%d' % (val) + self.log[logid] = log + return val + + def getStruct(self, key): + print("getStruct({})".format(key)) + return self.log[key] + + def zip(self): + print("zip()") + + +def main(): + handler = CalculatorHandler() + processor = Calculator.Processor(handler) + pfactory = TBinaryProtocol.TBinaryProtocolFactory() + server = TTornado.TTornadoServer(processor, pfactory) + + print("Starting the server...") + server.bind(9090) + server.start(1) + ioloop.IOLoop.instance().start() + print("done.") + + +if __name__ == "__main__": + main() diff --git a/src/jaegertracing/thrift/tutorial/py.twisted/Makefile.am b/src/jaegertracing/thrift/tutorial/py.twisted/Makefile.am new file mode 100755 index 000000000..50cd3429d --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py.twisted/Makefile.am @@ -0,0 +1,37 @@ +# +# 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. +# + +gen-py/tutorial/Calculator.py gen-py/shared/SharedService.py: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen py:twisted -r $< + +all-local: gen-py/tutorial/Calculator.py + +tutorialserver: all + ${PYTHON} PythonServer.py + +tutorialclient: all + ${PYTHON} PythonClient.py + +clean-local: + $(RM) -r gen-* + +EXTRA_DIST = \ + PythonClient.py \ + PythonServer.py \ + PythonServer.tac diff --git a/src/jaegertracing/thrift/tutorial/py.twisted/PythonClient.py b/src/jaegertracing/thrift/tutorial/py.twisted/PythonClient.py new file mode 100755 index 000000000..2976495e3 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py.twisted/PythonClient.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python + +# +# 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. +# + +import glob +import sys +sys.path.append('gen-py.twisted') +sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) + +from tutorial import Calculator +from tutorial.ttypes import InvalidOperation, Operation, Work + +from twisted.internet.defer import inlineCallbacks +from twisted.internet import reactor +from twisted.internet.protocol import ClientCreator + +from thrift.transport import TTwisted +from thrift.protocol import TBinaryProtocol + + +@inlineCallbacks +def main(client): + yield client.ping() + print('ping()') + + sum = yield client.add(1, 1) + print(('1+1=%d' % (sum))) + + work = Work() + + work.op = Operation.DIVIDE + work.num1 = 1 + work.num2 = 0 + + try: + quotient = yield client.calculate(1, work) + print('Whoa? You know how to divide by zero?') + print('FYI the answer is %d' % quotient) + except InvalidOperation as e: + print(('InvalidOperation: %r' % e)) + + work.op = Operation.SUBTRACT + work.num1 = 15 + work.num2 = 10 + + diff = yield client.calculate(1, work) + print(('15-10=%d' % (diff))) + + log = yield client.getStruct(1) + print(('Check log: %s' % (log.value))) + reactor.stop() + + +if __name__ == '__main__': + d = ClientCreator(reactor, + TTwisted.ThriftClientProtocol, + Calculator.Client, + TBinaryProtocol.TBinaryProtocolFactory(), + ).connectTCP("127.0.0.1", 9090) + d.addCallback(lambda conn: conn.client) + d.addCallback(main) + + reactor.run() diff --git a/src/jaegertracing/thrift/tutorial/py.twisted/PythonServer.py b/src/jaegertracing/thrift/tutorial/py.twisted/PythonServer.py new file mode 100755 index 000000000..034e4a312 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py.twisted/PythonServer.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python + +# +# 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. +# + +import glob +import sys +sys.path.append('gen-py.twisted') +sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) + +from tutorial import Calculator +from tutorial.ttypes import InvalidOperation, Operation + +from shared.ttypes import SharedStruct + +from zope.interface import implements +from twisted.internet import reactor + +from thrift.transport import TTwisted +from thrift.protocol import TBinaryProtocol + + +class CalculatorHandler: + implements(Calculator.Iface) + + def __init__(self): + self.log = {} + + def ping(self): + print('ping()') + + def add(self, n1, n2): + print('add(%d,%d)' % (n1, n2)) + return n1 + n2 + + def calculate(self, logid, work): + print('calculate(%d, %r)' % (logid, work)) + + if work.op == Operation.ADD: + val = work.num1 + work.num2 + elif work.op == Operation.SUBTRACT: + val = work.num1 - work.num2 + elif work.op == Operation.MULTIPLY: + val = work.num1 * work.num2 + elif work.op == Operation.DIVIDE: + if work.num2 == 0: + x = InvalidOperation() + x.whatOp = work.op + x.why = 'Cannot divide by 0' + raise x + val = work.num1 / work.num2 + else: + x = InvalidOperation() + x.whatOp = work.op + x.why = 'Invalid operation' + raise x + + log = SharedStruct() + log.key = logid + log.value = '%d' % (val) + self.log[logid] = log + + return val + + def getStruct(self, key): + print('getStruct(%d)' % (key)) + return self.log[key] + + def zip(self): + print('zip()') + + +if __name__ == '__main__': + handler = CalculatorHandler() + processor = Calculator.Processor(handler) + pfactory = TBinaryProtocol.TBinaryProtocolFactory() + server = reactor.listenTCP( + 9090, + TTwisted.ThriftServerFactory(processor, pfactory), + interface="127.0.0.1") + reactor.run() diff --git a/src/jaegertracing/thrift/tutorial/py.twisted/PythonServer.tac b/src/jaegertracing/thrift/tutorial/py.twisted/PythonServer.tac new file mode 100755 index 000000000..0479636de --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py.twisted/PythonServer.tac @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +# +# 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. +# + +from twisted.application import internet, service +from thrift.transport import TTwisted + +import glob +import sys +sys.path.append('gen-py.twisted') +sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) +from tutorial import Calculator +from PythonServer import CalculatorHandler +from thrift.protocol import TBinaryProtocol + + +def make_application(): + application = service.Application('CalcServer') + + handler = CalculatorHandler() + processor = Calculator.Processor(handler) + + serverFactory = TTwisted.ThriftServerFactory( + processor, + TBinaryProtocol.TBinaryProtocolFactory()) + + calcService = internet.TCPServer(9090, serverFactory) + + multiService = service.MultiService() + calcService.setServiceParent(multiService) + multiService.setServiceParent(application) + + return application + +if __name__ == '__main__': + application = make_application() diff --git a/src/jaegertracing/thrift/tutorial/py/Makefile.am b/src/jaegertracing/thrift/tutorial/py/Makefile.am new file mode 100755 index 000000000..7db816d3b --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py/Makefile.am @@ -0,0 +1,37 @@ +# +# 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. +# + +gen-py/tutorial/Calculator.py gen-py/shared/SharedService.py: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen py -r $< + +all-local: gen-py/tutorial/Calculator.py + +tutorialserver: all + ${PYTHON} PythonServer.py + +tutorialclient: all + ${PYTHON} PythonClient.py + +clean-local: + $(RM) -r gen-* + +EXTRA_DIST = \ + setup.cfg \ + PythonServer.py \ + PythonClient.py diff --git a/src/jaegertracing/thrift/tutorial/py/PythonClient.py b/src/jaegertracing/thrift/tutorial/py/PythonClient.py new file mode 100755 index 000000000..a6c196641 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py/PythonClient.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +# +# 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. +# + +import sys +import glob +sys.path.append('gen-py') +sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) + +from tutorial import Calculator +from tutorial.ttypes import InvalidOperation, Operation, Work + +from thrift import Thrift +from thrift.transport import TSocket +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol + + +def main(): + # Make socket + transport = TSocket.TSocket('localhost', 9090) + + # Buffering is critical. Raw sockets are very slow + transport = TTransport.TBufferedTransport(transport) + + # Wrap in a protocol + protocol = TBinaryProtocol.TBinaryProtocol(transport) + + # Create a client to use the protocol encoder + client = Calculator.Client(protocol) + + # Connect! + transport.open() + + client.ping() + print('ping()') + + sum_ = client.add(1, 1) + print('1+1=%d' % sum_) + + work = Work() + + work.op = Operation.DIVIDE + work.num1 = 1 + work.num2 = 0 + + try: + quotient = client.calculate(1, work) + print('Whoa? You know how to divide by zero?') + print('FYI the answer is %d' % quotient) + except InvalidOperation as e: + print('InvalidOperation: %r' % e) + + work.op = Operation.SUBTRACT + work.num1 = 15 + work.num2 = 10 + + diff = client.calculate(1, work) + print('15-10=%d' % diff) + + log = client.getStruct(1) + print('Check log: %s' % log.value) + + # Close! + transport.close() + + +if __name__ == '__main__': + try: + main() + except Thrift.TException as tx: + print('%s' % tx.message) diff --git a/src/jaegertracing/thrift/tutorial/py/PythonServer.py b/src/jaegertracing/thrift/tutorial/py/PythonServer.py new file mode 100755 index 000000000..e6421ef08 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py/PythonServer.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +# +# 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. +# + +import glob +import sys +sys.path.append('gen-py') +sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) + +from tutorial import Calculator +from tutorial.ttypes import InvalidOperation, Operation + +from shared.ttypes import SharedStruct + +from thrift.transport import TSocket +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol +from thrift.server import TServer + + +class CalculatorHandler: + def __init__(self): + self.log = {} + + def ping(self): + print('ping()') + + def add(self, n1, n2): + print('add(%d,%d)' % (n1, n2)) + return n1 + n2 + + def calculate(self, logid, work): + print('calculate(%d, %r)' % (logid, work)) + + if work.op == Operation.ADD: + val = work.num1 + work.num2 + elif work.op == Operation.SUBTRACT: + val = work.num1 - work.num2 + elif work.op == Operation.MULTIPLY: + val = work.num1 * work.num2 + elif work.op == Operation.DIVIDE: + if work.num2 == 0: + x = InvalidOperation() + x.whatOp = work.op + x.why = 'Cannot divide by 0' + raise x + val = work.num1 / work.num2 + else: + x = InvalidOperation() + x.whatOp = work.op + x.why = 'Invalid operation' + raise x + + log = SharedStruct() + log.key = logid + log.value = '%d' % (val) + self.log[logid] = log + + return val + + def getStruct(self, key): + print('getStruct(%d)' % (key)) + return self.log[key] + + def zip(self): + print('zip()') + + +if __name__ == '__main__': + handler = CalculatorHandler() + processor = Calculator.Processor(handler) + transport = TSocket.TServerSocket(host='127.0.0.1', port=9090) + tfactory = TTransport.TBufferedTransportFactory() + pfactory = TBinaryProtocol.TBinaryProtocolFactory() + + server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) + + # You could do one of these for a multithreaded server + # server = TServer.TThreadedServer( + # processor, transport, tfactory, pfactory) + # server = TServer.TThreadPoolServer( + # processor, transport, tfactory, pfactory) + + print('Starting the server...') + server.serve() + print('done.') diff --git a/src/jaegertracing/thrift/tutorial/py/setup.cfg b/src/jaegertracing/thrift/tutorial/py/setup.cfg new file mode 100644 index 000000000..2a7120a29 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/py/setup.cfg @@ -0,0 +1,2 @@ +[flake8] +ignore = E402 diff --git a/src/jaegertracing/thrift/tutorial/rb/Makefile.am b/src/jaegertracing/thrift/tutorial/rb/Makefile.am new file mode 100755 index 000000000..885cd9231 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/rb/Makefile.am @@ -0,0 +1,36 @@ +# +# 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. +# + +gen-rb/calculator.rb gen-rb/shared_service.rb: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen rb -r $< + +all-local: gen-rb/calculator.rb + +tutorialserver: all + ${RUBY} RubyServer.rb + +tutorialclient: all + ${RUBY} RubyClient.rb + +clean-local: + $(RM) -r gen-* + +EXTRA_DIST = \ + RubyServer.rb \ + RubyClient.rb diff --git a/src/jaegertracing/thrift/tutorial/rb/RubyClient.rb b/src/jaegertracing/thrift/tutorial/rb/RubyClient.rb new file mode 100755 index 000000000..9a5aa432f --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/rb/RubyClient.rb @@ -0,0 +1,75 @@ +#!/usr/bin/env ruby + +# +# 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. +# + +$:.push('gen-rb') +$:.unshift '../../lib/rb/lib' + +require 'thrift' + +require 'calculator' + +begin + port = ARGV[0] || 9090 + + transport = Thrift::BufferedTransport.new(Thrift::Socket.new('localhost', port)) + protocol = Thrift::BinaryProtocol.new(transport) + client = Calculator::Client.new(protocol) + + transport.open() + + client.ping() + print "ping()\n" + + sum = client.add(1,1) + print "1+1=", sum, "\n" + + sum = client.add(1,4) + print "1+4=", sum, "\n" + + work = Work.new() + + work.op = Operation::SUBTRACT + work.num1 = 15 + work.num2 = 10 + diff = client.calculate(1, work) + print "15-10=", diff, "\n" + + log = client.getStruct(1) + print "Log: ", log.value, "\n" + + begin + work.op = Operation::DIVIDE + work.num1 = 1 + work.num2 = 0 + quot = client.calculate(1, work) + puts "Whoa, we can divide by 0 now?" + rescue InvalidOperation => io + print "InvalidOperation: ", io.why, "\n" + end + + client.zip() + print "zip\n" + + transport.close() + +rescue Thrift::Exception => tx + print 'Thrift::Exception: ', tx.message, "\n" +end diff --git a/src/jaegertracing/thrift/tutorial/rb/RubyServer.rb b/src/jaegertracing/thrift/tutorial/rb/RubyServer.rb new file mode 100755 index 000000000..1d707d740 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/rb/RubyServer.rb @@ -0,0 +1,95 @@ +#!/usr/bin/env ruby + +# +# 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. +# + +$:.push('gen-rb') +$:.unshift '../../lib/rb/lib' + +require 'thrift' + +require 'calculator' +require 'shared_types' + +class CalculatorHandler + def initialize() + @log = {} + end + + def ping() + puts "ping()" + end + + def add(n1, n2) + print "add(", n1, ",", n2, ")\n" + return n1 + n2 + end + + def calculate(logid, work) + print "calculate(", logid, ", {", work.op, ",", work.num1, ",", work.num2,"})\n" + if work.op == Operation::ADD + val = work.num1 + work.num2 + elsif work.op == Operation::SUBTRACT + val = work.num1 - work.num2 + elsif work.op == Operation::MULTIPLY + val = work.num1 * work.num2 + elsif work.op == Operation::DIVIDE + if work.num2 == 0 + x = InvalidOperation.new() + x.whatOp = work.op + x.why = "Cannot divide by 0" + raise x + end + val = work.num1 / work.num2 + else + x = InvalidOperation.new() + x.whatOp = work.op + x.why = "Invalid operation" + raise x + end + + entry = SharedStruct.new() + entry.key = logid + entry.value = "#{val}" + @log[logid] = entry + + return val + + end + + def getStruct(key) + print "getStruct(", key, ")\n" + return @log[key] + end + + def zip() + print "zip\n" + end + +end + +handler = CalculatorHandler.new() +processor = Calculator::Processor.new(handler) +transport = Thrift::ServerSocket.new(9090) +transportFactory = Thrift::BufferedTransportFactory.new() +server = Thrift::SimpleServer.new(processor, transport, transportFactory) + +puts "Starting the server..." +server.serve() +puts "done." diff --git a/src/jaegertracing/thrift/tutorial/rs/Cargo.toml b/src/jaegertracing/thrift/tutorial/rs/Cargo.toml new file mode 100644 index 000000000..60f02d73c --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/rs/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "thrift-tutorial" +version = "0.1.0" +license = "Apache-2.0" +authors = ["Apache Thrift Developers <dev@thrift.apache.org>"] +exclude = ["Makefile*", "shared.rs", "tutorial.rs"] +publish = false + +[dependencies] +clap = "2.33" +ordered-float = "1.0" +try_from = "0.3" + +[dependencies.thrift] +path = "../../lib/rs" + diff --git a/src/jaegertracing/thrift/tutorial/rs/Makefile.am b/src/jaegertracing/thrift/tutorial/rs/Makefile.am new file mode 100644 index 000000000..666331e4a --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/rs/Makefile.am @@ -0,0 +1,52 @@ +# +# 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. +# + +THRIFT = $(top_builddir)/compiler/cpp/thrift + +gen-rs/tutorial.rs gen-rs/shared.rs: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) -out src --gen rs -r $< + +all-local: gen-rs/tutorial.rs + $(CARGO) build + [ -d bin ] || mkdir bin + cp target/debug/tutorial_server bin/tutorial_server + cp target/debug/tutorial_client bin/tutorial_client + +check: all + +tutorialserver: all + bin/tutorial_server + +tutorialclient: all + bin/tutorial_client + +clean-local: + $(CARGO) clean + -$(RM) Cargo.lock + -$(RM) src/shared.rs + -$(RM) src/tutorial.rs + -$(RM) -r bin + +EXTRA_DIST = \ + Cargo.toml \ + src/lib.rs \ + src/bin/tutorial_server.rs \ + src/bin/tutorial_client.rs \ + README.md + diff --git a/src/jaegertracing/thrift/tutorial/rs/README.md b/src/jaegertracing/thrift/tutorial/rs/README.md new file mode 100644 index 000000000..166854bea --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/rs/README.md @@ -0,0 +1,318 @@ +# Rust Language Bindings for Thrift + +## Getting Started + +1. Get the [Thrift compiler](https://thrift.apache.org). + +2. Add the following crates to your `Cargo.toml`. + +```toml +thrift = "x.y.z" # x.y.z is the version of the thrift compiler +ordered-float = "0.3.0" +try_from = "0.2.0" +``` + +3. Add the same crates to your `lib.rs` or `main.rs`. + +```rust +extern crate ordered_float; +extern crate thrift; +extern crate try_from; +``` + +4. Generate Rust sources for your IDL (for example, `Tutorial.thrift`). + +```shell +thrift -out my_rust_program/src --gen rs -r Tutorial.thrift +``` + +5. Use the generated source in your code. + +```rust +// add extern crates here, or in your lib.rs +extern crate ordered_float; +extern crate thrift; +extern crate try_from; + +// generated Rust module +mod tutorial; + +use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol}; +use thrift::protocol::{TInputProtocol, TOutputProtocol}; +use thrift::transport::{TFramedReadTransport, TFramedWriteTransport}; +use thrift::transport::{TIoChannel, TTcpChannel}; + +use tutorial::{CalculatorSyncClient, TCalculatorSyncClient}; +use tutorial::{Operation, Work}; + +fn main() { + match run() { + Ok(()) => println!("client ran successfully"), + Err(e) => { + println!("client failed with {:?}", e); + std::process::exit(1); + } + } +} + +fn run() -> thrift::Result<()> { + // + // build client + // + + println!("connect to server on 127.0.0.1:9090"); + let mut c = TTcpChannel::new(); + c.open("127.0.0.1:9090")?; + + let (i_chan, o_chan) = c.split()?; + + let i_prot = TCompactInputProtocol::new( + TFramedReadTransport::new(i_chan) + ); + let o_prot = TCompactOutputProtocol::new( + TFramedWriteTransport::new(o_chan) + ); + + let mut client = CalculatorSyncClient::new(i_prot, o_prot); + + // + // alright! - let's make some calls + // + + // two-way, void return + client.ping()?; + + // two-way with some return + let res = client.calculate( + 72, + Work::new(7, 8, Operation::Multiply, None) + )?; + println!("multiplied 7 and 8, got {}", res); + + // two-way and returns a Thrift-defined exception + let res = client.calculate( + 77, + Work::new(2, 0, Operation::Divide, None) + ); + match res { + Ok(v) => panic!("shouldn't have succeeded with result {}", v), + Err(e) => println!("divide by zero failed with {:?}", e), + } + + // one-way + client.zip()?; + + // done! + Ok(()) +} +``` + +## Code Generation + +### Thrift Files and Generated Modules + +The Thrift code generator takes each Thrift file and generates a Rust module +with the same name snake-cased. For example, running the compiler on +`ThriftTest.thrift` creates `thrift_test.rs`. To use these generated files add +`mod ...` and `use ...` declarations to your `lib.rs` or `main.rs` - one for +each generated file. + +### Results and Errors + +The Thrift runtime library defines a `thrift::Result` and a `thrift::Error` type, +both of which are used throught the runtime library and in all generated code. +Conversions are defined from `std::io::Error`, `str` and `String` into +`thrift::Error`. + +### Thrift Type and their Rust Equivalents + +Thrift defines a number of types, each of which is translated into its Rust +equivalent by the code generator. + +* Primitives (bool, i8, i16, i32, i64, double, string, binary) +* Typedefs +* Enums +* Containers +* Structs +* Unions +* Exceptions +* Services +* Constants (primitives, containers, structs) + +In addition, unless otherwise noted, thrift includes are translated into +`use ...` statements in the generated code, and all declarations, parameters, +traits and types in the generated code are namespaced appropriately. + +The following subsections cover each type and their generated Rust equivalent. + +### Primitives + +Thrift primitives have straightforward Rust equivalents. + +* bool: `bool` +* i8: `i8` +* i16: `i16` +* i32: `i32` +* i64: `i64` +* double: `OrderedFloat<f64>` +* string: `String` +* binary: `Vec<u8>` + +### Typedefs + +A typedef is translated to a `pub type` declaration. + +```thrift +typedef i64 UserId + +typedef map<string, UserId> MapType +``` +```rust +pub type UserId = i64; + +pub type MapType = BTreeMap<String, Bonk>; +``` + +### Enums + +A Thrift enum is represented as a Rust enum, and each variant is transcribed 1:1. + +```thrift +enum Numberz +{ + ONE = 1, + TWO, + THREE, + FIVE = 5, + SIX, + EIGHT = 8 +} +``` + +```rust +#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub enum Numberz { + ONE = 1, + TWO = 2, + THREE = 3, + FIVE = 5, + SIX = 6, + EIGHT = 8, +} + +impl TryFrom<i32> for Numberz { + // ... +} + +``` + +### Containers + +Thrift has three container types: list, set and map. They are translated into +Rust `Vec`, `BTreeSet` and `BTreeMap` respectively. Any Thrift type (this +includes structs, enums and typedefs) can be a list/set element or a map +key/value. + +#### List + +```thrift +list <i32> numbers +``` + +```rust +numbers: Vec<i32> +``` + +#### Set + +```thrift +set <i32> numbers +``` + +```rust +numbers: BTreeSet<i32> +``` + +#### Map + +```thrift +map <string, i32> numbers +``` + +```rust +numbers: BTreeMap<String, i32> +``` + +### Structs + +A Thrift struct is represented as a Rust struct, and each field transcribed 1:1. + +```thrift +struct CrazyNesting { + 1: string string_field, + 2: optional set<Insanity> set_field, + 3: required list< + map<set<i32>, map<i32,set<list<map<Insanity,string>>>>> + > + 4: binary binary_field +} +``` +```rust +#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct CrazyNesting { + pub string_field: Option<String>, + pub set_field: Option<BTreeSet<Insanity>>, + pub list_field: Vec< + BTreeMap< + BTreeSet<i32>, + BTreeMap<i32, BTreeSet<Vec<BTreeMap<Insanity, String>>>> + > + >, + pub binary_field: Option<Vec<u8>>, +} + +impl CrazyNesting { + pub fn read_from_in_protocol(i_prot: &mut TInputProtocol) + -> + thrift::Result<CrazyNesting> { + // ... + } + pub fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) + -> + thrift::Result<()> { + // ... + } +} + +``` +##### Optionality + +Thrift has 3 "optionality" types: + +1. Required +2. Optional +3. Default + +The Rust code generator encodes *Required* fields as the bare type itself, while +*Optional* and *Default* fields are encoded as `Option<TypeName>`. + +```thrift +struct Foo { + 1: required string bar // 1. required + 2: optional string baz // 2. optional + 3: string qux // 3. default +} +``` + +```rust +pub struct Foo { + bar: String, // 1. required + baz: Option<String>, // 2. optional + qux: Option<String>, // 3. default +} +``` + +## Known Issues + +* Struct constants are not supported +* Map, list and set constants require a const holder struct diff --git a/src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_client.rs b/src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_client.rs new file mode 100644 index 000000000..bfd81d4c3 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_client.rs @@ -0,0 +1,130 @@ +// 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. + +#[macro_use] +extern crate clap; + +extern crate thrift; +extern crate thrift_tutorial; + +use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol}; +use thrift::transport::{ + ReadHalf, TFramedReadTransport, TFramedWriteTransport, TIoChannel, TTcpChannel, WriteHalf, +}; + +use thrift_tutorial::shared::TSharedServiceSyncClient; +use thrift_tutorial::tutorial::{CalculatorSyncClient, Operation, TCalculatorSyncClient, Work}; + +fn main() { + match run() { + Ok(()) => println!("tutorial client ran successfully"), + Err(e) => { + println!("tutorial client failed with error {:?}", e); + std::process::exit(1); + } + } +} + +fn run() -> thrift::Result<()> { + let options = clap_app!(rust_tutorial_client => + (version: "0.1.0") + (author: "Apache Thrift Developers <dev@thrift.apache.org>") + (about: "Thrift Rust tutorial client") + (@arg host: --host +takes_value "host on which the tutorial server listens") + (@arg port: --port +takes_value "port on which the tutorial server listens") + ); + let matches = options.get_matches(); + + // get any passed-in args or the defaults + let host = matches.value_of("host").unwrap_or("127.0.0.1"); + let port = value_t!(matches, "port", u16).unwrap_or(9090); + + // build our client and connect to the host:port + let mut client = new_client(host, port)?; + + // alright! + // let's start making some calls + + // let's start with a ping; the server should respond + println!("ping!"); + client.ping()?; + + // simple add + println!("add"); + let res = client.add(1, 2)?; + println!("added 1, 2 and got {}", res); + + let logid = 32; + + // let's do...a multiply! + let res = client.calculate(logid, Work::new(7, 8, Operation::Multiply, None))?; + println!("multiplied 7 and 8 and got {}", res); + + // let's get the log for it + let res = client.get_struct(logid /* 32 */)?; + println!("got log {:?} for operation {}", res, logid); + + // ok - let's be bad :( + // do a divide by 0 + // logid doesn't matter; won't be recorded + let res = client.calculate(77, Work::new(2, 0, Operation::Divide, "we bad".to_owned())); + + // we should have gotten an exception back + match res { + Ok(v) => panic!("should not have succeeded with result {}", v), + Err(e) => println!("divide by zero failed with error {:?}", e), + } + + // let's do a one-way call + println!("zip"); + client.zip()?; + + // and then close out with a final ping + println!("ping!"); + client.ping()?; + + Ok(()) +} + +type ClientInputProtocol = TCompactInputProtocol<TFramedReadTransport<ReadHalf<TTcpChannel>>>; +type ClientOutputProtocol = TCompactOutputProtocol<TFramedWriteTransport<WriteHalf<TTcpChannel>>>; + +fn new_client( + host: &str, + port: u16, +) -> thrift::Result<CalculatorSyncClient<ClientInputProtocol, ClientOutputProtocol>> { + let mut c = TTcpChannel::new(); + + // open the underlying TCP stream + println!("connecting to tutorial server on {}:{}", host, port); + c.open(&format!("{}:{}", host, port))?; + + // clone the TCP channel into two halves, one which + // we'll use for reading, the other for writing + let (i_chan, o_chan) = c.split()?; + + // wrap the raw sockets (slow) with a buffered transport of some kind + let i_tran = TFramedReadTransport::new(i_chan); + let o_tran = TFramedWriteTransport::new(o_chan); + + // now create the protocol implementations + let i_prot = TCompactInputProtocol::new(i_tran); + let o_prot = TCompactOutputProtocol::new(o_tran); + + // we're done! + Ok(CalculatorSyncClient::new(i_prot, o_prot)) +} diff --git a/src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_server.rs b/src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_server.rs new file mode 100644 index 000000000..95b1a2b6e --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/rs/src/bin/tutorial_server.rs @@ -0,0 +1,179 @@ +// 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. + +#[macro_use] +extern crate clap; + +extern crate thrift; +extern crate thrift_tutorial; + +use std::collections::HashMap; +use std::convert::{From, Into}; +use std::default::Default; +use std::sync::Mutex; + +use thrift::protocol::{TCompactInputProtocolFactory, TCompactOutputProtocolFactory}; +use thrift::server::TServer; + +use thrift::transport::{TFramedReadTransportFactory, TFramedWriteTransportFactory}; +use thrift_tutorial::shared::{SharedServiceSyncHandler, SharedStruct}; +use thrift_tutorial::tutorial::{CalculatorSyncHandler, CalculatorSyncProcessor}; +use thrift_tutorial::tutorial::{InvalidOperation, Operation, Work}; + +fn main() { + match run() { + Ok(()) => println!("tutorial server ran successfully"), + Err(e) => { + println!("tutorial server failed with error {:?}", e); + std::process::exit(1); + } + } +} + +fn run() -> thrift::Result<()> { + let options = clap_app!(rust_tutorial_server => + (version: "0.1.0") + (author: "Apache Thrift Developers <dev@thrift.apache.org>") + (about: "Thrift Rust tutorial server") + (@arg port: --port +takes_value "port on which the tutorial server listens") + ); + let matches = options.get_matches(); + + let port = value_t!(matches, "port", u16).unwrap_or(9090); + let listen_address = format!("127.0.0.1:{}", port); + + println!("binding to {}", listen_address); + + let i_tran_fact = TFramedReadTransportFactory::new(); + let i_prot_fact = TCompactInputProtocolFactory::new(); + + let o_tran_fact = TFramedWriteTransportFactory::new(); + let o_prot_fact = TCompactOutputProtocolFactory::new(); + + // demux incoming messages + let processor = CalculatorSyncProcessor::new(CalculatorServer { + ..Default::default() + }); + + // create the server and start listening + let mut server = TServer::new( + i_tran_fact, + i_prot_fact, + o_tran_fact, + o_prot_fact, + processor, + 10, + ); + + server.listen(&listen_address) +} + +/// Handles incoming Calculator service calls. +struct CalculatorServer { + log: Mutex<HashMap<i32, SharedStruct>>, +} + +impl Default for CalculatorServer { + fn default() -> CalculatorServer { + CalculatorServer { + log: Mutex::new(HashMap::new()), + } + } +} + +// since Calculator extends SharedService we have to implement the +// handler for both traits. +// + +// SharedService handler +impl SharedServiceSyncHandler for CalculatorServer { + fn handle_get_struct(&self, key: i32) -> thrift::Result<SharedStruct> { + let log = self.log.lock().unwrap(); + log.get(&key) + .cloned() + .ok_or_else(|| format!("could not find log for key {}", key).into()) + } +} + +// Calculator handler +impl CalculatorSyncHandler for CalculatorServer { + fn handle_ping(&self) -> thrift::Result<()> { + println!("pong!"); + Ok(()) + } + + fn handle_add(&self, num1: i32, num2: i32) -> thrift::Result<i32> { + println!("handling add: n1:{} n2:{}", num1, num2); + Ok(num1 + num2) + } + + fn handle_calculate(&self, logid: i32, w: Work) -> thrift::Result<i32> { + println!("handling calculate: l:{}, w:{:?}", logid, w); + + let res = if let Some(ref op) = w.op { + if w.num1.is_none() || w.num2.is_none() { + Err(InvalidOperation { + what_op: Some(*op as i32), + why: Some("no operands specified".to_owned()), + }) + } else { + // so that I don't have to call unwrap() multiple times below + let num1 = w.num1.as_ref().expect("operands checked"); + let num2 = w.num2.as_ref().expect("operands checked"); + + match *op { + Operation::Add => Ok(num1 + num2), + Operation::Subtract => Ok(num1 - num2), + Operation::Multiply => Ok(num1 * num2), + Operation::Divide => { + if *num2 == 0 { + Err(InvalidOperation { + what_op: Some(*op as i32), + why: Some("divide by 0".to_owned()), + }) + } else { + Ok(num1 / num2) + } + } + } + } + } else { + Err(InvalidOperation::new( + None, + "no operation specified".to_owned(), + )) + }; + + // if the operation was successful log it + if let Ok(ref v) = res { + let mut log = self.log.lock().unwrap(); + log.insert(logid, SharedStruct::new(logid, format!("{}", v))); + } + + // the try! macro automatically maps errors + // but, since we aren't using that here we have to map errors manually + // + // exception structs defined in the IDL have an auto-generated + // impl of From::from + res.map_err(From::from) + } + + fn handle_zip(&self) -> thrift::Result<()> { + println!("handling zip"); + Ok(()) + } +} diff --git a/src/jaegertracing/thrift/tutorial/rs/src/lib.rs b/src/jaegertracing/thrift/tutorial/rs/src/lib.rs new file mode 100644 index 000000000..40007e5d3 --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/rs/src/lib.rs @@ -0,0 +1,23 @@ +// 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. + +extern crate ordered_float; +extern crate thrift; +extern crate try_from; + +pub mod shared; +pub mod tutorial; diff --git a/src/jaegertracing/thrift/tutorial/shared.thrift b/src/jaegertracing/thrift/tutorial/shared.thrift new file mode 100644 index 000000000..5747f06bf --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/shared.thrift @@ -0,0 +1,44 @@ +/* + * 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. + */ + +/** + * This Thrift file can be included by other Thrift files that want to share + * these definitions. + */ + +namespace cl shared +namespace cpp shared +namespace d share // "shared" would collide with the eponymous D keyword. +namespace dart shared +namespace java shared +namespace perl shared +namespace php shared +namespace haxe shared +namespace netcore shared +namespace netstd shared + + +struct SharedStruct { + 1: i32 key + 2: string value +} + +service SharedService { + SharedStruct getStruct(1: i32 key) +} diff --git a/src/jaegertracing/thrift/tutorial/tutorial.thrift b/src/jaegertracing/thrift/tutorial/tutorial.thrift new file mode 100644 index 000000000..ea18b73dd --- /dev/null +++ b/src/jaegertracing/thrift/tutorial/tutorial.thrift @@ -0,0 +1,158 @@ +/* + * 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. + */ + +# Thrift Tutorial +# Mark Slee (mcslee@facebook.com) +# +# This file aims to teach you how to use Thrift, in a .thrift file. Neato. The +# first thing to notice is that .thrift files support standard shell comments. +# This lets you make your thrift file executable and include your Thrift build +# step on the top line. And you can place comments like this anywhere you like. +# +# Before running this file, you will need to have installed the thrift compiler +# into /usr/local/bin. + +/** + * The first thing to know about are types. The available types in Thrift are: + * + * bool Boolean, one byte + * i8 (byte) Signed 8-bit integer + * i16 Signed 16-bit integer + * i32 Signed 32-bit integer + * i64 Signed 64-bit integer + * double 64-bit floating point value + * string String + * binary Blob (byte array) + * map<t1,t2> Map from one type to another + * list<t1> Ordered list of one type + * set<t1> Set of unique elements of one type + * + * Did you also notice that Thrift supports C style comments? + */ + +// Just in case you were wondering... yes. We support simple C comments too. + +/** + * Thrift files can reference other Thrift files to include common struct + * and service definitions. These are found using the current path, or by + * searching relative to any paths specified with the -I compiler flag. + * + * Included objects are accessed using the name of the .thrift file as a + * prefix. i.e. shared.SharedObject + */ +include "shared.thrift" + +/** + * Thrift files can namespace, package, or prefix their output in various + * target languages. + */ + +namespace cl tutorial +namespace cpp tutorial +namespace d tutorial +namespace dart tutorial +namespace java tutorial +namespace php tutorial +namespace perl tutorial +namespace haxe tutorial +namespace netcore tutorial +namespace netstd tutorial + +/** + * Thrift lets you do typedefs to get pretty names for your types. Standard + * C style here. + */ +typedef i32 MyInteger + +/** + * Thrift also lets you define constants for use across languages. Complex + * types and structs are specified using JSON notation. + */ +const i32 INT32CONSTANT = 9853 +const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'} + +/** + * You can define enums, which are just 32 bit integers. Values are optional + * and start at 1 if not supplied, C style again. + */ +enum Operation { + ADD = 1, + SUBTRACT = 2, + MULTIPLY = 3, + DIVIDE = 4 +} + +/** + * Structs are the basic complex data structures. They are comprised of fields + * which each have an integer identifier, a type, a symbolic name, and an + * optional default value. + * + * Fields can be declared "optional", which ensures they will not be included + * in the serialized output if they aren't set. Note that this requires some + * manual management in some languages. + */ +struct Work { + 1: i32 num1 = 0, + 2: i32 num2, + 3: Operation op, + 4: optional string comment, +} + +/** + * Structs can also be exceptions, if they are nasty. + */ +exception InvalidOperation { + 1: i32 whatOp, + 2: string why +} + +/** + * Ahh, now onto the cool part, defining a service. Services just need a name + * and can optionally inherit from another service using the extends keyword. + */ +service Calculator extends shared.SharedService { + + /** + * A method definition looks like C code. It has a return type, arguments, + * and optionally a list of exceptions that it may throw. Note that argument + * lists and exception lists are specified using the exact same syntax as + * field lists in struct or exception definitions. + */ + + void ping(), + + i32 add(1:i32 num1, 2:i32 num2), + + i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), + + /** + * This method has a oneway modifier. That means the client only makes + * a request and does not listen for any response at all. Oneway methods + * must be void. + */ + oneway void zip() + +} + +/** + * That just about covers the basics. Take a look in the test/ folder for more + * detailed examples. After you run this file, your generated code shows up + * in folders with names gen-<language>. The generated code isn't too scary + * to look at. It even has pretty indentation. + */ |