You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by je...@apache.org on 2014/03/24 20:44:22 UTC

git commit: THRIFT-2425 PHP: Server-side support for Multiplexing Services

Repository: thrift
Updated Branches:
  refs/heads/master 932cad8dc -> e8ca73f62


THRIFT-2425 PHP: Server-side support for Multiplexing Services

Patch: Aldo Armiento


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/e8ca73f6
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/e8ca73f6
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/e8ca73f6

Branch: refs/heads/master
Commit: e8ca73f62f97fe1cf05425727a9831d14316e4d4
Parents: 932cad8
Author: Jens Geyer <je...@apache.org>
Authored: Mon Mar 24 21:41:12 2014 +0200
Committer: Jens Geyer <je...@apache.org>
Committed: Mon Mar 24 21:41:12 2014 +0200

----------------------------------------------------------------------
 lib/php/lib/Thrift/TMultiplexedProcessor.php | 135 ++++++++++++++++++++++
 1 file changed, 135 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/e8ca73f6/lib/php/lib/Thrift/TMultiplexedProcessor.php
----------------------------------------------------------------------
diff --git a/lib/php/lib/Thrift/TMultiplexedProcessor.php b/lib/php/lib/Thrift/TMultiplexedProcessor.php
new file mode 100644
index 0000000..9146ab6
--- /dev/null
+++ b/lib/php/lib/Thrift/TMultiplexedProcessor.php
@@ -0,0 +1,135 @@
+<?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.processor
+ */
+
+namespace Thrift;
+
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TMultiplexedProtocol;
+use Thrift\Protocol\TProtocolDecorator;
+use Thrift\Type\TMessageType;
+
+/**
+ * <code>TMultiplexedProcessor</code> is a Processor allowing
+ * a single <code>TServer</code> to provide multiple services.
+ *
+ * <p>To do so, you instantiate the processor and then register additional
+ * processors with it, as shown in the following example:</p>
+ *
+ * <blockquote><code>
+ *     $processor = new TMultiplexedProcessor();
+ *
+ *     processor->registerProcessor(
+ *         "Calculator",
+ *         new \tutorial\CalculatorProcessor(new CalculatorHandler()));
+ *
+ *     processor->registerProcessor(
+ *         "WeatherReport",
+ *         new \tutorial\WeatherReportProcessor(new WeatherReportHandler()));
+ *
+ *     $processor->process($protocol, $protocol);
+ * </code></blockquote>
+ */
+
+class TMultiplexedProcessor {
+    private $serviceProcessorMap_;
+
+    /**
+     * 'Register' a service with this <code>TMultiplexedProcessor</code>.  This
+     * allows us to broker requests to individual services by using the service
+     * name to select them at request time.
+     *
+     * @param serviceName Name of a service, has to be identical to the name
+     * declared in the Thrift IDL, e.g. "WeatherReport".
+     * @param processor Implementation of a service, ususally referred to
+     * as "handlers", e.g. WeatherReportHandler implementing WeatherReport.Iface.
+     */
+    public function registerProcessor($serviceName, $processor) {
+        $this->serviceProcessorMap_[$serviceName] = $processor;
+    }
+
+    /**
+     * This implementation of <code>process</code> performs the following steps:
+     *
+     * <ol>
+     *     <li>Read the beginning of the message.</li>
+     *     <li>Extract the service name from the message.</li>
+     *     <li>Using the service name to locate the appropriate processor.</li>
+     *     <li>Dispatch to the processor, with a decorated instance of TProtocol
+     *         that allows readMessageBegin() to return the original Message.</li>
+     * </ol>
+     *
+     * @throws TException If the message type is not CALL or ONEWAY, if
+     * the service name was not found in the message, or if the service
+     * name was not found in the service map.
+     */
+    public function process(TProtocol $input, TProtocol $output) {
+        /*
+            Use the actual underlying protocol (e.g. TBinaryProtocol) to read the
+            message header. This pulls the message "off the wire", which we'll
+            deal with at the end of this method.
+        */
+        $input->readMessageBegin($fname, $mtype, $rseqid);
+
+        if ($mtype !== TMessageType::CALL && $mtype != TMessageType::ONEWAY) {
+            throw new TException("This should not have happened!?");
+        }
+
+        // Extract the service name and the new Message name.
+        if (strpos($fname, TMultiplexedProtocol::SEPARATOR) === false) {
+            throw new TException("Service name not found in message name: {$fname}. Did you " .
+                "forget to use a TMultiplexProtocol in your client?");
+        }
+        list($serviceName, $messageName) = explode(':', $fname, 2);
+        if (!array_key_exists($serviceName, $this->serviceProcessorMap_)) {
+            throw new TException("Service name not found: {$serviceName}.  Did you forget " .
+                "to call registerProcessor()?");
+        }
+
+        // Dispatch processing to the stored processor
+        $processor = $this->serviceProcessorMap_[$serviceName];
+        return $processor->process(
+            new StoredMessageProtocol($input, $messageName, $mtype, $rseqid), $output
+        );
+    }
+}
+
+/**
+ *  Our goal was to work with any protocol. In order to do that, we needed
+ *  to allow them to call readMessageBegin() and get the Message in exactly
+ *  the standard format, without the service name prepended to the Message name.
+ */
+class StoredMessageProtocol extends TProtocolDecorator {
+    private $fname_, $mtype_, $rseqid_;
+
+    public function __construct(TProtocol $protocol, $fname, $mtype, $rseqid) {
+        parent::__construct($protocol);
+        $this->fname_  = $fname;
+        $this->mtype_  = $mtype;
+        $this->rseqid_ = $rseqid;
+    }
+
+    public function readMessageBegin(&$name, &$type, &$seqid) {
+        $name  = $this->fname_;
+        $type  = $this->mtype_;
+        $seqid = $this->rseqid_;
+    }
+}