Browse Source

Automatic Commit By liuyuqi

liuyuqi-dellpc 5 years ago
commit
e6291d488c
100 changed files with 24582 additions and 0 deletions
  1. 38 0
      .idea/$CACHE_FILE$
  2. 76 0
      .idea/$PRODUCT_WORKSPACE_FILE$
  3. 2 0
      .idea/.gitignore
  4. 6 0
      .idea/dictionaries
  5. 6 0
      .idea/encodings.xml
  6. 5 0
      .idea/inspectionProfiles/profiles_settings.xml
  7. 9 0
      .idea/misc.xml
  8. 8 0
      .idea/modules.xml
  9. 9 0
      .idea/opensearch-tutorial.iml
  10. 6 0
      .idea/vcs.xml
  11. 2 0
      README.md
  12. 57 0
      docs/安装使用.md
  13. 0 0
      java/.gitkeep
  14. 1 0
      php/.gitignore
  15. 31 0
      php/OpenSearch/Autoloader/Autoloader.php
  16. 123 0
      php/OpenSearch/Client/AppClient.php
  17. 152 0
      php/OpenSearch/Client/BehaviorCollectionClient.php
  18. 151 0
      php/OpenSearch/Client/DocumentClient.php
  19. 314 0
      php/OpenSearch/Client/OpenSearchClient.php
  20. 67 0
      php/OpenSearch/Client/SearchClient.php
  21. 67 0
      php/OpenSearch/Client/SuggestClient.php
  22. 1861 0
      php/OpenSearch/Generated/App/AppService.php
  23. 1680 0
      php/OpenSearch/Generated/App/Types.php
  24. 356 0
      php/OpenSearch/Generated/BehaviorCollection/BehaviorCollectionService.php
  25. 39 0
      php/OpenSearch/Generated/BehaviorCollection/Types.php
  26. 588 0
      php/OpenSearch/Generated/Common/Types.php
  27. 411 0
      php/OpenSearch/Generated/Document/DocumentService.php
  28. 44 0
      php/OpenSearch/Generated/Document/Types.php
  29. 2551 0
      php/OpenSearch/Generated/FirstRank/FirstRankService.php
  30. 364 0
      php/OpenSearch/Generated/FirstRank/Types.php
  31. 67 0
      php/OpenSearch/Generated/GeneralSearcher/GeneralSearcherService.php
  32. 95 0
      php/OpenSearch/Generated/GeneralSearcher/Types.php
  33. 440 0
      php/OpenSearch/Generated/OpenSearch/OpenSearchService.php
  34. 275 0
      php/OpenSearch/Generated/OpenSearch/Types.php
  35. 356 0
      php/OpenSearch/Generated/Search/OpenSearchSearcherService.php
  36. 2637 0
      php/OpenSearch/Generated/Search/Types.php
  37. 1910 0
      php/OpenSearch/Generated/SecondRank/SecondRankService.php
  38. 146 0
      php/OpenSearch/Generated/SecondRank/Types.php
  39. 409 0
      php/OpenSearch/Generated/Summary/SummaryService.php
  40. 261 0
      php/OpenSearch/Generated/Summary/Types.php
  41. 380 0
      php/OpenSearch/Thrift/Base/TBase.php
  42. 210 0
      php/OpenSearch/Thrift/ClassLoader/ThriftClassLoader.php
  43. 76 0
      php/OpenSearch/Thrift/Exception/TApplicationException.php
  44. 383 0
      php/OpenSearch/Thrift/Exception/TException.php
  45. 50 0
      php/OpenSearch/Thrift/Exception/TProtocolException.php
  46. 40 0
      php/OpenSearch/Thrift/Exception/TTransportException.php
  47. 45 0
      php/OpenSearch/Thrift/Factory/TBinaryProtocolFactory.php
  48. 40 0
      php/OpenSearch/Thrift/Factory/TCompactProtocolFactory.php
  49. 40 0
      php/OpenSearch/Thrift/Factory/TJSONProtocolFactory.php
  50. 36 0
      php/OpenSearch/Thrift/Factory/TProtocolFactory.php
  51. 66 0
      php/OpenSearch/Thrift/Factory/TStringFuncFactory.php
  52. 18 0
      php/OpenSearch/Thrift/Factory/TTransportFactory.php
  53. 39 0
      php/OpenSearch/Thrift/Protocol/JSON/BaseContext.php
  54. 54 0
      php/OpenSearch/Thrift/Protocol/JSON/ListContext.php
  55. 57 0
      php/OpenSearch/Thrift/Protocol/JSON/LookaheadReader.php
  56. 64 0
      php/OpenSearch/Thrift/Protocol/JSON/PairContext.php
  57. 33 0
      php/OpenSearch/Thrift/Protocol/SimpleJSON/CollectionMapKeyException.php
  58. 36 0
      php/OpenSearch/Thrift/Protocol/SimpleJSON/Context.php
  59. 45 0
      php/OpenSearch/Thrift/Protocol/SimpleJSON/ListContext.php
  60. 51 0
      php/OpenSearch/Thrift/Protocol/SimpleJSON/MapContext.php
  61. 53 0
      php/OpenSearch/Thrift/Protocol/SimpleJSON/StructContext.php
  62. 453 0
      php/OpenSearch/Thrift/Protocol/TBinaryProtocol.php
  63. 65 0
      php/OpenSearch/Thrift/Protocol/TBinaryProtocolAccelerated.php
  64. 739 0
      php/OpenSearch/Thrift/Protocol/TCompactProtocol.php
  65. 807 0
      php/OpenSearch/Thrift/Protocol/TJSONProtocol.php
  66. 85 0
      php/OpenSearch/Thrift/Protocol/TMultiplexedProtocol.php
  67. 352 0
      php/OpenSearch/Thrift/Protocol/TProtocol.php
  68. 284 0
      php/OpenSearch/Thrift/Protocol/TProtocolDecorator.php
  69. 371 0
      php/OpenSearch/Thrift/Protocol/TSimpleJSONProtocol.php
  70. 85 0
      php/OpenSearch/Thrift/Serializer/TBinarySerializer.php
  71. 120 0
      php/OpenSearch/Thrift/Server/TForkingServer.php
  72. 94 0
      php/OpenSearch/Thrift/Server/TSSLServerSocket.php
  73. 100 0
      php/OpenSearch/Thrift/Server/TServer.php
  74. 122 0
      php/OpenSearch/Thrift/Server/TServerSocket.php
  75. 56 0
      php/OpenSearch/Thrift/Server/TServerTransport.php
  76. 58 0
      php/OpenSearch/Thrift/Server/TSimpleServer.php
  77. 40 0
      php/OpenSearch/Thrift/StringFunc/Core.php
  78. 46 0
      php/OpenSearch/Thrift/StringFunc/Mbstring.php
  79. 28 0
      php/OpenSearch/Thrift/StringFunc/TStringFunc.php
  80. 143 0
      php/OpenSearch/Thrift/TMultiplexedProcessor.php
  81. 181 0
      php/OpenSearch/Thrift/Transport/TBufferedTransport.php
  82. 249 0
      php/OpenSearch/Thrift/Transport/TCurlClient.php
  83. 193 0
      php/OpenSearch/Thrift/Transport/TFramedTransport.php
  84. 229 0
      php/OpenSearch/Thrift/Transport/THttpClient.php
  85. 100 0
      php/OpenSearch/Thrift/Transport/TMemoryBuffer.php
  86. 51 0
      php/OpenSearch/Thrift/Transport/TNullTransport.php
  87. 123 0
      php/OpenSearch/Thrift/Transport/TPhpStream.php
  88. 112 0
      php/OpenSearch/Thrift/Transport/TSSLSocket.php
  89. 337 0
      php/OpenSearch/Thrift/Transport/TSocket.php
  90. 300 0
      php/OpenSearch/Thrift/Transport/TSocketPool.php
  91. 95 0
      php/OpenSearch/Thrift/Transport/TTransport.php
  92. 50 0
      php/OpenSearch/Thrift/Type/TConstant.php
  93. 34 0
      php/OpenSearch/Thrift/Type/TMessageType.php
  94. 47 0
      php/OpenSearch/Thrift/Type/TType.php
  95. 222 0
      php/OpenSearch/Util/ClauseParamsBuilder.php
  96. 506 0
      php/OpenSearch/Util/SearchParamsBuilder.php
  97. 61 0
      php/OpenSearch/Util/SuggestParamsBuilder.php
  98. 183 0
      php/OpenSearch/Util/UrlParamsBuilder.php
  99. 14 0
      php/demo/Config.inc.php
  100. 11 0
      php/demo/demo_app.php

+ 38 - 0
.idea/$CACHE_FILE$

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectInspectionProfilesVisibleTreeState">
+    <entry key="Project Default">
+      <profile-state>
+        <expanded-state>
+          <State />
+          <State>
+            <id>CDI (Contexts and Dependency Injection)</id>
+          </State>
+          <State>
+            <id>CodeSpring CoreSpring</id>
+          </State>
+          <State>
+            <id>EncapsulationJava</id>
+          </State>
+          <State>
+            <id>Java</id>
+          </State>
+          <State>
+            <id>Spring</id>
+          </State>
+          <State>
+            <id>Spring AOPSpring</id>
+          </State>
+          <State>
+            <id>Spring CoreSpring</id>
+          </State>
+        </expanded-state>
+        <selected-state>
+          <State>
+            <id>AOP</id>
+          </State>
+        </selected-state>
+      </profile-state>
+    </entry>
+  </component>
+</project>

+ 76 - 0
.idea/$PRODUCT_WORKSPACE_FILE$

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="masterDetails">
+    <states>
+      <state key="ArquillianSettingsConfigurable.UI">
+        <settings>
+          <splitter-proportions>
+            <option name="proportions">
+              <list>
+                <option value="0.2" />
+              </list>
+            </option>
+          </splitter-proportions>
+        </settings>
+      </state>
+      <state key="GlobalLibrariesConfigurable.UI">
+        <settings>
+          <last-edited>scala-sdk-2.12.1</last-edited>
+          <splitter-proportions>
+            <option name="proportions">
+              <list>
+                <option value="0.2" />
+              </list>
+            </option>
+          </splitter-proportions>
+        </settings>
+      </state>
+      <state key="JdkListConfigurable.UI">
+        <settings>
+          <last-edited>1.8</last-edited>
+          <splitter-proportions>
+            <option name="proportions">
+              <list>
+                <option value="0.2" />
+              </list>
+            </option>
+          </splitter-proportions>
+        </settings>
+      </state>
+      <state key="ProjectJDKs.UI">
+        <settings>
+          <last-edited>1.8</last-edited>
+          <splitter-proportions>
+            <option name="proportions">
+              <list>
+                <option value="0.2" />
+              </list>
+            </option>
+          </splitter-proportions>
+        </settings>
+      </state>
+      <state key="ProjectLibrariesConfigurable.UI">
+        <settings>
+          <splitter-proportions>
+            <option name="proportions">
+              <list>
+                <option value="0.2" />
+              </list>
+            </option>
+          </splitter-proportions>
+        </settings>
+      </state>
+      <state key="ScopeChooserConfigurable.UI">
+        <settings>
+          <splitter-proportions>
+            <option name="proportions">
+              <list>
+                <option value="0.2" />
+              </list>
+            </option>
+          </splitter-proportions>
+        </settings>
+      </state>
+    </states>
+  </component>
+</project>

+ 2 - 0
.idea/.gitignore

@@ -0,0 +1,2 @@
+# Default ignored files
+/workspace.xml

+ 6 - 0
.idea/dictionaries

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectDictionaryState">
+    <dictionary name="liuyuqi" />
+  </component>
+</project>

+ 6 - 0
.idea/encodings.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding" native2AsciiForPropertiesFiles="true" defaultCharsetForPropertiesFiles="UTF-8">
+    <file url="PROJECT" charset="UTF-8" />
+  </component>
+</project>

+ 5 - 0
.idea/inspectionProfiles/profiles_settings.xml

@@ -0,0 +1,5 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="PROJECT_PROFILE" />
+  </settings>
+</component>

+ 9 - 0
.idea/misc.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+  <component name="SvnConfiguration">
+    <configuration>C:\Users\liuyuqi\AppData\Roaming\Subversion</configuration>
+  </component>
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/opensearch-tutorial.iml" filepath="$PROJECT_DIR$/.idea/opensearch-tutorial.iml" />
+    </modules>
+  </component>
+</project>

+ 9 - 0
.idea/opensearch-tutorial.iml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>

+ 2 - 0
README.md

@@ -0,0 +1,2 @@
+## opensearch-tutorial
+

+ 57 - 0
docs/安装使用.md

@@ -0,0 +1,57 @@
+## 安装使用
+
+### 产品介绍
+
+阿里云搜索产品,**结构化数据搜索**托管服务,可实现在线/离线,实时搜索功能。**在内存中**构建索引并提供搜索服务。开发者通过控制台和API与系统交互。
+
+
+
+## 使用场景
+
+电商产品搜索,文档搜索,大数据搜索。
+
+
+
+1、曾有一个用户有一个1TB csv **用户信息**,包含用户xxxx,需求:通过搜索用户名,邮箱等查询结果。
+
+2、某查查公司有**企业工商数据**,需求:通过用户名字,公司名字等查询相关信息。
+
+3、某 xx 外卖平台有**店铺,商品信息**,业务部门需要通过 餐品名,店铺名查询 某外卖店相关信息,定向推广。
+
+
+
+### 安装使用
+
+阿里云服务,无需自己安装。开通 <https://www.aliyun.com/product/opensearch> 即可。
+
+- 第一步,控制台创建应用,创建表。
+
+- 第二步,通过api上传数据。
+
+- 第三步, **数据查询,处理,推送结果。**
+
+      
+
+提供 php,java,python等sdk
+
+
+
+java:
+
+```xml
+<dependency>
+    <groupId>com.aliyun.opensearch</groupId>
+    <artifactId>aliyun-sdk-opensearch</artifactId>
+    <version>3.4.1</version>
+</dependency>
+
+```
+
+
+
+php:
+
+http://docs-aliyun.cn-hangzhou.oss.aliyun-inc.com/assets/attach/53083/cn_zh/1556162189492/opensearch-sdk-php-release-v3.1.0.zip?spm=a2c4g.11186623.2.14.28ca3abdMVLd2x&file=opensearch-sdk-php-release-v3.1.0.zip
+
+
+

+ 0 - 0
java/.gitkeep


+ 1 - 0
php/.gitignore

@@ -0,0 +1 @@
+vendor

+ 31 - 0
php/OpenSearch/Autoloader/Autoloader.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.
+ */
+
+$basePath = __DIR__ . '/../../';
+require_once $basePath . 'OpenSearch/Thrift/ClassLoader/ThriftClassLoader.php';
+
+use Thrift\ClassLoader\ThriftClassLoader;
+
+$loader = new ThriftClassLoader();
+
+$loader->registerNamespace('Thrift', $basePath . 'OpenSearch');
+$loader->registerNamespace('OpenSearch', $basePath);
+$loader->registerDefinition('OpenSearch', $basePath);
+$loader->register();

+ 123 - 0
php/OpenSearch/Client/AppClient.php

@@ -0,0 +1,123 @@
+<?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.
+ */
+
+namespace OpenSearch\Client;
+
+use OpenSearch\Generated\App\AppServiceIf;
+use OpenSearch\Generated\Common\Pageable;
+
+/**
+ * 应用基本信息管理类。
+ *
+ * 管理应用的基本信息,包含创建应用(save)、修改应用(updateById)、删除应用(removeById)
+ * 、获取应用的基本详情(getById)、获取应用列表(listAll)、给应用导入全量数据(reindexById)
+ * 等方法。
+ *
+ */
+class AppClient implements AppServiceIf {
+
+    private $openSearchClient = null;
+
+    private $path = "/apps";
+
+    /**
+     * 构造方法。
+     *
+     * @param \OpenSearch\Client\OpenSearchClient $openSearchClient 基础类,负责计算签名,和服务端进行交互和返回结果。
+     * @return void
+     */
+    public function __construct($openSearchClient) {
+        $this->openSearchClient = $openSearchClient;
+    }
+
+    /**
+     * 创建一个新应用,或者创建一个新版本。
+     *
+     * 创建一个新的应用或者创建一个新的版本,如果在$app中指定了name,则会创建一个新版本,否则会创建一个新应用。
+     *
+     * > 创建版本的个数依赖服务端的限制。
+     *
+     * @param string $app 要创建的应用主体JSON,包含name、type、schema、quota、first_ranks、second_ranks、summary、data_sources、suggest、fetch_fields、query_processors等信息。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult OpenSearchResult类
+     */
+    public function save($app) {
+        return $this->openSearchClient->post($this->path, $app);
+    }
+
+    /**
+     * 通过应用名称或者应用ID获取一个应用的详情信息。
+     *
+     * @param string $identity 要查询的应用名称或者应用ID,如果应用有多个版本,则指定应用名称为当前应用的在线版本。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function getById($identity) {
+        $path = $this->path . "/" . $identity;
+        return $this->openSearchClient->get($path);
+    }
+
+    /**
+     * 获取应用列表。
+     *
+     * @param \OpenSearch\Generated\Common\Pageable $pageable 分页信息,包含页码和每页展示条数。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function listAll(Pageable $pageable) {
+        return $this->openSearchClient->get(
+            $this->path, array('page' => $pageable->page, 'size' => $pageable->size)
+        );
+    }
+
+    /**
+     * 根据指定的应用id或名称删除应用版本或者应用;当指定的为应用名称,则表示指定的为当前应用分组中的在线的应用。。
+     *
+     * 如果当前应用只有一个版本,则会删除这个应用的整个分组;
+     * 如果当前应用分组有多个应用,则需要当前要删除的版本不能处于在线状态。
+     *
+     * @param string $identity 指定的应用ID或者应用名称。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function removeById($identity) {
+        $path = $this->path . "/" . $identity;
+        return $this->openSearchClient->delete($path);
+    }
+
+    /**
+     * 更新某个应用的信息。
+     *
+     * @param string $identity 指定的应用ID或者应用名称;当指定的为应用名称,则表示指定的为当前应用分组中的在线的应用。
+     * @param string $app 修改一个应用的应用结构json,包含name、type、schema、quota、first_ranks、second_ranks、summary、data_sources、suggest、fetch_fields、query_processors等信息。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function updateById($identity, $app) {
+        $path = $this->path . "/" . $identity;
+        return $this->openSearchClient->patch($path, $app);
+    }
+
+    /**
+     * 在创建过程中全量导入数据。
+     *
+     * @param string $identity 指定的应用ID或者应用名称;当指定的为应用名称,则表示指定的为当前应用分组中的在线的应用。。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function reindexById($identity) {
+        $path = $this->path . "/{$identity}/actions/reindex";
+        return $this->openSearchClient->post($path);
+    }
+}

+ 152 - 0
php/OpenSearch/Client/BehaviorCollectionClient.php

@@ -0,0 +1,152 @@
+<?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.
+ */
+
+namespace OpenSearch\Client;
+
+use OpenSearch\Generated\BehaviorCollection\Command;
+use OpenSearch\Generated\BehaviorCollection\Constant;
+use OpenSearch\Generated\BehaviorCollection\BehaviorCollectionServiceIf;
+use OpenSearch\Client\OpenSearchClient;
+
+/**
+ * 搜索行为数据文档推送类。
+ *
+ * 管理搜索应用的行为数据推送,包含单条推送文档、批量推送文档等。
+ *
+ */
+class BehaviorCollectionClient implements BehaviorCollectionServiceIf {
+
+	private $openSearchClient;
+	private $recordBuffer = array();
+
+	const SEARCH_DOC_CLICK_EVENT_ID = 2001;
+
+	/**
+     * 构造方法。
+     *
+     * @param \OpenSearch\Client\OpenSearchClient $openSearchClient 基础类,负责计算签名,和服务端进行交互和返回结果。
+     * @return void
+     */
+	public function __construct($openSearchClient) {
+        $this->openSearchClient = $openSearchClient;
+    }
+
+    /**
+     * 增加一条搜索点击文档。
+     *
+     * > Note:
+     * >
+     * > 这条文档只是增加到sdk client buffer中,没有正式提交到服务端;只有调用了commit方法才会被提交到服务端。
+     * > 你可以多次addSearchDocClickRecord然后调用commit() 统一提交。
+     *
+     * @param string $searchDocListPage 	搜索结果列表所在的页面名称
+     * @param string $docDetailPage 		某个搜索文档被点击后,搜索文档的详情页面名称
+     * @param int    $detailPageStayTime 	用户在详情页停留的时长(单位为ms)
+     * @param string $objectId 				被点击的文档的主键,不能为空
+     * @param string $opsRequestMisc 		opensearch返回的查询结果中的ops_request_misc字段
+     * @param string $basicFields 			其他基础字段, 非必需字段
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function addSearchDocClickRecord(
+    	$searchDocListPage, 
+    	$docDetailPage,
+    	$detailPageStayTime,
+		$objectId,
+		$opsRequestMisc,
+		array $basicFields = []) {
+
+    	$jsonFields = [
+    		'event_id'    => self::SEARCH_DOC_CLICK_EVENT_ID,
+    		'sdk_type'    => OpenSearchClient::SDK_TYPE,
+    		'sdk_version' => OpenSearchClient::SDK_VERSION,
+    		'page' => $docDetailPage,
+    		'arg1' => $searchDocListPage,
+    		'arg2' => "",
+    		'arg3' => $detailPageStayTime,
+    		'args' => self::createSearchDocClickArgs($objectId, $opsRequestMisc),
+    	];
+
+    	if (!empty($basicFields)) {
+    		foreach ($basicFields as $key => $value) {
+    			$jsonFields[$key] = $value;
+    		}
+    	}
+
+    	$this->addOneRecord($jsonFields, Command::$__names[Command::ADD]);
+    }
+
+    /**
+     * 把sdk client buffer中的文档发布到服务端。
+     *
+     * > Note:
+     * >
+     * > 在发送之前会把buffer中的文档清空,所以如果服务端返回错误需要重试的情况下,需要重新生成文档并commit,避免丢数据的可能。
+     *
+     * @param string $searchAppName 			关联的搜索应用名
+     * @param string $behaviorCollectionName	行为数据采集名称,开通时控制台会返回该名称
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function commit($searchAppName, $behaviorCollectionName) {
+    	$recordsJson = json_encode($this->recordBuffer);
+    	$this->recordBuffer = array();
+    	return $this->doPush($recordsJson, $searchAppName, $behaviorCollectionName);
+    }
+
+    /**
+     * 批量推送文档。
+     *
+     * > Note:
+     * >
+     * > 此操作会同步发送文档到服务端。
+     *
+     * @param string $recordsJson 				文档list的json
+     * @param string $searchAppName 			关联的搜索应用名
+     * @param string $behaviorCollectionName	行为数据采集名称,开通时控制台会返回该名称
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function push($recordsJson, $searchAppName, $behaviorCollectionName) {
+    	return $this->doPush($recordsJson, $searchAppName, $behaviorCollectionName);
+    }
+
+    private function doPush($recordsJson, $searchAppName, $behaviorCollectionName) {
+    	$path = self::createPushPath($searchAppName, $behaviorCollectionName);
+    	return $this->openSearchClient->post($path, $recordsJson);
+    }
+
+    private function addOneRecord($jsonFields, $command) {
+    	$cmdName    = Constant::get('DOC_KEY_CMD');
+    	$fieldsName = Constant::get('DOC_KEY_FIELDS');
+    	
+    	$jsonRecord = [
+    		$cmdName    => $command,
+    		$fieldsName => $jsonFields
+    	];
+
+    	$this->recordBuffer[] = $jsonRecord;
+    }
+
+    private static function createPushPath($searchAppName, $behaviorCollectionName) {
+    	return sprintf("/app-groups/%s/data-collections/%s/actions/bulk", $searchAppName, $behaviorCollectionName);
+    }
+
+    private static function createSearchDocClickArgs($objectId, $opsRequestMisc) {
+    	return sprintf("object_id=%s,object_type=ops_search_doc,ops_request_misc=%s", $objectId, $opsRequestMisc);
+    }
+}

+ 151 - 0
php/OpenSearch/Client/DocumentClient.php

@@ -0,0 +1,151 @@
+<?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.
+ */
+
+namespace OpenSearch\Client;
+
+use OpenSearch\Generated\Document\Command;
+use OpenSearch\Generated\Document\Constant;
+use OpenSearch\Generated\Document\DocumentServiceIf;
+
+/**
+ * 应用文档操作类。
+ *
+ * 管理应用的文档,包含推送文档,删除文档,更新文档,批量推送文档等。
+ *
+ */
+class DocumentClient implements DocumentServiceIf {
+
+    private $openSearchClient;
+
+    const DOCUMENT_API_PATH = '/apps';
+
+    /**
+     * @var sdk缓存的文档的数量。
+     */
+    public $docs = array();
+
+    /**
+     * 构造方法。
+     *
+     * @param \OpenSearch\Client\OpenSearchClient $openSearchClient 基础类,负责计算签名,和服务端进行交互和返回结果。
+     * @return void
+     */
+    public function __construct($openSearchClient) {
+        $this->openSearchClient = $openSearchClient;
+    }
+
+    /**
+     * 增加一条文档。
+     *
+     * > Note:
+     * >
+     * > 这条文档只是增加到sdk client buffer中,没有正式提交到服务端;只有调用了commit方法才会被提交到服务端。
+     * 你可以add多次然后调用commit() 统一提交。
+     *
+     * @param array $fields 一条文档的所有字段,例如array("id" => 1, "name" => "tony");
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function add($fields) {
+        $this->pushOneDoc($fields, Command::$__names[Command::ADD]);
+    }
+
+    /**
+     * 修改一条文档。
+     *
+     * > Note:
+     * >
+     * > 这条文档只是增加到sdk client buffer中,没有正式提交到服务端;只有调用了commit方法才会被提交到服务端。
+     * 你可以update多次然后调用commit() 统一提交。
+     *
+     * > 标准版不支持update操作。
+     *
+     * @param array $fields 一条文档的所有字段,例如array("id" => 1, "name" => "tony");
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function update($fields) {
+        $this->pushOneDoc($fields, Command::$__names[Command::UPDATE]);
+    }
+
+    /**
+     * 删除一条文档。
+     *
+     * > Note:
+     * >
+     * > 这条文档只是增加到sdk client buffer中,没有正式提交到服务端;只有调用了commit方法才会被提交到服务端。
+     * 你可以remove多次然后调用commit() 统一提交。
+     *
+     * @param array $fields 一条文档的主键字段,例如array("id" => 1);
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function remove($fields) {
+        $this->pushOneDoc($fields, Command::$__names[Command::DELETE]);
+    }
+
+    /**
+     * 批量推送文档。
+     *
+     * > Note:
+     * >
+     * > 此操作会同步发送到服务端。
+     *
+     * @param string $docsJson 文档list的json,例如[{"cmd":"ADD","fields":{"id":"1","name":"tony"}},...]
+     * @param string $appName 指定的app name或者app ID
+     * @param string $tableName 指定的table name
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function push($docsJson, $appName, $tableName) {
+        $path = self::_getPath($appName, $tableName);
+        return $this->openSearchClient->post($path, $docsJson);
+    }
+
+    /**
+     * 把client buffer中的文档发布到服务端。
+     *
+     * > Note:
+     * >
+     * > 在发送之前会把buffer中的文档清空,所以如果服务端返回错误需要重试的情况下,需要重新生成文档并commit,避免丢数据的可能。
+     *
+     * @param string $appName 指定的app name或者app ID
+     * @param string $tableName 指定的table name
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function commit($appName, $tableName) {
+        $json = json_encode($this->docs);
+        $this->docs = array();
+        return $this->push($json, $appName, $tableName);
+    }
+
+    /**
+     * 推送一条文档到客户端buffer中。
+     *
+     * @param array $fields 一条文档的所有字段,例如array("id" => 1, "name" => "tony");
+     * @param string $cmd 文档的操作类型,有ADD, UPDATE和DELETE;
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function pushOneDoc($fields, $cmd) {
+        $cmdName = Constant::get('DOC_KEY_CMD');
+        $fieldName = Constant::get('DOC_KEY_FIELDS');
+        $this->docs[] = array($cmdName => $cmd, $fieldName => $fields);
+    }
+
+    private static function _getPath($appName, $tableName) {
+        return self::DOCUMENT_API_PATH . sprintf("/%s/%s/actions/bulk", $appName, $tableName);
+    }
+}

+ 314 - 0
php/OpenSearch/Client/OpenSearchClient.php

@@ -0,0 +1,314 @@
+<?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.
+ */
+
+namespace OpenSearch\Client;
+
+use OpenSearch\Generated\OpenSearch\OpenSearch;
+use OpenSearch\Generated\OpenSearch\Constant;
+use OpenSearch\Generated\Common\OpenSearchResult;
+use OpenSearch\Generated\Common\TraceInfo;
+
+class OpenSearchClient extends OpenSearch {
+
+    const METHOD_GET = 'GET';
+    const METHOD_POST = 'POST';
+    const METHOD_PUT = 'PUT';
+    const METHOD_DELETE = 'DELETE';
+    const METHOD_PATCH = 'PATCH';
+
+    const API_VERSION = '3';
+    const API_TYPE = 'openapi';
+
+    const SDK_VERSION = '3.1.0';
+    const SDK_TYPE    = 'opensearch_sdk';
+
+    private $debug = false;
+
+    public $timeout = 10;
+    public $connectTimeout = 1;
+
+    /**
+     * 构造方法。
+     *
+     * @param string $accessKey 指定您的accessKeyId,在 https://ak-console.aliyun.com/#/accesskey 中可以创建。
+     * @param string $secret 指定您的secret。
+     * @param string $host 指定您要访问的区域的endPoint,在控制台应用详情页中有指定。
+     * @param array @options 指定一些可选参数,debug:true/false,是否开启debug模式(默认不开启),gzip:true/false 是否开启gzip压缩(默认不开启),timeout:超时时间,seconds(默认10秒),connectTimeout: 连接超时时间,seconds(默认1秒)
+     * @return void
+     */
+    public function __construct($accessKey, $secret, $host, $options = array()) {
+        $args = array(
+            'accessKey' => trim($accessKey),
+            'secret' => trim($secret),
+            'host' => trim($host),
+            'options' => $options
+        );
+
+        if (isset($options['gzip'])) {
+            $args['gzip'] = $options['gzip'];
+        }
+
+        if (isset($options['timeout'])) {
+            $args['timeout'] = $options['timeout'];
+        }
+
+        if (isset($options['connectTimeout'])) {
+            $args['connectTimeout'] = $options['connectTimeout'];
+        }
+
+        if (isset($options['debug'])) {
+            $this->debug = (boolean) $options['debug'];
+        }
+
+        parent::__construct($args);
+    }
+
+    /**
+     * 发送一个GET请求。
+     *
+     * @param string $uri 发起GET请求的uri。
+     * @param array $params 发起GET请求的参数,以param_key => param_value的方式体现。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function get($uri, $params = array()) {
+        return $this->call($uri, $params, '', self::METHOD_GET);
+    }
+
+    /**
+     * 发送一个PUT请求。
+     *
+     * @param string $uri 发起PUT请求的uri。
+     * @param string $body 发起PUT请求的body体,为一个原始的json格式的string。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function put($uri, $body = '') {
+        return $this->call($uri, array(), $body, self::METHOD_PUT);
+    }
+
+    /**
+     * 发送一个POST请求。
+     *
+     * @param string $uri 发起POST请求的uri。
+     * @param string $body 发起POST请求的body体,为一个原始的json格式的string。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function post($uri, $body = '') {
+        return $this->call($uri, array(), $body, self::METHOD_POST);
+    }
+
+    /**
+     * 发送一个DELETE请求。
+     *
+     * @param string $uri 发起DELETE请求的uri。
+     * @param string $body 发起DELETE请求的body体,为一个原始的json格式的string。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function delete($uri, $body = '') {
+        return $this->call($uri, array(), $body, self::METHOD_DELETE);
+    }
+
+    /**
+     * 发送一个PATCH请求。
+     *
+     * @param string $uri 发起PATCH请求的uri。
+     * @param string $body 发起PATCH请求的body体,为一个原始的json格式的string。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function patch($uri, $body = '') {
+        return $this->call($uri, array(), $body, self::METHOD_PATCH);
+    }
+
+    /**
+     * 发送一个请求。
+     *
+     * @param string $uri 发起请求的uri。
+     * @param array $params 指定的url中的query string 列表。
+     * @param string $body 发起请求的body体,为一个原始的json格式的string。
+     * @param string $method 发起请求的方法,有GET/POST/DELETE/PUT/PATCH等
+     * @return \OpenSearch\Generated\Common\OpenSearchResult
+     */
+    public function call($uri, array $params, $body, $method) {
+        $path = "/v" . self::API_VERSION . "/" . self::API_TYPE . "{$uri}";
+        $url = $this->host . $path;
+
+        $items = array();
+        $items['method'] = $method;
+        $items['request_path'] = $path;
+        $items['content_type'] = "application/json";
+        $items['accept_language'] = "zh-cn";
+        $items['date'] = gmdate('Y-m-d\TH:i:s\Z');
+        $items['opensearch_headers'] = array();
+        $items['content_md5'] = "";
+        $items['opensearch_headers']['X-Opensearch-Nonce'] = $this->_nonce();
+
+        if ($method != self::METHOD_GET) {
+            if (!empty($body)) {
+                $items['content_md5'] = md5($body);
+                $items['body_json'] = $body;
+            }
+        }
+        $items['query_params'] = $params;
+
+        $signature = $this->_signature($this->secret, $items);
+        $items['authorization'] = "OPENSEARCH {$this->accessKey}:{$signature}";
+
+        return $this->_curl($url, $items);
+    }
+
+    private function _nonce() {
+        return intval(microtime(true) * 1000) . mt_rand(10000, 99999);
+    }
+
+    private function _signature($secret, $items) {
+        $params = isset($items['query_params']) ? $items['query_params'] : "";
+
+        $signature = '';
+        $string = '';
+        $string .= strtoupper($items['method']) . "\n";
+        $string .= $items['content_md5'] . "\n";
+        $string .= $items['content_type'] . "\n";
+        $string .= $items['date'] . "\n";
+
+        $headers = self::_filter($items['opensearch_headers']);
+        foreach($headers as $key => $value){
+          $string .= strtolower($key) . ":" . $value."\n";
+        }
+
+        $resource = str_replace('%2F', '/', rawurlencode($items['request_path']));
+        $sortParams = self::_filter($params);
+
+        $queryString = $this->_buildQuery($sortParams);
+        $canonicalizedResource = $resource;
+
+        if(!empty($queryString)){
+          $canonicalizedResource .= '?'.$queryString;
+        }
+
+        $string .= $canonicalizedResource;
+
+        $signature = base64_encode(hash_hmac('sha1', $string, $secret, true));
+        return $signature;
+    }
+
+    private function _buildQuery($params) {
+        $query = '';
+        if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
+            $query = !empty($params) ? http_build_query($params, null, '&', PHP_QUERY_RFC3986) : '';
+        } else {
+            $arg = '';
+            foreach ($params as $key => $val) {
+                $arg .= rawurlencode($key) . "=" . rawurlencode($val) . "&";
+            }
+            $query = substr($arg, 0, count($arg) - 2);
+        }
+
+        return $query;
+    }
+
+    private function _filter($parameters = array()){
+        $params = array();
+        if(!empty($parameters)){
+            foreach ($parameters as $key => $val) {
+                if ($key == "Signature" ||$val === "" || $val === NULL){
+                    continue;
+                } else {
+                    $params[$key] = $parameters[$key];
+                }
+            }
+
+            uksort($params,'strnatcasecmp');
+            reset($params);
+        }
+        return $params;
+    }
+
+    private function _getHeaders($items) {
+        $headers = array();
+        $headers[] = 'Content-Type: '.$items['content_type'];
+        $headers[] = 'Date: '.$items['date'];
+        $headers[] = 'Accept-Language: '.$items['accept_language'];
+        $headers[] = 'Content-Md5: '.$items['content_md5'];
+        $headers[] = 'Authorization: '.$items['authorization'];
+        if (is_array($items['opensearch_headers'])) {
+            foreach($items['opensearch_headers'] as $key => $value){
+                $headers[] = $key . ": " . $value;
+            }
+        }
+
+        return $headers;
+    }
+
+    private function _curl($url, $items) {
+        $method = strtoupper($items['method']);
+        $options = array(
+            CURLOPT_HTTP_VERSION => 'CURL_HTTP_VERSION_1_1',
+            CURLOPT_CONNECTTIMEOUT => $this->connectTimeout,
+            CURLOPT_TIMEOUT => $this->timeout,
+            CURLOPT_CUSTOMREQUEST => $method,
+            CURLOPT_HEADER => false,
+            CURLOPT_RETURNTRANSFER => true,
+            CURLOPT_USERAGENT => "opensearch/php sdk " . self::SDK_VERSION . "/" . PHP_VERSION,
+            CURLOPT_HTTPHEADER => $this->_getHeaders($items),
+        );
+
+        if ($method == self::METHOD_GET) {
+            $query = $this->_buildQuery($items['query_params']);
+            $url .= preg_match('/\?/i', $url) ? '&' . $query : '?' . $query;
+        } else{
+            if(!empty($items['body_json'])){
+                $options[CURLOPT_POSTFIELDS] = $items['body_json'];
+            }
+        }
+
+        if ($this->gzip) {
+            $options[CURLOPT_ENCODING] = 'gzip';
+        }
+
+        if ($this->debug) {
+            $out = fopen('php://temp','rw');
+            $options[CURLOPT_VERBOSE] = true;
+            $options[CURLOPT_STDERR] = $out;
+        }
+
+        $session = curl_init($url);
+        curl_setopt_array($session, $options);
+        $response = curl_exec($session);
+        curl_close($session);
+
+        $openSearchResult = new OpenSearchResult();
+        $openSearchResult->result = $response;
+
+        if ($this->debug) {
+            $openSearchResult->traceInfo = $this->getDebugInfo($out, $items);
+        }
+
+        return $openSearchResult;
+    }
+
+    private function getDebugInfo($handler, $items) {
+        rewind($handler);
+        $trace = new TraceInfo();
+        $header = stream_get_contents($handler);
+        fclose($handler);
+
+        $trace->tracer = "\n" . $header;
+        return $trace;
+    }
+}

+ 67 - 0
php/OpenSearch/Client/SearchClient.php

@@ -0,0 +1,67 @@
+<?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.
+ */
+
+namespace OpenSearch\Client;
+
+use OpenSearch\Generated\Search\Config;
+use OpenSearch\Generated\Search\OpenSearchSearcherServiceIf;
+use OpenSearch\Generated\Search\SearchFormat;
+use OpenSearch\Generated\Search\SearchParams;
+use OpenSearch\Util\UrlParamsBuilder;
+
+/**
+ * 应用搜索操作类。
+ *
+ * 通过制定关键词、过滤条件搜索应用结果。
+ *
+ */
+class SearchClient implements OpenSearchSearcherServiceIf {
+
+    const SEARCH_API_PATH = '/apps/%s/search';
+
+    private $openSearchClient;
+
+    /**
+     * 构造方法。
+     *
+     * @param \OpenSearch\Client\OpenSearchClient $openSearchClient 基础类,负责计算签名,和服务端进行交互和返回结果。
+     * @return void
+     */
+    public function __construct($openSearchClient) {
+        $this->openSearchClient = $openSearchClient;
+    }
+
+    /**
+     * 执行搜索操作。
+     *
+     * @param \OpenSearch\Generated\Search\SearchParams $searchParams 制定的搜索条件。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult OpenSearchResult类
+     */
+    public function execute(SearchParams $searchParams) {
+        $path = self::getPath($searchParams);
+        $builder = new UrlParamsBuilder($searchParams);
+        return $this->openSearchClient->get($path, $builder->getHttpParams());
+    }
+
+    private static function getPath($searchParams) {
+        $appNames = isset($searchParams->config->appNames) ? implode(',', $searchParams->config->appNames) : '';
+        return sprintf(self::SEARCH_API_PATH, $appNames);
+    }
+}

+ 67 - 0
php/OpenSearch/Client/SuggestClient.php

@@ -0,0 +1,67 @@
+<?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.
+ */
+
+namespace OpenSearch\Client;
+
+use OpenSearch\Generated\Search\OpenSearchSearcherServiceIf;
+use OpenSearch\Generated\Search\SearchParams;
+use OpenSearch\Util\SuggestParamsBuilder;
+
+/**
+ * 应用下拉提示操作类。
+ *
+ * 通过制定关键词、过滤条件搜索应用的下拉提示的结果。
+ *
+ */
+class SuggestClient implements OpenSearchSearcherServiceIf {
+
+    const SUGGEST_API_PATH = '/apps/%s/suggest/%s/search';
+
+    private $openSearchClient;
+
+    /**
+     * 构造方法。
+     *
+     * @param \OpenSearch\Client\OpenSearchClient $openSearchClient 基础类,负责计算签名,和服务端进行交互和返回结果。
+     * @return void
+     */
+    public function __construct($openSearchClient) {
+        $this->openSearchClient = $openSearchClient;
+    }
+
+    /**
+     * 执行搜索操作。
+     *
+     * @param \OpenSearch\Generated\Search\SearchParams $searchParams 制定的搜索条件。
+     * @return \OpenSearch\Generated\Common\OpenSearchResult OpenSearchResult类
+     */
+    public function execute(SearchParams $searchParams) {
+        $path = self::getPath($searchParams);
+        $params = SuggestParamsBuilder::getQueryParams($searchParams);
+        return $this->openSearchClient->get($path, $params);
+    }
+
+    private static function getPath($searchParams) {
+        $appName = implode(',', $searchParams->config->appNames);
+        $suggestName = $searchParams->suggest->suggestName;
+
+        return sprintf(self::SUGGEST_API_PATH, $appName, $suggestName);
+    }
+}

+ 1861 - 0
php/OpenSearch/Generated/App/AppService.php

@@ -0,0 +1,1861 @@
+<?php
+namespace OpenSearch\Generated\App;
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+interface AppServiceIf {
+  /**
+   * @param string $app
+   * @return \OpenSearch\Generated\Common\OpenSearchResult
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function save($app);
+  /**
+   * @param string $identity
+   * @return \OpenSearch\Generated\Common\OpenSearchResult
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function getById($identity);
+  /**
+   * @param \OpenSearch\Generated\Common\Pageable $pageable
+   * @return \OpenSearch\Generated\Common\OpenSearchResult
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function listAll(\OpenSearch\Generated\Common\Pageable $pageable);
+  /**
+   * @param string $identity
+   * @return \OpenSearch\Generated\Common\OpenSearchResult
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function removeById($identity);
+  /**
+   * @param string $identity
+   * @param string $app
+   * @return \OpenSearch\Generated\Common\OpenSearchResult
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function updateById($identity, $app);
+  /**
+   * @param string $identity
+   * @return \OpenSearch\Generated\Common\OpenSearchResult
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function reindexById($identity);
+}
+
+
+class AppServiceClient implements \OpenSearch\Generated\App\AppServiceIf {
+  protected $input_ = null;
+  protected $output_ = null;
+
+  protected $seqid_ = 0;
+
+  public function __construct($input, $output=null) {
+    $this->input_ = $input;
+    $this->output_ = $output ? $output : $input;
+  }
+
+  public function save($app)
+  {
+    $this->send_save($app);
+    return $this->recv_save();
+  }
+
+  public function send_save($app)
+  {
+    $args = new \OpenSearch\Generated\App\AppService_save_args();
+    $args->app = $app;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'save', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('save', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_save()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\App\AppService_save_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\App\AppService_save_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("save failed: unknown result");
+  }
+
+  public function getById($identity)
+  {
+    $this->send_getById($identity);
+    return $this->recv_getById();
+  }
+
+  public function send_getById($identity)
+  {
+    $args = new \OpenSearch\Generated\App\AppService_getById_args();
+    $args->identity = $identity;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'getById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('getById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_getById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\App\AppService_getById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\App\AppService_getById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("getById failed: unknown result");
+  }
+
+  public function listAll(\OpenSearch\Generated\Common\Pageable $pageable)
+  {
+    $this->send_listAll($pageable);
+    return $this->recv_listAll();
+  }
+
+  public function send_listAll(\OpenSearch\Generated\Common\Pageable $pageable)
+  {
+    $args = new \OpenSearch\Generated\App\AppService_listAll_args();
+    $args->pageable = $pageable;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'listAll', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('listAll', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_listAll()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\App\AppService_listAll_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\App\AppService_listAll_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("listAll failed: unknown result");
+  }
+
+  public function removeById($identity)
+  {
+    $this->send_removeById($identity);
+    return $this->recv_removeById();
+  }
+
+  public function send_removeById($identity)
+  {
+    $args = new \OpenSearch\Generated\App\AppService_removeById_args();
+    $args->identity = $identity;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'removeById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('removeById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_removeById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\App\AppService_removeById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\App\AppService_removeById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("removeById failed: unknown result");
+  }
+
+  public function updateById($identity, $app)
+  {
+    $this->send_updateById($identity, $app);
+    return $this->recv_updateById();
+  }
+
+  public function send_updateById($identity, $app)
+  {
+    $args = new \OpenSearch\Generated\App\AppService_updateById_args();
+    $args->identity = $identity;
+    $args->app = $app;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'updateById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('updateById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_updateById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\App\AppService_updateById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\App\AppService_updateById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("updateById failed: unknown result");
+  }
+
+  public function reindexById($identity)
+  {
+    $this->send_reindexById($identity);
+    return $this->recv_reindexById();
+  }
+
+  public function send_reindexById($identity)
+  {
+    $args = new \OpenSearch\Generated\App\AppService_reindexById_args();
+    $args->identity = $identity;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'reindexById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('reindexById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_reindexById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\App\AppService_reindexById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\App\AppService_reindexById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("reindexById failed: unknown result");
+  }
+
+}
+
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+class AppService_save_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $app = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'app',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['app'])) {
+        $this->app = $vals['app'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_save_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->app);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_save_args');
+    if ($this->app !== null) {
+      $xfer += $output->writeFieldBegin('app', TType::STRING, 1);
+      $xfer += $output->writeString($this->app);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_save_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchResult
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchResult',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_save_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\Common\OpenSearchResult();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_save_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_getById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $identity = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'identity',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['identity'])) {
+        $this->identity = $vals['identity'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_getById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->identity);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_getById_args');
+    if ($this->identity !== null) {
+      $xfer += $output->writeFieldBegin('identity', TType::STRING, 1);
+      $xfer += $output->writeString($this->identity);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_getById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchResult
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchResult',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_getById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\Common\OpenSearchResult();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_getById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_listAll_args {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Common\Pageable
+   */
+  public $pageable = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'pageable',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\Pageable',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['pageable'])) {
+        $this->pageable = $vals['pageable'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_listAll_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->pageable = new \OpenSearch\Generated\Common\Pageable();
+            $xfer += $this->pageable->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_listAll_args');
+    if ($this->pageable !== null) {
+      if (!is_object($this->pageable)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('pageable', TType::STRUCT, 1);
+      $xfer += $this->pageable->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_listAll_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchResult
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchResult',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_listAll_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\Common\OpenSearchResult();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_listAll_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_removeById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $identity = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'identity',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['identity'])) {
+        $this->identity = $vals['identity'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_removeById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->identity);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_removeById_args');
+    if ($this->identity !== null) {
+      $xfer += $output->writeFieldBegin('identity', TType::STRING, 1);
+      $xfer += $output->writeString($this->identity);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_removeById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchResult
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchResult',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_removeById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\Common\OpenSearchResult();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_removeById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_updateById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $identity = null;
+  /**
+   * @var string
+   */
+  public $app = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'identity',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'app',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['identity'])) {
+        $this->identity = $vals['identity'];
+      }
+      if (isset($vals['app'])) {
+        $this->app = $vals['app'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_updateById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->identity);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->app);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_updateById_args');
+    if ($this->identity !== null) {
+      $xfer += $output->writeFieldBegin('identity', TType::STRING, 1);
+      $xfer += $output->writeString($this->identity);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->app !== null) {
+      $xfer += $output->writeFieldBegin('app', TType::STRING, 2);
+      $xfer += $output->writeString($this->app);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_updateById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchResult
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchResult',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_updateById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\Common\OpenSearchResult();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_updateById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_reindexById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $identity = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'identity',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['identity'])) {
+        $this->identity = $vals['identity'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_reindexById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->identity);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_reindexById_args');
+    if ($this->identity !== null) {
+      $xfer += $output->writeFieldBegin('identity', TType::STRING, 1);
+      $xfer += $output->writeString($this->identity);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppService_reindexById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchResult
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchResult',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppService_reindexById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\Common\OpenSearchResult();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppService_reindexById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppServiceProcessor {
+  protected $handler_ = null;
+  public function __construct($handler) {
+    $this->handler_ = $handler;
+  }
+
+  public function process($input, $output) {
+    $rseqid = 0;
+    $fname = null;
+    $mtype = 0;
+
+    $input->readMessageBegin($fname, $mtype, $rseqid);
+    $methodname = 'process_'.$fname;
+    if (!method_exists($this, $methodname)) {
+      $input->skip(TType::STRUCT);
+      $input->readMessageEnd();
+      $x = new TApplicationException('Function '.$fname.' not implemented.', TApplicationException::UNKNOWN_METHOD);
+      $output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid);
+      $x->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+      return;
+    }
+    $this->$methodname($rseqid, $input, $output);
+    return true;
+  }
+
+  protected function process_save($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\App\AppService_save_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\App\AppService_save_result();
+    try {
+      $result->success = $this->handler_->save($args->app);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'save', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('save', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_getById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\App\AppService_getById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\App\AppService_getById_result();
+    try {
+      $result->success = $this->handler_->getById($args->identity);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'getById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('getById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_listAll($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\App\AppService_listAll_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\App\AppService_listAll_result();
+    try {
+      $result->success = $this->handler_->listAll($args->pageable);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'listAll', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('listAll', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_removeById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\App\AppService_removeById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\App\AppService_removeById_result();
+    try {
+      $result->success = $this->handler_->removeById($args->identity);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'removeById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('removeById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_updateById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\App\AppService_updateById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\App\AppService_updateById_result();
+    try {
+      $result->success = $this->handler_->updateById($args->identity, $args->app);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'updateById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('updateById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_reindexById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\App\AppService_reindexById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\App\AppService_reindexById_result();
+    try {
+      $result->success = $this->handler_->reindexById($args->identity);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'reindexById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('reindexById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+}
+

+ 1680 - 0
php/OpenSearch/Generated/App/Types.php

@@ -0,0 +1,1680 @@
+<?php
+namespace OpenSearch\Generated\App;
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+final class AppStatus {
+  const AVAILABLE = 1;
+  const PAUSE = 5;
+  const FORBID = 6;
+  const UNOPEN = 7;
+  const CREATING = 8;
+  const FAILED = 9;
+  static public $__names = array(
+    1 => 'AVAILABLE',
+    5 => 'PAUSE',
+    6 => 'FORBID',
+    7 => 'UNOPEN',
+    8 => 'CREATING',
+    9 => 'FAILED',
+  );
+}
+
+class Quota {
+  static $_TSPEC;
+
+  /**
+   * @var double
+   */
+  public $doc_size = null;
+  /**
+   * @var int
+   */
+  public $qps = null;
+  /**
+   * @var string
+   */
+  public $type = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'doc_size',
+          'type' => TType::DOUBLE,
+          ),
+        2 => array(
+          'var' => 'qps',
+          'type' => TType::I32,
+          ),
+        3 => array(
+          'var' => 'type',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['doc_size'])) {
+        $this->doc_size = $vals['doc_size'];
+      }
+      if (isset($vals['qps'])) {
+        $this->qps = $vals['qps'];
+      }
+      if (isset($vals['type'])) {
+        $this->type = $vals['type'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Quota';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::DOUBLE) {
+            $xfer += $input->readDouble($this->doc_size);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->qps);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->type);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Quota');
+    if ($this->doc_size !== null) {
+      $xfer += $output->writeFieldBegin('doc_size', TType::DOUBLE, 1);
+      $xfer += $output->writeDouble($this->doc_size);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->qps !== null) {
+      $xfer += $output->writeFieldBegin('qps', TType::I32, 2);
+      $xfer += $output->writeI32($this->qps);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->type !== null) {
+      $xfer += $output->writeFieldBegin('type', TType::STRING, 3);
+      $xfer += $output->writeString($this->type);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class Field {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $name = null;
+  /**
+   * @var string
+   */
+  public $type = null;
+  /**
+   * @var bool
+   */
+  public $primary_key = null;
+  /**
+   * @var string[]
+   */
+  public $join_with = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'name',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'type',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'primary_key',
+          'type' => TType::BOOL,
+          ),
+        4 => array(
+          'var' => 'join_with',
+          'type' => TType::LST,
+          'etype' => TType::STRING,
+          'elem' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['name'])) {
+        $this->name = $vals['name'];
+      }
+      if (isset($vals['type'])) {
+        $this->type = $vals['type'];
+      }
+      if (isset($vals['primary_key'])) {
+        $this->primary_key = $vals['primary_key'];
+      }
+      if (isset($vals['join_with'])) {
+        $this->join_with = $vals['join_with'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Field';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->name);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->type);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::BOOL) {
+            $xfer += $input->readBool($this->primary_key);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 4:
+          if ($ftype == TType::LST) {
+            $this->join_with = array();
+            $_size0 = 0;
+            $_etype3 = 0;
+            $xfer += $input->readListBegin($_etype3, $_size0);
+            for ($_i4 = 0; $_i4 < $_size0; ++$_i4)
+            {
+              $elem5 = null;
+              $xfer += $input->readString($elem5);
+              $this->join_with []= $elem5;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Field');
+    if ($this->name !== null) {
+      $xfer += $output->writeFieldBegin('name', TType::STRING, 1);
+      $xfer += $output->writeString($this->name);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->type !== null) {
+      $xfer += $output->writeFieldBegin('type', TType::STRING, 2);
+      $xfer += $output->writeString($this->type);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->primary_key !== null) {
+      $xfer += $output->writeFieldBegin('primary_key', TType::BOOL, 3);
+      $xfer += $output->writeBool($this->primary_key);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->join_with !== null) {
+      if (!is_array($this->join_with)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('join_with', TType::LST, 4);
+      {
+        $output->writeListBegin(TType::STRING, count($this->join_with));
+        {
+          foreach ($this->join_with as $iter6)
+          {
+            $xfer += $output->writeString($iter6);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class Table {
+  static $_TSPEC;
+
+  /**
+   * @var array
+   */
+  public $fields = null;
+  /**
+   * @var bool
+   */
+  public $primary_table = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'fields',
+          'type' => TType::MAP,
+          'ktype' => TType::STRING,
+          'vtype' => TType::STRUCT,
+          'key' => array(
+            'type' => TType::STRING,
+          ),
+          'val' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\App\Field',
+            ),
+          ),
+        2 => array(
+          'var' => 'primary_table',
+          'type' => TType::BOOL,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['fields'])) {
+        $this->fields = $vals['fields'];
+      }
+      if (isset($vals['primary_table'])) {
+        $this->primary_table = $vals['primary_table'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Table';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::MAP) {
+            $this->fields = array();
+            $_size7 = 0;
+            $_ktype8 = 0;
+            $_vtype9 = 0;
+            $xfer += $input->readMapBegin($_ktype8, $_vtype9, $_size7);
+            for ($_i11 = 0; $_i11 < $_size7; ++$_i11)
+            {
+              $key12 = '';
+              $val13 = new \OpenSearch\Generated\App\Field();
+              $xfer += $input->readString($key12);
+              $val13 = new \OpenSearch\Generated\App\Field();
+              $xfer += $val13->read($input);
+              $this->fields[$key12] = $val13;
+            }
+            $xfer += $input->readMapEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::BOOL) {
+            $xfer += $input->readBool($this->primary_table);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Table');
+    if ($this->fields !== null) {
+      if (!is_array($this->fields)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('fields', TType::MAP, 1);
+      {
+        $output->writeMapBegin(TType::STRING, TType::STRUCT, count($this->fields));
+        {
+          foreach ($this->fields as $kiter14 => $viter15)
+          {
+            $xfer += $output->writeString($kiter14);
+            $xfer += $viter15->write($output);
+          }
+        }
+        $output->writeMapEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->primary_table !== null) {
+      $xfer += $output->writeFieldBegin('primary_table', TType::BOOL, 2);
+      $xfer += $output->writeBool($this->primary_table);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SearchField {
+  static $_TSPEC;
+
+  /**
+   * @var string[]
+   */
+  public $fields = null;
+  /**
+   * @var string
+   */
+  public $analyzer = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'fields',
+          'type' => TType::LST,
+          'etype' => TType::STRING,
+          'elem' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        2 => array(
+          'var' => 'analyzer',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['fields'])) {
+        $this->fields = $vals['fields'];
+      }
+      if (isset($vals['analyzer'])) {
+        $this->analyzer = $vals['analyzer'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SearchField';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::LST) {
+            $this->fields = array();
+            $_size16 = 0;
+            $_etype19 = 0;
+            $xfer += $input->readListBegin($_etype19, $_size16);
+            for ($_i20 = 0; $_i20 < $_size16; ++$_i20)
+            {
+              $elem21 = null;
+              $xfer += $input->readString($elem21);
+              $this->fields []= $elem21;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->analyzer);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SearchField');
+    if ($this->fields !== null) {
+      if (!is_array($this->fields)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('fields', TType::LST, 1);
+      {
+        $output->writeListBegin(TType::STRING, count($this->fields));
+        {
+          foreach ($this->fields as $iter22)
+          {
+            $xfer += $output->writeString($iter22);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->analyzer !== null) {
+      $xfer += $output->writeFieldBegin('analyzer', TType::STRING, 2);
+      $xfer += $output->writeString($this->analyzer);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class Indexes {
+  static $_TSPEC;
+
+  /**
+   * @var array
+   */
+  public $search_fields = null;
+  /**
+   * @var string[]
+   */
+  public $filter_fields = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'search_fields',
+          'type' => TType::MAP,
+          'ktype' => TType::STRING,
+          'vtype' => TType::STRUCT,
+          'key' => array(
+            'type' => TType::STRING,
+          ),
+          'val' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\App\SearchField',
+            ),
+          ),
+        2 => array(
+          'var' => 'filter_fields',
+          'type' => TType::LST,
+          'etype' => TType::STRING,
+          'elem' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['search_fields'])) {
+        $this->search_fields = $vals['search_fields'];
+      }
+      if (isset($vals['filter_fields'])) {
+        $this->filter_fields = $vals['filter_fields'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Indexes';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::MAP) {
+            $this->search_fields = array();
+            $_size23 = 0;
+            $_ktype24 = 0;
+            $_vtype25 = 0;
+            $xfer += $input->readMapBegin($_ktype24, $_vtype25, $_size23);
+            for ($_i27 = 0; $_i27 < $_size23; ++$_i27)
+            {
+              $key28 = '';
+              $val29 = new \OpenSearch\Generated\App\SearchField();
+              $xfer += $input->readString($key28);
+              $val29 = new \OpenSearch\Generated\App\SearchField();
+              $xfer += $val29->read($input);
+              $this->search_fields[$key28] = $val29;
+            }
+            $xfer += $input->readMapEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::LST) {
+            $this->filter_fields = array();
+            $_size30 = 0;
+            $_etype33 = 0;
+            $xfer += $input->readListBegin($_etype33, $_size30);
+            for ($_i34 = 0; $_i34 < $_size30; ++$_i34)
+            {
+              $elem35 = null;
+              $xfer += $input->readString($elem35);
+              $this->filter_fields []= $elem35;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Indexes');
+    if ($this->search_fields !== null) {
+      if (!is_array($this->search_fields)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('search_fields', TType::MAP, 1);
+      {
+        $output->writeMapBegin(TType::STRING, TType::STRUCT, count($this->search_fields));
+        {
+          foreach ($this->search_fields as $kiter36 => $viter37)
+          {
+            $xfer += $output->writeString($kiter36);
+            $xfer += $viter37->write($output);
+          }
+        }
+        $output->writeMapEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->filter_fields !== null) {
+      if (!is_array($this->filter_fields)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('filter_fields', TType::LST, 2);
+      {
+        $output->writeListBegin(TType::STRING, count($this->filter_fields));
+        {
+          foreach ($this->filter_fields as $iter38)
+          {
+            $xfer += $output->writeString($iter38);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class Schema {
+  static $_TSPEC;
+
+  /**
+   * @var array
+   */
+  public $tables = null;
+  /**
+   * @var \OpenSearch\Generated\App\Indexes
+   */
+  public $indexes = null;
+  /**
+   * @var string
+   */
+  public $route_field = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'tables',
+          'type' => TType::MAP,
+          'ktype' => TType::STRING,
+          'vtype' => TType::STRUCT,
+          'key' => array(
+            'type' => TType::STRING,
+          ),
+          'val' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\App\Table',
+            ),
+          ),
+        2 => array(
+          'var' => 'indexes',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\App\Indexes',
+          ),
+        3 => array(
+          'var' => 'route_field',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['tables'])) {
+        $this->tables = $vals['tables'];
+      }
+      if (isset($vals['indexes'])) {
+        $this->indexes = $vals['indexes'];
+      }
+      if (isset($vals['route_field'])) {
+        $this->route_field = $vals['route_field'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Schema';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::MAP) {
+            $this->tables = array();
+            $_size39 = 0;
+            $_ktype40 = 0;
+            $_vtype41 = 0;
+            $xfer += $input->readMapBegin($_ktype40, $_vtype41, $_size39);
+            for ($_i43 = 0; $_i43 < $_size39; ++$_i43)
+            {
+              $key44 = '';
+              $val45 = new \OpenSearch\Generated\App\Table();
+              $xfer += $input->readString($key44);
+              $val45 = new \OpenSearch\Generated\App\Table();
+              $xfer += $val45->read($input);
+              $this->tables[$key44] = $val45;
+            }
+            $xfer += $input->readMapEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->indexes = new \OpenSearch\Generated\App\Indexes();
+            $xfer += $this->indexes->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->route_field);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Schema');
+    if ($this->tables !== null) {
+      if (!is_array($this->tables)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('tables', TType::MAP, 1);
+      {
+        $output->writeMapBegin(TType::STRING, TType::STRUCT, count($this->tables));
+        {
+          foreach ($this->tables as $kiter46 => $viter47)
+          {
+            $xfer += $output->writeString($kiter46);
+            $xfer += $viter47->write($output);
+          }
+        }
+        $output->writeMapEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->indexes !== null) {
+      if (!is_object($this->indexes)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('indexes', TType::STRUCT, 2);
+      $xfer += $this->indexes->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->route_field !== null) {
+      $xfer += $output->writeFieldBegin('route_field', TType::STRING, 3);
+      $xfer += $output->writeString($this->route_field);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class Group {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $type = "advance";
+  /**
+   * @var string
+   */
+  public $current_version = null;
+  /**
+   * @var string[]
+   */
+  public $versions = null;
+  /**
+   * @var int
+   */
+  public $switch_time = null;
+  /**
+   * @var string
+   */
+  public $id = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'type',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'current_version',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'versions',
+          'type' => TType::LST,
+          'etype' => TType::STRING,
+          'elem' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        4 => array(
+          'var' => 'switch_time',
+          'type' => TType::I32,
+          ),
+        5 => array(
+          'var' => 'id',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['type'])) {
+        $this->type = $vals['type'];
+      }
+      if (isset($vals['current_version'])) {
+        $this->current_version = $vals['current_version'];
+      }
+      if (isset($vals['versions'])) {
+        $this->versions = $vals['versions'];
+      }
+      if (isset($vals['switch_time'])) {
+        $this->switch_time = $vals['switch_time'];
+      }
+      if (isset($vals['id'])) {
+        $this->id = $vals['id'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Group';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->type);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->current_version);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::LST) {
+            $this->versions = array();
+            $_size48 = 0;
+            $_etype51 = 0;
+            $xfer += $input->readListBegin($_etype51, $_size48);
+            for ($_i52 = 0; $_i52 < $_size48; ++$_i52)
+            {
+              $elem53 = null;
+              $xfer += $input->readString($elem53);
+              $this->versions []= $elem53;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 4:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->switch_time);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 5:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->id);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Group');
+    if ($this->type !== null) {
+      $xfer += $output->writeFieldBegin('type', TType::STRING, 1);
+      $xfer += $output->writeString($this->type);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->current_version !== null) {
+      $xfer += $output->writeFieldBegin('current_version', TType::STRING, 2);
+      $xfer += $output->writeString($this->current_version);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->versions !== null) {
+      if (!is_array($this->versions)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('versions', TType::LST, 3);
+      {
+        $output->writeListBegin(TType::STRING, count($this->versions));
+        {
+          foreach ($this->versions as $iter54)
+          {
+            $xfer += $output->writeString($iter54);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->switch_time !== null) {
+      $xfer += $output->writeFieldBegin('switch_time', TType::I32, 4);
+      $xfer += $output->writeI32($this->switch_time);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->id !== null) {
+      $xfer += $output->writeFieldBegin('id', TType::STRING, 5);
+      $xfer += $output->writeString($this->id);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class App {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $id = null;
+  /**
+   * @var string
+   */
+  public $name = null;
+  /**
+   * @var string
+   */
+  public $type = "advance";
+  /**
+   * @var \OpenSearch\Generated\App\Schema
+   */
+  public $schema = null;
+  /**
+   * @var \OpenSearch\Generated\App\Quota
+   */
+  public $quota = null;
+  /**
+   * @var string
+   */
+  public $description = null;
+  /**
+   * @var \OpenSearch\Generated\App\Group
+   */
+  public $group = null;
+  /**
+   * @var bool
+   */
+  public $auto_switch = null;
+  /**
+   * @var int
+   */
+  public $switch_time = null;
+  /**
+   * @var string[]
+   */
+  public $fetch_fields = null;
+  /**
+   * @var array
+   */
+  public $first_ranks = null;
+  /**
+   * @var string
+   */
+  public $virtual_cluster = null;
+  /**
+   * @var bool
+   */
+  public $realtime_shared = null;
+  /**
+   * @var int
+   */
+  public $status = null;
+  /**
+   * @var int
+   */
+  public $data_progress = null;
+  /**
+   * @var int
+   */
+  public $progress_percent = null;
+  /**
+   * @var bool
+   */
+  public $rebuilding = null;
+  /**
+   * @var int
+   */
+  public $unread_error_count = null;
+  /**
+   * @var int
+   */
+  public $action_cause = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'id',
+          'type' => TType::STRING,
+          ),
+        10 => array(
+          'var' => 'name',
+          'type' => TType::STRING,
+          ),
+        11 => array(
+          'var' => 'type',
+          'type' => TType::STRING,
+          ),
+        12 => array(
+          'var' => 'schema',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\App\Schema',
+          ),
+        13 => array(
+          'var' => 'quota',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\App\Quota',
+          ),
+        14 => array(
+          'var' => 'description',
+          'type' => TType::STRING,
+          ),
+        15 => array(
+          'var' => 'group',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\App\Group',
+          ),
+        16 => array(
+          'var' => 'auto_switch',
+          'type' => TType::BOOL,
+          ),
+        17 => array(
+          'var' => 'switch_time',
+          'type' => TType::I32,
+          ),
+        18 => array(
+          'var' => 'fetch_fields',
+          'type' => TType::LST,
+          'etype' => TType::STRING,
+          'elem' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        19 => array(
+          'var' => 'first_ranks',
+          'type' => TType::MAP,
+          'ktype' => TType::STRING,
+          'vtype' => TType::STRUCT,
+          'key' => array(
+            'type' => TType::STRING,
+          ),
+          'val' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+            ),
+          ),
+        20 => array(
+          'var' => 'virtual_cluster',
+          'type' => TType::STRING,
+          ),
+        21 => array(
+          'var' => 'realtime_shared',
+          'type' => TType::BOOL,
+          ),
+        100 => array(
+          'var' => 'status',
+          'type' => TType::I32,
+          ),
+        101 => array(
+          'var' => 'data_progress',
+          'type' => TType::I32,
+          ),
+        102 => array(
+          'var' => 'progress_percent',
+          'type' => TType::I32,
+          ),
+        103 => array(
+          'var' => 'rebuilding',
+          'type' => TType::BOOL,
+          ),
+        104 => array(
+          'var' => 'unread_error_count',
+          'type' => TType::I32,
+          ),
+        105 => array(
+          'var' => 'action_cause',
+          'type' => TType::I32,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['id'])) {
+        $this->id = $vals['id'];
+      }
+      if (isset($vals['name'])) {
+        $this->name = $vals['name'];
+      }
+      if (isset($vals['type'])) {
+        $this->type = $vals['type'];
+      }
+      if (isset($vals['schema'])) {
+        $this->schema = $vals['schema'];
+      }
+      if (isset($vals['quota'])) {
+        $this->quota = $vals['quota'];
+      }
+      if (isset($vals['description'])) {
+        $this->description = $vals['description'];
+      }
+      if (isset($vals['group'])) {
+        $this->group = $vals['group'];
+      }
+      if (isset($vals['auto_switch'])) {
+        $this->auto_switch = $vals['auto_switch'];
+      }
+      if (isset($vals['switch_time'])) {
+        $this->switch_time = $vals['switch_time'];
+      }
+      if (isset($vals['fetch_fields'])) {
+        $this->fetch_fields = $vals['fetch_fields'];
+      }
+      if (isset($vals['first_ranks'])) {
+        $this->first_ranks = $vals['first_ranks'];
+      }
+      if (isset($vals['virtual_cluster'])) {
+        $this->virtual_cluster = $vals['virtual_cluster'];
+      }
+      if (isset($vals['realtime_shared'])) {
+        $this->realtime_shared = $vals['realtime_shared'];
+      }
+      if (isset($vals['status'])) {
+        $this->status = $vals['status'];
+      }
+      if (isset($vals['data_progress'])) {
+        $this->data_progress = $vals['data_progress'];
+      }
+      if (isset($vals['progress_percent'])) {
+        $this->progress_percent = $vals['progress_percent'];
+      }
+      if (isset($vals['rebuilding'])) {
+        $this->rebuilding = $vals['rebuilding'];
+      }
+      if (isset($vals['unread_error_count'])) {
+        $this->unread_error_count = $vals['unread_error_count'];
+      }
+      if (isset($vals['action_cause'])) {
+        $this->action_cause = $vals['action_cause'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'App';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->id);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 10:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->name);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 11:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->type);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 12:
+          if ($ftype == TType::STRUCT) {
+            $this->schema = new \OpenSearch\Generated\App\Schema();
+            $xfer += $this->schema->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 13:
+          if ($ftype == TType::STRUCT) {
+            $this->quota = new \OpenSearch\Generated\App\Quota();
+            $xfer += $this->quota->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 14:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->description);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 15:
+          if ($ftype == TType::STRUCT) {
+            $this->group = new \OpenSearch\Generated\App\Group();
+            $xfer += $this->group->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 16:
+          if ($ftype == TType::BOOL) {
+            $xfer += $input->readBool($this->auto_switch);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 17:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->switch_time);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 18:
+          if ($ftype == TType::LST) {
+            $this->fetch_fields = array();
+            $_size55 = 0;
+            $_etype58 = 0;
+            $xfer += $input->readListBegin($_etype58, $_size55);
+            for ($_i59 = 0; $_i59 < $_size55; ++$_i59)
+            {
+              $elem60 = null;
+              $xfer += $input->readString($elem60);
+              $this->fetch_fields []= $elem60;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 19:
+          if ($ftype == TType::MAP) {
+            $this->first_ranks = array();
+            $_size61 = 0;
+            $_ktype62 = 0;
+            $_vtype63 = 0;
+            $xfer += $input->readMapBegin($_ktype62, $_vtype63, $_size61);
+            for ($_i65 = 0; $_i65 < $_size61; ++$_i65)
+            {
+              $key66 = '';
+              $val67 = new \OpenSearch\Generated\FirstRank\FirstRank();
+              $xfer += $input->readString($key66);
+              $val67 = new \OpenSearch\Generated\FirstRank\FirstRank();
+              $xfer += $val67->read($input);
+              $this->first_ranks[$key66] = $val67;
+            }
+            $xfer += $input->readMapEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 20:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->virtual_cluster);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 21:
+          if ($ftype == TType::BOOL) {
+            $xfer += $input->readBool($this->realtime_shared);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 100:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->status);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 101:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->data_progress);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 102:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->progress_percent);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 103:
+          if ($ftype == TType::BOOL) {
+            $xfer += $input->readBool($this->rebuilding);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 104:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->unread_error_count);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 105:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->action_cause);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('App');
+    if ($this->id !== null) {
+      $xfer += $output->writeFieldBegin('id', TType::STRING, 1);
+      $xfer += $output->writeString($this->id);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->name !== null) {
+      $xfer += $output->writeFieldBegin('name', TType::STRING, 10);
+      $xfer += $output->writeString($this->name);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->type !== null) {
+      $xfer += $output->writeFieldBegin('type', TType::STRING, 11);
+      $xfer += $output->writeString($this->type);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->schema !== null) {
+      if (!is_object($this->schema)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('schema', TType::STRUCT, 12);
+      $xfer += $this->schema->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->quota !== null) {
+      if (!is_object($this->quota)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('quota', TType::STRUCT, 13);
+      $xfer += $this->quota->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->description !== null) {
+      $xfer += $output->writeFieldBegin('description', TType::STRING, 14);
+      $xfer += $output->writeString($this->description);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->group !== null) {
+      if (!is_object($this->group)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('group', TType::STRUCT, 15);
+      $xfer += $this->group->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->auto_switch !== null) {
+      $xfer += $output->writeFieldBegin('auto_switch', TType::BOOL, 16);
+      $xfer += $output->writeBool($this->auto_switch);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->switch_time !== null) {
+      $xfer += $output->writeFieldBegin('switch_time', TType::I32, 17);
+      $xfer += $output->writeI32($this->switch_time);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->fetch_fields !== null) {
+      if (!is_array($this->fetch_fields)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('fetch_fields', TType::LST, 18);
+      {
+        $output->writeListBegin(TType::STRING, count($this->fetch_fields));
+        {
+          foreach ($this->fetch_fields as $iter68)
+          {
+            $xfer += $output->writeString($iter68);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->first_ranks !== null) {
+      if (!is_array($this->first_ranks)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('first_ranks', TType::MAP, 19);
+      {
+        $output->writeMapBegin(TType::STRING, TType::STRUCT, count($this->first_ranks));
+        {
+          foreach ($this->first_ranks as $kiter69 => $viter70)
+          {
+            $xfer += $output->writeString($kiter69);
+            $xfer += $viter70->write($output);
+          }
+        }
+        $output->writeMapEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->virtual_cluster !== null) {
+      $xfer += $output->writeFieldBegin('virtual_cluster', TType::STRING, 20);
+      $xfer += $output->writeString($this->virtual_cluster);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->realtime_shared !== null) {
+      $xfer += $output->writeFieldBegin('realtime_shared', TType::BOOL, 21);
+      $xfer += $output->writeBool($this->realtime_shared);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->status !== null) {
+      $xfer += $output->writeFieldBegin('status', TType::I32, 100);
+      $xfer += $output->writeI32($this->status);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->data_progress !== null) {
+      $xfer += $output->writeFieldBegin('data_progress', TType::I32, 101);
+      $xfer += $output->writeI32($this->data_progress);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->progress_percent !== null) {
+      $xfer += $output->writeFieldBegin('progress_percent', TType::I32, 102);
+      $xfer += $output->writeI32($this->progress_percent);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->rebuilding !== null) {
+      $xfer += $output->writeFieldBegin('rebuilding', TType::BOOL, 103);
+      $xfer += $output->writeBool($this->rebuilding);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->unread_error_count !== null) {
+      $xfer += $output->writeFieldBegin('unread_error_count', TType::I32, 104);
+      $xfer += $output->writeI32($this->unread_error_count);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->action_cause !== null) {
+      $xfer += $output->writeFieldBegin('action_cause', TType::I32, 105);
+      $xfer += $output->writeI32($this->action_cause);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+final class Constant extends \Thrift\Type\TConstant {
+  static protected $TYPE_STANDARD;
+  static protected $TYPE_ADVANCE;
+
+  static protected function init_TYPE_STANDARD() {
+    return "standard";
+  }
+
+  static protected function init_TYPE_ADVANCE() {
+    return "advance";
+  }
+}
+
+

+ 356 - 0
php/OpenSearch/Generated/BehaviorCollection/BehaviorCollectionService.php

@@ -0,0 +1,356 @@
+<?php
+namespace OpenSearch\Generated\BehaviorCollection;
+/**
+ * Autogenerated by Thrift Compiler (0.9.3)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+interface BehaviorCollectionServiceIf {
+  /**
+   * @param string $recordsJson
+   * @param string $searchAppName
+   * @param string $behaviorCollectionName
+   * @return \OpenSearch\Generated\Common\OpenSearchResult
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function push($recordsJson, $searchAppName, $behaviorCollectionName);
+}
+
+class BehaviorCollectionServiceClient implements \OpenSearch\Generated\BehaviorCollection\BehaviorCollectionServiceIf {
+  protected $input_ = null;
+  protected $output_ = null;
+
+  protected $seqid_ = 0;
+
+  public function __construct($input, $output=null) {
+    $this->input_ = $input;
+    $this->output_ = $output ? $output : $input;
+  }
+
+  public function push($recordsJson, $searchAppName, $behaviorCollectionName)
+  {
+    $this->send_push($recordsJson, $searchAppName, $behaviorCollectionName);
+    return $this->recv_push();
+  }
+
+  public function send_push($recordsJson, $searchAppName, $behaviorCollectionName)
+  {
+    $args = new \BehaviorCollectionService_push_args();
+    $args->recordsJson = $recordsJson;
+    $args->searchAppName = $searchAppName;
+    $args->behaviorCollectionName = $behaviorCollectionName;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'push', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('push', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_push()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\BehaviorCollectionService_push_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \BehaviorCollectionService_push_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("push failed: unknown result");
+  }
+
+}
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+class BehaviorCollectionService_push_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $recordsJson = null;
+  /**
+   * @var string
+   */
+  public $searchAppName = null;
+  /**
+   * @var string
+   */
+  public $behaviorCollectionName = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'recordsJson',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'searchAppName',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'behaviorCollectionName',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['recordsJson'])) {
+        $this->recordsJson = $vals['recordsJson'];
+      }
+      if (isset($vals['searchAppName'])) {
+        $this->searchAppName = $vals['searchAppName'];
+      }
+      if (isset($vals['behaviorCollectionName'])) {
+        $this->behaviorCollectionName = $vals['behaviorCollectionName'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'BehaviorCollectionService_push_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->recordsJson);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->searchAppName);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->behaviorCollectionName);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('BehaviorCollectionService_push_args');
+    if ($this->recordsJson !== null) {
+      $xfer += $output->writeFieldBegin('recordsJson', TType::STRING, 1);
+      $xfer += $output->writeString($this->recordsJson);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->searchAppName !== null) {
+      $xfer += $output->writeFieldBegin('searchAppName', TType::STRING, 2);
+      $xfer += $output->writeString($this->searchAppName);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->behaviorCollectionName !== null) {
+      $xfer += $output->writeFieldBegin('behaviorCollectionName', TType::STRING, 3);
+      $xfer += $output->writeString($this->behaviorCollectionName);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class BehaviorCollectionService_push_result {
+  static $_TSPEC;
+
+  /**
+   * @var \Generated\Common\OpenSearchResult
+   */
+  public $success = null;
+  /**
+   * @var \Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\Generated\Common\OpenSearchResult',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'BehaviorCollectionService_push_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \Generated\Common\OpenSearchResult();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('BehaviorCollectionService_push_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+

+ 39 - 0
php/OpenSearch/Generated/BehaviorCollection/Types.php

@@ -0,0 +1,39 @@
+<?php
+namespace OpenSearch\Generated\BehaviorCollection;
+/**
+ * Autogenerated by Thrift Compiler (0.9.3)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+final class Command {
+  const ADD = 0;
+  static public $__names = array(
+    0 => 'ADD',
+  );
+}
+
+final class Constant extends \Thrift\Type\TConstant {
+  static protected $DOC_KEY_CMD;
+  static protected $DOC_KEY_FIELDS;
+
+  static protected function init_DOC_KEY_CMD() {
+    return "cmd";
+  }
+
+  static protected function init_DOC_KEY_FIELDS() {
+    return "fields";
+  }
+}
+
+

+ 588 - 0
php/OpenSearch/Generated/Common/Types.php

@@ -0,0 +1,588 @@
+<?php
+namespace OpenSearch\Generated\Common;
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+class Pageable {
+  static $_TSPEC;
+
+  /**
+   * @var int
+   */
+  public $page = null;
+  /**
+   * @var int
+   */
+  public $size = null;
+  /**
+   * @var int
+   */
+  public $start = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        10 => array(
+          'var' => 'page',
+          'type' => TType::I32,
+          ),
+        11 => array(
+          'var' => 'size',
+          'type' => TType::I32,
+          ),
+        12 => array(
+          'var' => 'start',
+          'type' => TType::I32,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['page'])) {
+        $this->page = $vals['page'];
+      }
+      if (isset($vals['size'])) {
+        $this->size = $vals['size'];
+      }
+      if (isset($vals['start'])) {
+        $this->start = $vals['start'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Pageable';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 10:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->page);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 11:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->size);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 12:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->start);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Pageable');
+    if ($this->page !== null) {
+      $xfer += $output->writeFieldBegin('page', TType::I32, 10);
+      $xfer += $output->writeI32($this->page);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->size !== null) {
+      $xfer += $output->writeFieldBegin('size', TType::I32, 11);
+      $xfer += $output->writeI32($this->size);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->start !== null) {
+      $xfer += $output->writeFieldBegin('start', TType::I32, 12);
+      $xfer += $output->writeI32($this->start);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class AppReference {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $id = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'id',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['id'])) {
+        $this->id = $vals['id'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'AppReference';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->id);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('AppReference');
+    if ($this->id !== null) {
+      $xfer += $output->writeFieldBegin('id', TType::STRING, 1);
+      $xfer += $output->writeString($this->id);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class TraceInfo {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $requestId = null;
+  /**
+   * @var string
+   */
+  public $tracer = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'requestId',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'tracer',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['requestId'])) {
+        $this->requestId = $vals['requestId'];
+      }
+      if (isset($vals['tracer'])) {
+        $this->tracer = $vals['tracer'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'TraceInfo';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->requestId);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->tracer);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('TraceInfo');
+    if ($this->requestId !== null) {
+      $xfer += $output->writeFieldBegin('requestId', TType::STRING, 1);
+      $xfer += $output->writeString($this->requestId);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->tracer !== null) {
+      $xfer += $output->writeFieldBegin('tracer', TType::STRING, 3);
+      $xfer += $output->writeString($this->tracer);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class OpenSearchResult {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $result = null;
+  /**
+   * @var \OpenSearch\Generated\Common\TraceInfo
+   */
+  public $traceInfo = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'result',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'traceInfo',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\TraceInfo',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['result'])) {
+        $this->result = $vals['result'];
+      }
+      if (isset($vals['traceInfo'])) {
+        $this->traceInfo = $vals['traceInfo'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'OpenSearchResult';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->result);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRUCT) {
+            $this->traceInfo = new \OpenSearch\Generated\Common\TraceInfo();
+            $xfer += $this->traceInfo->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('OpenSearchResult');
+    if ($this->result !== null) {
+      $xfer += $output->writeFieldBegin('result', TType::STRING, 1);
+      $xfer += $output->writeString($this->result);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->traceInfo !== null) {
+      if (!is_object($this->traceInfo)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('traceInfo', TType::STRUCT, 3);
+      $xfer += $this->traceInfo->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class OpenSearchException extends TException {
+  static $_TSPEC;
+
+  /**
+   * @var int
+   */
+  public $code = null;
+  /**
+   * @var string
+   */
+  public $message = null;
+  /**
+   * @var string
+   */
+  public $requestId = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'code',
+          'type' => TType::I32,
+          ),
+        2 => array(
+          'var' => 'message',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'requestId',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['code'])) {
+        $this->code = $vals['code'];
+      }
+      if (isset($vals['message'])) {
+        $this->message = $vals['message'];
+      }
+      if (isset($vals['requestId'])) {
+        $this->requestId = $vals['requestId'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'OpenSearchException';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->code);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->message);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->requestId);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('OpenSearchException');
+    if ($this->code !== null) {
+      $xfer += $output->writeFieldBegin('code', TType::I32, 1);
+      $xfer += $output->writeI32($this->code);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->message !== null) {
+      $xfer += $output->writeFieldBegin('message', TType::STRING, 2);
+      $xfer += $output->writeString($this->message);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->requestId !== null) {
+      $xfer += $output->writeFieldBegin('requestId', TType::STRING, 3);
+      $xfer += $output->writeString($this->requestId);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class OpenSearchClientException extends TException {
+  static $_TSPEC;
+
+
+  public function __construct() {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        );
+    }
+  }
+
+  public function getName() {
+    return 'OpenSearchClientException';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('OpenSearchClientException');
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+

+ 411 - 0
php/OpenSearch/Generated/Document/DocumentService.php

@@ -0,0 +1,411 @@
+<?php
+namespace OpenSearch\Generated\Document;
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+interface DocumentServiceIf {
+  /**
+   * @param string $docsJson
+   * @param string $appName
+   * @param string $tableName
+   * @return \OpenSearch\Generated\Common\OpenSearchResult
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function push($docsJson, $appName, $tableName);
+}
+
+
+class DocumentServiceClient implements \OpenSearch\Generated\Document\DocumentServiceIf {
+  protected $input_ = null;
+  protected $output_ = null;
+
+  protected $seqid_ = 0;
+
+  public function __construct($input, $output=null) {
+    $this->input_ = $input;
+    $this->output_ = $output ? $output : $input;
+  }
+
+  public function push($docsJson, $appName, $tableName)
+  {
+    $this->send_push($docsJson, $appName, $tableName);
+    return $this->recv_push();
+  }
+
+  public function send_push($docsJson, $appName, $tableName)
+  {
+    $args = new \OpenSearch\Generated\Document\DocumentService_push_args();
+    $args->docsJson = $docsJson;
+    $args->appName = $appName;
+    $args->tableName = $tableName;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'push', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('push', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_push()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\Document\DocumentService_push_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\Document\DocumentService_push_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("push failed: unknown result");
+  }
+
+}
+
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+class DocumentService_push_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $docsJson = null;
+  /**
+   * @var string
+   */
+  public $appName = null;
+  /**
+   * @var string
+   */
+  public $tableName = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'docsJson',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'appName',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'tableName',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['docsJson'])) {
+        $this->docsJson = $vals['docsJson'];
+      }
+      if (isset($vals['appName'])) {
+        $this->appName = $vals['appName'];
+      }
+      if (isset($vals['tableName'])) {
+        $this->tableName = $vals['tableName'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'DocumentService_push_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->docsJson);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->appName);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->tableName);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('DocumentService_push_args');
+    if ($this->docsJson !== null) {
+      $xfer += $output->writeFieldBegin('docsJson', TType::STRING, 1);
+      $xfer += $output->writeString($this->docsJson);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->appName !== null) {
+      $xfer += $output->writeFieldBegin('appName', TType::STRING, 2);
+      $xfer += $output->writeString($this->appName);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->tableName !== null) {
+      $xfer += $output->writeFieldBegin('tableName', TType::STRING, 3);
+      $xfer += $output->writeString($this->tableName);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class DocumentService_push_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchResult
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchResult',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'DocumentService_push_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\Common\OpenSearchResult();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('DocumentService_push_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class DocumentServiceProcessor {
+  protected $handler_ = null;
+  public function __construct($handler) {
+    $this->handler_ = $handler;
+  }
+
+  public function process($input, $output) {
+    $rseqid = 0;
+    $fname = null;
+    $mtype = 0;
+
+    $input->readMessageBegin($fname, $mtype, $rseqid);
+    $methodname = 'process_'.$fname;
+    if (!method_exists($this, $methodname)) {
+      $input->skip(TType::STRUCT);
+      $input->readMessageEnd();
+      $x = new TApplicationException('Function '.$fname.' not implemented.', TApplicationException::UNKNOWN_METHOD);
+      $output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid);
+      $x->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+      return;
+    }
+    $this->$methodname($rseqid, $input, $output);
+    return true;
+  }
+
+  protected function process_push($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\Document\DocumentService_push_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\Document\DocumentService_push_result();
+    try {
+      $result->success = $this->handler_->push($args->docsJson, $args->appName, $args->tableName);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'push', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('push', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+}
+

+ 44 - 0
php/OpenSearch/Generated/Document/Types.php

@@ -0,0 +1,44 @@
+<?php
+namespace OpenSearch\Generated\Document;
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+final class Command {
+  const ADD = 0;
+  const DELETE = 1;
+  const UPDATE = 2;
+  static public $__names = array(
+    0 => 'ADD',
+    1 => 'DELETE',
+    2 => 'UPDATE',
+  );
+}
+
+final class Constant extends \Thrift\Type\TConstant {
+  static protected $DOC_KEY_CMD;
+  static protected $DOC_KEY_FIELDS;
+
+  static protected function init_DOC_KEY_CMD() {
+    return "cmd";
+  }
+
+  static protected function init_DOC_KEY_FIELDS() {
+    return "fields";
+  }
+}
+
+

+ 2551 - 0
php/OpenSearch/Generated/FirstRank/FirstRankService.php

@@ -0,0 +1,2551 @@
+<?php
+namespace OpenSearch\Generated\FirstRank;
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+interface FirstRankServiceIf {
+  /**
+   * @param \OpenSearch\Generated\FirstRank\FirstRank $firstRank
+   * @return \OpenSearch\Generated\FirstRank\FirstRank
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function save(\OpenSearch\Generated\FirstRank\FirstRank $firstRank);
+  /**
+   * @param string $identity
+   * @return \OpenSearch\Generated\FirstRank\FirstRank
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function getById($identity);
+  /**
+   * @return \OpenSearch\Generated\FirstRank\FirstRank[]
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function listAll();
+  /**
+   * @param string $appId
+   * @return \OpenSearch\Generated\FirstRank\FirstRank[]
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function listByAppId($appId);
+  /**
+   * @param string $appId
+   * @param string $name
+   * @return \OpenSearch\Generated\FirstRank\FirstRank[]
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function listByAppIdAndName($appId, $name);
+  /**
+   * @param string $identity
+   * @param \OpenSearch\Generated\FirstRank\FirstRank $firstRank
+   * @return \OpenSearch\Generated\FirstRank\FirstRank
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function updateById($identity, \OpenSearch\Generated\FirstRank\FirstRank $firstRank);
+  /**
+   * @param string $identity
+   * @param \OpenSearch\Generated\FirstRank\FirstRank $firstRank
+   * @return \OpenSearch\Generated\FirstRank\FirstRank
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function validateUpdateById($identity, \OpenSearch\Generated\FirstRank\FirstRank $firstRank);
+  /**
+   * @param string $identity
+   * @return \OpenSearch\Generated\FirstRank\FirstRank
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function removeById($identity);
+}
+
+
+class FirstRankServiceClient implements \OpenSearch\Generated\FirstRank\FirstRankServiceIf {
+  protected $input_ = null;
+  protected $output_ = null;
+
+  protected $seqid_ = 0;
+
+  public function __construct($input, $output=null) {
+    $this->input_ = $input;
+    $this->output_ = $output ? $output : $input;
+  }
+
+  public function save(\OpenSearch\Generated\FirstRank\FirstRank $firstRank)
+  {
+    $this->send_save($firstRank);
+    return $this->recv_save();
+  }
+
+  public function send_save(\OpenSearch\Generated\FirstRank\FirstRank $firstRank)
+  {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_save_args();
+    $args->firstRank = $firstRank;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'save', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('save', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_save()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\FirstRank\FirstRankService_save_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\FirstRank\FirstRankService_save_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("save failed: unknown result");
+  }
+
+  public function getById($identity)
+  {
+    $this->send_getById($identity);
+    return $this->recv_getById();
+  }
+
+  public function send_getById($identity)
+  {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_getById_args();
+    $args->identity = $identity;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'getById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('getById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_getById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\FirstRank\FirstRankService_getById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\FirstRank\FirstRankService_getById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("getById failed: unknown result");
+  }
+
+  public function listAll()
+  {
+    $this->send_listAll();
+    return $this->recv_listAll();
+  }
+
+  public function send_listAll()
+  {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_listAll_args();
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'listAll', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('listAll', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_listAll()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\FirstRank\FirstRankService_listAll_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\FirstRank\FirstRankService_listAll_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("listAll failed: unknown result");
+  }
+
+  public function listByAppId($appId)
+  {
+    $this->send_listByAppId($appId);
+    return $this->recv_listByAppId();
+  }
+
+  public function send_listByAppId($appId)
+  {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_listByAppId_args();
+    $args->appId = $appId;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'listByAppId', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('listByAppId', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_listByAppId()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\FirstRank\FirstRankService_listByAppId_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\FirstRank\FirstRankService_listByAppId_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("listByAppId failed: unknown result");
+  }
+
+  public function listByAppIdAndName($appId, $name)
+  {
+    $this->send_listByAppIdAndName($appId, $name);
+    return $this->recv_listByAppIdAndName();
+  }
+
+  public function send_listByAppIdAndName($appId, $name)
+  {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_listByAppIdAndName_args();
+    $args->appId = $appId;
+    $args->name = $name;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'listByAppIdAndName', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('listByAppIdAndName', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_listByAppIdAndName()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\FirstRank\FirstRankService_listByAppIdAndName_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\FirstRank\FirstRankService_listByAppIdAndName_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("listByAppIdAndName failed: unknown result");
+  }
+
+  public function updateById($identity, \OpenSearch\Generated\FirstRank\FirstRank $firstRank)
+  {
+    $this->send_updateById($identity, $firstRank);
+    return $this->recv_updateById();
+  }
+
+  public function send_updateById($identity, \OpenSearch\Generated\FirstRank\FirstRank $firstRank)
+  {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_updateById_args();
+    $args->identity = $identity;
+    $args->firstRank = $firstRank;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'updateById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('updateById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_updateById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\FirstRank\FirstRankService_updateById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\FirstRank\FirstRankService_updateById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("updateById failed: unknown result");
+  }
+
+  public function validateUpdateById($identity, \OpenSearch\Generated\FirstRank\FirstRank $firstRank)
+  {
+    $this->send_validateUpdateById($identity, $firstRank);
+    return $this->recv_validateUpdateById();
+  }
+
+  public function send_validateUpdateById($identity, \OpenSearch\Generated\FirstRank\FirstRank $firstRank)
+  {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_validateUpdateById_args();
+    $args->identity = $identity;
+    $args->firstRank = $firstRank;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'validateUpdateById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('validateUpdateById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_validateUpdateById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\FirstRank\FirstRankService_validateUpdateById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\FirstRank\FirstRankService_validateUpdateById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("validateUpdateById failed: unknown result");
+  }
+
+  public function removeById($identity)
+  {
+    $this->send_removeById($identity);
+    return $this->recv_removeById();
+  }
+
+  public function send_removeById($identity)
+  {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_removeById_args();
+    $args->identity = $identity;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'removeById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('removeById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_removeById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\FirstRank\FirstRankService_removeById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\FirstRank\FirstRankService_removeById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("removeById failed: unknown result");
+  }
+
+}
+
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+class FirstRankService_save_args {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank
+   */
+  public $firstRank = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'firstRank',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['firstRank'])) {
+        $this->firstRank = $vals['firstRank'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_save_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->firstRank = new \OpenSearch\Generated\FirstRank\FirstRank();
+            $xfer += $this->firstRank->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_save_args');
+    if ($this->firstRank !== null) {
+      if (!is_object($this->firstRank)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('firstRank', TType::STRUCT, 1);
+      $xfer += $this->firstRank->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_save_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_save_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\FirstRank\FirstRank();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_save_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_getById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $identity = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'identity',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['identity'])) {
+        $this->identity = $vals['identity'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_getById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->identity);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_getById_args');
+    if ($this->identity !== null) {
+      $xfer += $output->writeFieldBegin('identity', TType::STRING, 1);
+      $xfer += $output->writeString($this->identity);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_getById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_getById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\FirstRank\FirstRank();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_getById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_listAll_args {
+  static $_TSPEC;
+
+
+  public function __construct() {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        );
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_listAll_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_listAll_args');
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_listAll_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank[]
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::LST,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+            ),
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_listAll_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::LST) {
+            $this->success = array();
+            $_size7 = 0;
+            $_etype10 = 0;
+            $xfer += $input->readListBegin($_etype10, $_size7);
+            for ($_i11 = 0; $_i11 < $_size7; ++$_i11)
+            {
+              $elem12 = null;
+              $elem12 = new \OpenSearch\Generated\FirstRank\FirstRank();
+              $xfer += $elem12->read($input);
+              $this->success []= $elem12;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_listAll_result');
+    if ($this->success !== null) {
+      if (!is_array($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::LST, 0);
+      {
+        $output->writeListBegin(TType::STRUCT, count($this->success));
+        {
+          foreach ($this->success as $iter13)
+          {
+            $xfer += $iter13->write($output);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_listByAppId_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $appId = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'appId',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['appId'])) {
+        $this->appId = $vals['appId'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_listByAppId_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->appId);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_listByAppId_args');
+    if ($this->appId !== null) {
+      $xfer += $output->writeFieldBegin('appId', TType::STRING, 1);
+      $xfer += $output->writeString($this->appId);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_listByAppId_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank[]
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::LST,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+            ),
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_listByAppId_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::LST) {
+            $this->success = array();
+            $_size14 = 0;
+            $_etype17 = 0;
+            $xfer += $input->readListBegin($_etype17, $_size14);
+            for ($_i18 = 0; $_i18 < $_size14; ++$_i18)
+            {
+              $elem19 = null;
+              $elem19 = new \OpenSearch\Generated\FirstRank\FirstRank();
+              $xfer += $elem19->read($input);
+              $this->success []= $elem19;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_listByAppId_result');
+    if ($this->success !== null) {
+      if (!is_array($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::LST, 0);
+      {
+        $output->writeListBegin(TType::STRUCT, count($this->success));
+        {
+          foreach ($this->success as $iter20)
+          {
+            $xfer += $iter20->write($output);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_listByAppIdAndName_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $appId = null;
+  /**
+   * @var string
+   */
+  public $name = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'appId',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'name',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['appId'])) {
+        $this->appId = $vals['appId'];
+      }
+      if (isset($vals['name'])) {
+        $this->name = $vals['name'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_listByAppIdAndName_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->appId);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->name);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_listByAppIdAndName_args');
+    if ($this->appId !== null) {
+      $xfer += $output->writeFieldBegin('appId', TType::STRING, 1);
+      $xfer += $output->writeString($this->appId);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->name !== null) {
+      $xfer += $output->writeFieldBegin('name', TType::STRING, 2);
+      $xfer += $output->writeString($this->name);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_listByAppIdAndName_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank[]
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::LST,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+            ),
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_listByAppIdAndName_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::LST) {
+            $this->success = array();
+            $_size21 = 0;
+            $_etype24 = 0;
+            $xfer += $input->readListBegin($_etype24, $_size21);
+            for ($_i25 = 0; $_i25 < $_size21; ++$_i25)
+            {
+              $elem26 = null;
+              $elem26 = new \OpenSearch\Generated\FirstRank\FirstRank();
+              $xfer += $elem26->read($input);
+              $this->success []= $elem26;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_listByAppIdAndName_result');
+    if ($this->success !== null) {
+      if (!is_array($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::LST, 0);
+      {
+        $output->writeListBegin(TType::STRUCT, count($this->success));
+        {
+          foreach ($this->success as $iter27)
+          {
+            $xfer += $iter27->write($output);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_updateById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $identity = null;
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank
+   */
+  public $firstRank = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'identity',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'firstRank',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['identity'])) {
+        $this->identity = $vals['identity'];
+      }
+      if (isset($vals['firstRank'])) {
+        $this->firstRank = $vals['firstRank'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_updateById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->identity);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->firstRank = new \OpenSearch\Generated\FirstRank\FirstRank();
+            $xfer += $this->firstRank->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_updateById_args');
+    if ($this->identity !== null) {
+      $xfer += $output->writeFieldBegin('identity', TType::STRING, 1);
+      $xfer += $output->writeString($this->identity);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->firstRank !== null) {
+      if (!is_object($this->firstRank)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('firstRank', TType::STRUCT, 2);
+      $xfer += $this->firstRank->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_updateById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_updateById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\FirstRank\FirstRank();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_updateById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_validateUpdateById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $identity = null;
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank
+   */
+  public $firstRank = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'identity',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'firstRank',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['identity'])) {
+        $this->identity = $vals['identity'];
+      }
+      if (isset($vals['firstRank'])) {
+        $this->firstRank = $vals['firstRank'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_validateUpdateById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->identity);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->firstRank = new \OpenSearch\Generated\FirstRank\FirstRank();
+            $xfer += $this->firstRank->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_validateUpdateById_args');
+    if ($this->identity !== null) {
+      $xfer += $output->writeFieldBegin('identity', TType::STRING, 1);
+      $xfer += $output->writeString($this->identity);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->firstRank !== null) {
+      if (!is_object($this->firstRank)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('firstRank', TType::STRUCT, 2);
+      $xfer += $this->firstRank->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_validateUpdateById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_validateUpdateById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\FirstRank\FirstRank();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_validateUpdateById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_removeById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $identity = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'identity',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['identity'])) {
+        $this->identity = $vals['identity'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_removeById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->identity);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_removeById_args');
+    if ($this->identity !== null) {
+      $xfer += $output->writeFieldBegin('identity', TType::STRING, 1);
+      $xfer += $output->writeString($this->identity);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankService_removeById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\FirstRank\FirstRank
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\FirstRank\FirstRank',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRankService_removeById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\FirstRank\FirstRank();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRankService_removeById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRankServiceProcessor {
+  protected $handler_ = null;
+  public function __construct($handler) {
+    $this->handler_ = $handler;
+  }
+
+  public function process($input, $output) {
+    $rseqid = 0;
+    $fname = null;
+    $mtype = 0;
+
+    $input->readMessageBegin($fname, $mtype, $rseqid);
+    $methodname = 'process_'.$fname;
+    if (!method_exists($this, $methodname)) {
+      $input->skip(TType::STRUCT);
+      $input->readMessageEnd();
+      $x = new TApplicationException('Function '.$fname.' not implemented.', TApplicationException::UNKNOWN_METHOD);
+      $output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid);
+      $x->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+      return;
+    }
+    $this->$methodname($rseqid, $input, $output);
+    return true;
+  }
+
+  protected function process_save($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_save_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\FirstRank\FirstRankService_save_result();
+    try {
+      $result->success = $this->handler_->save($args->firstRank);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'save', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('save', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_getById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_getById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\FirstRank\FirstRankService_getById_result();
+    try {
+      $result->success = $this->handler_->getById($args->identity);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'getById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('getById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_listAll($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_listAll_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\FirstRank\FirstRankService_listAll_result();
+    try {
+      $result->success = $this->handler_->listAll();
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'listAll', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('listAll', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_listByAppId($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_listByAppId_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\FirstRank\FirstRankService_listByAppId_result();
+    try {
+      $result->success = $this->handler_->listByAppId($args->appId);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'listByAppId', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('listByAppId', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_listByAppIdAndName($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_listByAppIdAndName_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\FirstRank\FirstRankService_listByAppIdAndName_result();
+    try {
+      $result->success = $this->handler_->listByAppIdAndName($args->appId, $args->name);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'listByAppIdAndName', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('listByAppIdAndName', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_updateById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_updateById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\FirstRank\FirstRankService_updateById_result();
+    try {
+      $result->success = $this->handler_->updateById($args->identity, $args->firstRank);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'updateById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('updateById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_validateUpdateById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_validateUpdateById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\FirstRank\FirstRankService_validateUpdateById_result();
+    try {
+      $result->success = $this->handler_->validateUpdateById($args->identity, $args->firstRank);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'validateUpdateById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('validateUpdateById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_removeById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\FirstRank\FirstRankService_removeById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\FirstRank\FirstRankService_removeById_result();
+    try {
+      $result->success = $this->handler_->removeById($args->identity);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'removeById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('removeById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+}
+

+ 364 - 0
php/OpenSearch/Generated/FirstRank/Types.php

@@ -0,0 +1,364 @@
+<?php
+namespace OpenSearch\Generated\FirstRank;
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+class Meta {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $attribute = null;
+  /**
+   * @var double
+   */
+  public $weight = null;
+  /**
+   * @var string
+   */
+  public $arg = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        10 => array(
+          'var' => 'attribute',
+          'type' => TType::STRING,
+          ),
+        11 => array(
+          'var' => 'weight',
+          'type' => TType::DOUBLE,
+          ),
+        12 => array(
+          'var' => 'arg',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['attribute'])) {
+        $this->attribute = $vals['attribute'];
+      }
+      if (isset($vals['weight'])) {
+        $this->weight = $vals['weight'];
+      }
+      if (isset($vals['arg'])) {
+        $this->arg = $vals['arg'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Meta';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 10:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->attribute);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 11:
+          if ($ftype == TType::DOUBLE) {
+            $xfer += $input->readDouble($this->weight);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 12:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->arg);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Meta');
+    if ($this->attribute !== null) {
+      $xfer += $output->writeFieldBegin('attribute', TType::STRING, 10);
+      $xfer += $output->writeString($this->attribute);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->weight !== null) {
+      $xfer += $output->writeFieldBegin('weight', TType::DOUBLE, 11);
+      $xfer += $output->writeDouble($this->weight);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->arg !== null) {
+      $xfer += $output->writeFieldBegin('arg', TType::STRING, 12);
+      $xfer += $output->writeString($this->arg);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class FirstRank {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $id = null;
+  /**
+   * @var \OpenSearch\Generated\Common\AppReference
+   */
+  public $app = null;
+  /**
+   * @var string
+   */
+  public $name = null;
+  /**
+   * @var \OpenSearch\Generated\FirstRank\Meta[]
+   */
+  public $meta = null;
+  /**
+   * @var bool
+   */
+  public $active = null;
+  /**
+   * @var string
+   */
+  public $description = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'id',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'app',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\AppReference',
+          ),
+        10 => array(
+          'var' => 'name',
+          'type' => TType::STRING,
+          ),
+        11 => array(
+          'var' => 'meta',
+          'type' => TType::LST,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\FirstRank\Meta',
+            ),
+          ),
+        12 => array(
+          'var' => 'active',
+          'type' => TType::BOOL,
+          ),
+        13 => array(
+          'var' => 'description',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['id'])) {
+        $this->id = $vals['id'];
+      }
+      if (isset($vals['app'])) {
+        $this->app = $vals['app'];
+      }
+      if (isset($vals['name'])) {
+        $this->name = $vals['name'];
+      }
+      if (isset($vals['meta'])) {
+        $this->meta = $vals['meta'];
+      }
+      if (isset($vals['active'])) {
+        $this->active = $vals['active'];
+      }
+      if (isset($vals['description'])) {
+        $this->description = $vals['description'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'FirstRank';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->id);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->app = new \OpenSearch\Generated\Common\AppReference();
+            $xfer += $this->app->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 10:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->name);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 11:
+          if ($ftype == TType::LST) {
+            $this->meta = array();
+            $_size0 = 0;
+            $_etype3 = 0;
+            $xfer += $input->readListBegin($_etype3, $_size0);
+            for ($_i4 = 0; $_i4 < $_size0; ++$_i4)
+            {
+              $elem5 = null;
+              $elem5 = new \OpenSearch\Generated\FirstRank\Meta();
+              $xfer += $elem5->read($input);
+              $this->meta []= $elem5;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 12:
+          if ($ftype == TType::BOOL) {
+            $xfer += $input->readBool($this->active);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 13:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->description);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('FirstRank');
+    if ($this->id !== null) {
+      $xfer += $output->writeFieldBegin('id', TType::STRING, 1);
+      $xfer += $output->writeString($this->id);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->app !== null) {
+      if (!is_object($this->app)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('app', TType::STRUCT, 2);
+      $xfer += $this->app->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->name !== null) {
+      $xfer += $output->writeFieldBegin('name', TType::STRING, 10);
+      $xfer += $output->writeString($this->name);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->meta !== null) {
+      if (!is_array($this->meta)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('meta', TType::LST, 11);
+      {
+        $output->writeListBegin(TType::STRUCT, count($this->meta));
+        {
+          foreach ($this->meta as $iter6)
+          {
+            $xfer += $iter6->write($output);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->active !== null) {
+      $xfer += $output->writeFieldBegin('active', TType::BOOL, 12);
+      $xfer += $output->writeBool($this->active);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->description !== null) {
+      $xfer += $output->writeFieldBegin('description', TType::STRING, 13);
+      $xfer += $output->writeString($this->description);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+

+ 67 - 0
php/OpenSearch/Generated/GeneralSearcher/GeneralSearcherService.php

@@ -0,0 +1,67 @@
+<?php
+namespace OpenSearch\Generated\GeneralSearcher;
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+interface GeneralSearcherServiceIf {
+}
+
+
+class GeneralSearcherServiceClient implements \OpenSearch\Generated\GeneralSearcher\GeneralSearcherServiceIf {
+  protected $input_ = null;
+  protected $output_ = null;
+
+  protected $seqid_ = 0;
+
+  public function __construct($input, $output=null) {
+    $this->input_ = $input;
+    $this->output_ = $output ? $output : $input;
+  }
+
+}
+
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+class GeneralSearcherServiceProcessor {
+  protected $handler_ = null;
+  public function __construct($handler) {
+    $this->handler_ = $handler;
+  }
+
+  public function process($input, $output) {
+    $rseqid = 0;
+    $fname = null;
+    $mtype = 0;
+
+    $input->readMessageBegin($fname, $mtype, $rseqid);
+    $methodname = 'process_'.$fname;
+    if (!method_exists($this, $methodname)) {
+      $input->skip(TType::STRUCT);
+      $input->readMessageEnd();
+      $x = new TApplicationException('Function '.$fname.' not implemented.', TApplicationException::UNKNOWN_METHOD);
+      $output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid);
+      $x->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+      return;
+    }
+    $this->$methodname($rseqid, $input, $output);
+    return true;
+  }
+
+}
+

+ 95 - 0
php/OpenSearch/Generated/GeneralSearcher/Types.php

@@ -0,0 +1,95 @@
+<?php
+namespace OpenSearch\Generated\GeneralSearcher;
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+class SearchResult {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $result = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'result',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['result'])) {
+        $this->result = $vals['result'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SearchResult';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->result);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SearchResult');
+    if ($this->result !== null) {
+      $xfer += $output->writeFieldBegin('result', TType::STRING, 1);
+      $xfer += $output->writeString($this->result);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+

+ 440 - 0
php/OpenSearch/Generated/OpenSearch/OpenSearchService.php

@@ -0,0 +1,440 @@
+<?php
+namespace OpenSearch\Generated\OpenSearch;
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+interface OpenSearchServiceIf {
+  /**
+   * @param string $path
+   * @param array $params
+   * @param string $method
+   * @return string
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function call($path, array $params, $method);
+}
+
+
+class OpenSearchServiceClient implements \OpenSearch\Generated\OpenSearch\OpenSearchServiceIf {
+  protected $input_ = null;
+  protected $output_ = null;
+
+  protected $seqid_ = 0;
+
+  public function __construct($input, $output=null) {
+    $this->input_ = $input;
+    $this->output_ = $output ? $output : $input;
+  }
+
+  public function call($path, array $params, $method)
+  {
+    $this->send_call($path, $params, $method);
+    return $this->recv_call();
+  }
+
+  public function send_call($path, array $params, $method)
+  {
+    $args = new \OpenSearch\Generated\OpenSearch\OpenSearchService_call_args();
+    $args->path = $path;
+    $args->params = $params;
+    $args->method = $method;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'call', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('call', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_call()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\OpenSearch\OpenSearchService_call_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\OpenSearch\OpenSearchService_call_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("call failed: unknown result");
+  }
+
+}
+
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+class OpenSearchService_call_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $path = null;
+  /**
+   * @var array
+   */
+  public $params = null;
+  /**
+   * @var string
+   */
+  public $method = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'path',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'params',
+          'type' => TType::MAP,
+          'ktype' => TType::STRING,
+          'vtype' => TType::STRING,
+          'key' => array(
+            'type' => TType::STRING,
+          ),
+          'val' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        3 => array(
+          'var' => 'method',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['path'])) {
+        $this->path = $vals['path'];
+      }
+      if (isset($vals['params'])) {
+        $this->params = $vals['params'];
+      }
+      if (isset($vals['method'])) {
+        $this->method = $vals['method'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'OpenSearchService_call_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->path);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::MAP) {
+            $this->params = array();
+            $_size9 = 0;
+            $_ktype10 = 0;
+            $_vtype11 = 0;
+            $xfer += $input->readMapBegin($_ktype10, $_vtype11, $_size9);
+            for ($_i13 = 0; $_i13 < $_size9; ++$_i13)
+            {
+              $key14 = '';
+              $val15 = '';
+              $xfer += $input->readString($key14);
+              $xfer += $input->readString($val15);
+              $this->params[$key14] = $val15;
+            }
+            $xfer += $input->readMapEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->method);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('OpenSearchService_call_args');
+    if ($this->path !== null) {
+      $xfer += $output->writeFieldBegin('path', TType::STRING, 1);
+      $xfer += $output->writeString($this->path);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->params !== null) {
+      if (!is_array($this->params)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('params', TType::MAP, 2);
+      {
+        $output->writeMapBegin(TType::STRING, TType::STRING, count($this->params));
+        {
+          foreach ($this->params as $kiter16 => $viter17)
+          {
+            $xfer += $output->writeString($kiter16);
+            $xfer += $output->writeString($viter17);
+          }
+        }
+        $output->writeMapEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->method !== null) {
+      $xfer += $output->writeFieldBegin('method', TType::STRING, 3);
+      $xfer += $output->writeString($this->method);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class OpenSearchService_call_result {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRING,
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'OpenSearchService_call_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->success);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('OpenSearchService_call_result');
+    if ($this->success !== null) {
+      $xfer += $output->writeFieldBegin('success', TType::STRING, 0);
+      $xfer += $output->writeString($this->success);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class OpenSearchServiceProcessor {
+  protected $handler_ = null;
+  public function __construct($handler) {
+    $this->handler_ = $handler;
+  }
+
+  public function process($input, $output) {
+    $rseqid = 0;
+    $fname = null;
+    $mtype = 0;
+
+    $input->readMessageBegin($fname, $mtype, $rseqid);
+    $methodname = 'process_'.$fname;
+    if (!method_exists($this, $methodname)) {
+      $input->skip(TType::STRUCT);
+      $input->readMessageEnd();
+      $x = new TApplicationException('Function '.$fname.' not implemented.', TApplicationException::UNKNOWN_METHOD);
+      $output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid);
+      $x->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+      return;
+    }
+    $this->$methodname($rseqid, $input, $output);
+    return true;
+  }
+
+  protected function process_call($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\OpenSearch\OpenSearchService_call_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\OpenSearch\OpenSearchService_call_result();
+    try {
+      $result->success = $this->handler_->call($args->path, $args->params, $args->method);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'call', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('call', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+}
+

+ 275 - 0
php/OpenSearch/Generated/OpenSearch/Types.php

@@ -0,0 +1,275 @@
+<?php
+namespace OpenSearch\Generated\OpenSearch;
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+class OpenSearch {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $accessKey = null;
+  /**
+   * @var string
+   */
+  public $secret = null;
+  /**
+   * @var string
+   */
+  public $host = null;
+  /**
+   * @var array
+   */
+  public $options = null;
+  /**
+   * @var bool
+   */
+  public $gzip = true;
+  /**
+   * @var int
+   */
+  public $timeout = null;
+  /**
+   * @var int
+   */
+  public $connectTimeout = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'accessKey',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'secret',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'host',
+          'type' => TType::STRING,
+          ),
+        4 => array(
+          'var' => 'options',
+          'type' => TType::MAP,
+          'ktype' => TType::STRING,
+          'vtype' => TType::STRING,
+          'key' => array(
+            'type' => TType::STRING,
+          ),
+          'val' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        5 => array(
+          'var' => 'gzip',
+          'type' => TType::BOOL,
+          ),
+        6 => array(
+          'var' => 'timeout',
+          'type' => TType::I32,
+          ),
+        7 => array(
+          'var' => 'connectTimeout',
+          'type' => TType::I32,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['accessKey'])) {
+        $this->accessKey = $vals['accessKey'];
+      }
+      if (isset($vals['secret'])) {
+        $this->secret = $vals['secret'];
+      }
+      if (isset($vals['host'])) {
+        $this->host = $vals['host'];
+      }
+      if (isset($vals['options'])) {
+        $this->options = $vals['options'];
+      }
+      if (isset($vals['gzip'])) {
+        $this->gzip = $vals['gzip'];
+      }
+      if (isset($vals['timeout'])) {
+        $this->timeout = $vals['timeout'];
+      }
+      if (isset($vals['connectTimeout'])) {
+        $this->connectTimeout = $vals['connectTimeout'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'OpenSearch';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->accessKey);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->secret);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->host);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 4:
+          if ($ftype == TType::MAP) {
+            $this->options = array();
+            $_size0 = 0;
+            $_ktype1 = 0;
+            $_vtype2 = 0;
+            $xfer += $input->readMapBegin($_ktype1, $_vtype2, $_size0);
+            for ($_i4 = 0; $_i4 < $_size0; ++$_i4)
+            {
+              $key5 = '';
+              $val6 = '';
+              $xfer += $input->readString($key5);
+              $xfer += $input->readString($val6);
+              $this->options[$key5] = $val6;
+            }
+            $xfer += $input->readMapEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 5:
+          if ($ftype == TType::BOOL) {
+            $xfer += $input->readBool($this->gzip);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 6:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->timeout);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 7:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->connectTimeout);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('OpenSearch');
+    if ($this->accessKey !== null) {
+      $xfer += $output->writeFieldBegin('accessKey', TType::STRING, 1);
+      $xfer += $output->writeString($this->accessKey);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->secret !== null) {
+      $xfer += $output->writeFieldBegin('secret', TType::STRING, 2);
+      $xfer += $output->writeString($this->secret);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->host !== null) {
+      $xfer += $output->writeFieldBegin('host', TType::STRING, 3);
+      $xfer += $output->writeString($this->host);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->options !== null) {
+      if (!is_array($this->options)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('options', TType::MAP, 4);
+      {
+        $output->writeMapBegin(TType::STRING, TType::STRING, count($this->options));
+        {
+          foreach ($this->options as $kiter7 => $viter8)
+          {
+            $xfer += $output->writeString($kiter7);
+            $xfer += $output->writeString($viter8);
+          }
+        }
+        $output->writeMapEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->gzip !== null) {
+      $xfer += $output->writeFieldBegin('gzip', TType::BOOL, 5);
+      $xfer += $output->writeBool($this->gzip);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->timeout !== null) {
+      $xfer += $output->writeFieldBegin('timeout', TType::I32, 6);
+      $xfer += $output->writeI32($this->timeout);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->connectTimeout !== null) {
+      $xfer += $output->writeFieldBegin('connectTimeout', TType::I32, 7);
+      $xfer += $output->writeI32($this->connectTimeout);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+final class Constant extends \Thrift\Type\TConstant {
+  static protected $VERSION;
+
+  static protected function init_VERSION() {
+    return "3.1.0";
+  }
+}
+
+

+ 356 - 0
php/OpenSearch/Generated/Search/OpenSearchSearcherService.php

@@ -0,0 +1,356 @@
+<?php
+namespace OpenSearch\Generated\Search;
+/**
+ * Autogenerated by Thrift Compiler (0.9.3)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+interface OpenSearchSearcherServiceIf extends \OpenSearch\Generated\GeneralSearcher\GeneralSearcherServiceIf {
+  /**
+   * @param \OpenSearch\Generated\Search\SearchParams $searchParams
+   * @return \OpenSearch\Generated\GeneralSearcher\SearchResult
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function execute(\OpenSearch\Generated\Search\SearchParams $searchParams);
+}
+
+class OpenSearchSearcherServiceClient extends \OpenSearch\Generated\GeneralSearcher\GeneralSearcherServiceClient implements \OpenSearch\Generated\Search\OpenSearchSearcherServiceIf {
+  public function __construct($input, $output=null) {
+    parent::__construct($input, $output);
+  }
+
+  public function execute(\OpenSearch\Generated\Search\SearchParams $searchParams)
+  {
+    $this->send_execute($searchParams);
+    return $this->recv_execute();
+  }
+
+  public function send_execute(\OpenSearch\Generated\Search\SearchParams $searchParams)
+  {
+    $args = new \OpenSearch\Generated\Search\OpenSearchSearcherService_execute_args();
+    $args->searchParams = $searchParams;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'execute', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('execute', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_execute()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\Search\OpenSearchSearcherService_execute_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\Search\OpenSearchSearcherService_execute_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("execute failed: unknown result");
+  }
+
+}
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+class OpenSearchSearcherService_execute_args {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Search\SearchParams
+   */
+  public $searchParams = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'searchParams',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Search\SearchParams',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['searchParams'])) {
+        $this->searchParams = $vals['searchParams'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'OpenSearchSearcherService_execute_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->searchParams = new \OpenSearch\Generated\Search\SearchParams();
+            $xfer += $this->searchParams->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('OpenSearchSearcherService_execute_args');
+    if ($this->searchParams !== null) {
+      if (!is_object($this->searchParams)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('searchParams', TType::STRUCT, 1);
+      $xfer += $this->searchParams->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class OpenSearchSearcherService_execute_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\GeneralSearcher\SearchResult
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\GeneralSearcher\SearchResult',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'OpenSearchSearcherService_execute_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\GeneralSearcher\SearchResult();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('OpenSearchSearcherService_execute_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class OpenSearchSearcherServiceProcessor extends \OpenSearch\Generated\GeneralSearcher\GeneralSearcherServiceProcessor {
+  public function __construct($handler) {
+    parent::__construct($handler);
+  }
+
+  public function process($input, $output) {
+    $rseqid = 0;
+    $fname = null;
+    $mtype = 0;
+
+    $input->readMessageBegin($fname, $mtype, $rseqid);
+    $methodname = 'process_'.$fname;
+    if (!method_exists($this, $methodname)) {
+      $input->skip(TType::STRUCT);
+      $input->readMessageEnd();
+      $x = new TApplicationException('Function '.$fname.' not implemented.', TApplicationException::UNKNOWN_METHOD);
+      $output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid);
+      $x->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+      return;
+    }
+    $this->$methodname($rseqid, $input, $output);
+    return true;
+  }
+
+  protected function process_execute($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\Search\OpenSearchSearcherService_execute_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\Search\OpenSearchSearcherService_execute_result();
+    try {
+      $result->success = $this->handler_->execute($args->searchParams);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'execute', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('execute', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+}

+ 2637 - 0
php/OpenSearch/Generated/Search/Types.php

@@ -0,0 +1,2637 @@
+<?php
+namespace OpenSearch\Generated\Search;
+
+/**
+ * Autogenerated by Thrift Compiler (0.9.3)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+final class SearchType {
+  const SEARCH = 0;
+  const SCROLL = 1;
+  static public $__names = array(
+    0 => 'SEARCH',
+    1 => 'SCROLL',
+  );
+}
+
+final class SearchFormat {
+  const XML = 0;
+  const JSON = 1;
+  const FULLJSON = 2;
+  const PROTOBUF = 3;
+  static public $__names = array(
+    0 => 'XML',
+    1 => 'JSON',
+    2 => 'FULLJSON',
+    3 => 'PROTOBUF',
+  );
+}
+
+final class Order {
+  const DECREASE = 0;
+  const INCREASE = 1;
+  static public $__names = array(
+    0 => 'DECREASE',
+    1 => 'INCREASE',
+  );
+}
+
+class Config {
+  static $_TSPEC;
+
+  /**
+   * app name 或 app id 或 app version
+   * 
+   * @var string[]
+   */
+  public $appNames = null;
+  /**
+   * @var int
+   */
+  public $start = 0;
+  /**
+   * @var int
+   */
+  public $hits = 15;
+  /**
+   * @var int
+   */
+  public $searchFormat =   0;
+  /**
+   * example:  query=config=start:0,hit:15,rerank_size:200,format:json,KVpairs=name:company_name,price:new_price&&query=id:'489013149'</p>
+   * 
+   * config.setCustomConfig(Lists.newArrayList("mykey1:name#company_name,price#new_price"));
+   * 
+   * 
+   * 
+   * @var string[]
+   */
+  public $customConfig = null;
+  /**
+   * example: cluster=daogou&&kvpairs=name:company_name&&query=笔筒</p>
+   * 
+   * config.setKvpairs("name:company_name,price:new_price");
+   * 
+   * 
+   * 
+   * @var string
+   */
+  public $kvpairs = null;
+  /**
+   * 获取搜索结果包含的字段列表(fetch_fields)
+   * 
+   * 
+   * @var string[]
+   */
+  public $fetchFields = null;
+  /**
+   * 分区查询.  routeValue为分区键所对应的值.
+   * 
+   * 
+   * @var string
+   */
+  public $routeValue = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'appNames',
+          'type' => TType::LST,
+          'etype' => TType::STRING,
+          'elem' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        2 => array(
+          'var' => 'start',
+          'type' => TType::I32,
+          ),
+        3 => array(
+          'var' => 'hits',
+          'type' => TType::I32,
+          ),
+        5 => array(
+          'var' => 'searchFormat',
+          'type' => TType::I32,
+          ),
+        7 => array(
+          'var' => 'customConfig',
+          'type' => TType::LST,
+          'etype' => TType::STRING,
+          'elem' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        9 => array(
+          'var' => 'kvpairs',
+          'type' => TType::STRING,
+          ),
+        11 => array(
+          'var' => 'fetchFields',
+          'type' => TType::LST,
+          'etype' => TType::STRING,
+          'elem' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        13 => array(
+          'var' => 'routeValue',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['appNames'])) {
+        $this->appNames = $vals['appNames'];
+      }
+      if (isset($vals['start'])) {
+        $this->start = $vals['start'];
+      }
+      if (isset($vals['hits'])) {
+        $this->hits = $vals['hits'];
+      }
+      if (isset($vals['searchFormat'])) {
+        $this->searchFormat = $vals['searchFormat'];
+      }
+      if (isset($vals['customConfig'])) {
+        $this->customConfig = $vals['customConfig'];
+      }
+      if (isset($vals['kvpairs'])) {
+        $this->kvpairs = $vals['kvpairs'];
+      }
+      if (isset($vals['fetchFields'])) {
+        $this->fetchFields = $vals['fetchFields'];
+      }
+      if (isset($vals['routeValue'])) {
+        $this->routeValue = $vals['routeValue'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Config';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::LST) {
+            $this->appNames = array();
+            $_size0 = 0;
+            $_etype3 = 0;
+            $xfer += $input->readListBegin($_etype3, $_size0);
+            for ($_i4 = 0; $_i4 < $_size0; ++$_i4)
+            {
+              $elem5 = null;
+              $xfer += $input->readString($elem5);
+              $this->appNames []= $elem5;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->start);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->hits);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 5:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->searchFormat);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 7:
+          if ($ftype == TType::LST) {
+            $this->customConfig = array();
+            $_size6 = 0;
+            $_etype9 = 0;
+            $xfer += $input->readListBegin($_etype9, $_size6);
+            for ($_i10 = 0; $_i10 < $_size6; ++$_i10)
+            {
+              $elem11 = null;
+              $xfer += $input->readString($elem11);
+              $this->customConfig []= $elem11;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 9:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->kvpairs);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 11:
+          if ($ftype == TType::LST) {
+            $this->fetchFields = array();
+            $_size12 = 0;
+            $_etype15 = 0;
+            $xfer += $input->readListBegin($_etype15, $_size12);
+            for ($_i16 = 0; $_i16 < $_size12; ++$_i16)
+            {
+              $elem17 = null;
+              $xfer += $input->readString($elem17);
+              $this->fetchFields []= $elem17;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 13:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->routeValue);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Config');
+    if ($this->appNames !== null) {
+      if (!is_array($this->appNames)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('appNames', TType::LST, 1);
+      {
+        $output->writeListBegin(TType::STRING, count($this->appNames));
+        {
+          foreach ($this->appNames as $iter18)
+          {
+            $xfer += $output->writeString($iter18);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->start !== null) {
+      $xfer += $output->writeFieldBegin('start', TType::I32, 2);
+      $xfer += $output->writeI32($this->start);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->hits !== null) {
+      $xfer += $output->writeFieldBegin('hits', TType::I32, 3);
+      $xfer += $output->writeI32($this->hits);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->searchFormat !== null) {
+      $xfer += $output->writeFieldBegin('searchFormat', TType::I32, 5);
+      $xfer += $output->writeI32($this->searchFormat);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->customConfig !== null) {
+      if (!is_array($this->customConfig)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('customConfig', TType::LST, 7);
+      {
+        $output->writeListBegin(TType::STRING, count($this->customConfig));
+        {
+          foreach ($this->customConfig as $iter19)
+          {
+            $xfer += $output->writeString($iter19);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->kvpairs !== null) {
+      $xfer += $output->writeFieldBegin('kvpairs', TType::STRING, 9);
+      $xfer += $output->writeString($this->kvpairs);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->fetchFields !== null) {
+      if (!is_array($this->fetchFields)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('fetchFields', TType::LST, 11);
+      {
+        $output->writeListBegin(TType::STRING, count($this->fetchFields));
+        {
+          foreach ($this->fetchFields as $iter20)
+          {
+            $xfer += $output->writeString($iter20);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->routeValue !== null) {
+      $xfer += $output->writeFieldBegin('routeValue', TType::STRING, 13);
+      $xfer += $output->writeString($this->routeValue);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+/**
+ * 
+ * 传统搜索场景的主要目的是为了尽量短的时间内召回最符合的结果,所以对搜索结果进行了限制。在某些场景下需要提供更多的结果来进行分析工作,
+ * 可以使用scroll接口来获取更多的结果,目前scorll只支持query与filter子句,sort子句无法支持。
+ * 
+ * 注意事项
+ * <pre>
+ *  1, start值无效,通过hit值设置每次返回的结果数,即后续查询都以第一次查询指定的hit值为准;
+ *  2, aggregate、sort、distinct、排序表达式无效,如果传入,查询会报错且无结果;
+ *  3, 第一次查询需要完整的query、index_name、AccessKeyId等参数,后面的查询不需要传这些参数(即使传入,也会被忽略),只需要传入上一次返回的scroll_id即可;
+ *  4, 不支持多应用scroll查询;
+ *  5, 每次查询都必须传scroll参数,如果不传,对于第一次查询,就按正常的查询;对于后续的查询,按scroll处理,但结果中无scroll_id返回。
+ *  6, 返回结果均有第一次查询中的format决定,后续传scroll_id的响应格式均同第一次;
+ *  7, 如果用户传入的scroll_id是非法的,那么查询会报错,返回结果格式为json。
+ *  8, 第一次查询将不返回实际文档数据,只返回scroll_id,需要再次访问才能拿到搜索结果。
+ *  </pre>
+ */
+class DeepPaging {
+  static $_TSPEC;
+
+  /**
+   * 设置scroll请求的有效期
+   * 
+   * @param expire 指定的scroll请求有效期 默认 1m 表示一分钟,支持的时间单位包括:w=Week, d=Day, h=Hour, m=minute, s=second
+   * 
+   * @var string
+   */
+  public $scrollExpire = "1m";
+  /**
+   * @var string
+   */
+  public $scrollId = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'scrollExpire',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'scrollId',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['scrollExpire'])) {
+        $this->scrollExpire = $vals['scrollExpire'];
+      }
+      if (isset($vals['scrollId'])) {
+        $this->scrollId = $vals['scrollId'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'DeepPaging';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->scrollExpire);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->scrollId);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('DeepPaging');
+    if ($this->scrollExpire !== null) {
+      $xfer += $output->writeFieldBegin('scrollExpire', TType::STRING, 1);
+      $xfer += $output->writeString($this->scrollExpire);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->scrollId !== null) {
+      $xfer += $output->writeFieldBegin('scrollId', TType::STRING, 3);
+      $xfer += $output->writeString($this->scrollId);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SortField {
+  static $_TSPEC;
+
+  /**
+   * 排序方式字段名.
+   * 
+   * 
+   * @var string
+   */
+  public $field = null;
+  /**
+   * 排序方式,有升序“INCREASE”和降序“DECREASE”两种方式。默认值为“DECREASE”
+   * 
+   * 
+   * @var int
+   */
+  public $order =   0;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'field',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'order',
+          'type' => TType::I32,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['field'])) {
+        $this->field = $vals['field'];
+      }
+      if (isset($vals['order'])) {
+        $this->order = $vals['order'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SortField';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->field);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->order);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SortField');
+    if ($this->field !== null) {
+      $xfer += $output->writeFieldBegin('field', TType::STRING, 1);
+      $xfer += $output->writeString($this->field);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->order !== null) {
+      $xfer += $output->writeFieldBegin('order', TType::I32, 3);
+      $xfer += $output->writeI32($this->order);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+/**
+ * 排序字段及方式
+ * 
+ */
+class Sort {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Search\SortField[]
+   */
+  public $sortFields = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'sortFields',
+          'type' => TType::LST,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\Search\SortField',
+            ),
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['sortFields'])) {
+        $this->sortFields = $vals['sortFields'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Sort';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::LST) {
+            $this->sortFields = array();
+            $_size21 = 0;
+            $_etype24 = 0;
+            $xfer += $input->readListBegin($_etype24, $_size21);
+            for ($_i25 = 0; $_i25 < $_size21; ++$_i25)
+            {
+              $elem26 = null;
+              $elem26 = new \OpenSearch\Generated\Search\SortField();
+              $xfer += $elem26->read($input);
+              $this->sortFields []= $elem26;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Sort');
+    if ($this->sortFields !== null) {
+      if (!is_array($this->sortFields)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('sortFields', TType::LST, 1);
+      {
+        $output->writeListBegin(TType::STRUCT, count($this->sortFields));
+        {
+          foreach ($this->sortFields as $iter27)
+          {
+            $xfer += $iter27->write($output);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+/**
+ * 排序相关度及表达式
+ * 
+ */
+class Rank {
+  static $_TSPEC;
+
+  /**
+   * @var int
+   */
+  public $reRankSize = 200;
+  /**
+   * 设置粗排表达式名称
+   * 
+   * 
+   * @var string
+   */
+  public $firstRankName = null;
+  /**
+   * 设置粗排表达式名称
+   * 
+   * 
+   * @var string
+   */
+  public $secondRankName = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'reRankSize',
+          'type' => TType::I32,
+          ),
+        3 => array(
+          'var' => 'firstRankName',
+          'type' => TType::STRING,
+          ),
+        5 => array(
+          'var' => 'secondRankName',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['reRankSize'])) {
+        $this->reRankSize = $vals['reRankSize'];
+      }
+      if (isset($vals['firstRankName'])) {
+        $this->firstRankName = $vals['firstRankName'];
+      }
+      if (isset($vals['secondRankName'])) {
+        $this->secondRankName = $vals['secondRankName'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Rank';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->reRankSize);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->firstRankName);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 5:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->secondRankName);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Rank');
+    if ($this->reRankSize !== null) {
+      $xfer += $output->writeFieldBegin('reRankSize', TType::I32, 1);
+      $xfer += $output->writeI32($this->reRankSize);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->firstRankName !== null) {
+      $xfer += $output->writeFieldBegin('firstRankName', TType::STRING, 3);
+      $xfer += $output->writeString($this->firstRankName);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->secondRankName !== null) {
+      $xfer += $output->writeFieldBegin('secondRankName', TType::STRING, 5);
+      $xfer += $output->writeString($this->secondRankName);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+/**
+ * 增加了此内容后,fieldName字段可能会被截断、飘红等。
+ * 
+ */
+class Summary {
+  static $_TSPEC;
+
+  /**
+   * 指定的生效的字段。此字段必需为可分词的text类型的字段。
+   * 
+   * 
+   * @var string
+   */
+  public $summary_field = null;
+  /**
+   * 指定结果集返回的词字段的字节长度,一个汉字为2个字节。
+   * 
+   * 
+   * @var string
+   */
+  public $summary_len = null;
+  /**
+   * 指定用什么符号来标注未展示完的数据,例如“...”。
+   * 
+   * 
+   * @var string
+   */
+  public $summary_ellipsis = "...";
+  /**
+   * 指定query命中几段summary内容。
+   * 
+   * 
+   * @var string
+   */
+  public $summary_snippet = null;
+  /**
+   * 指定命中的query的标红标签,可以为em等。
+   * 
+   * 
+   * @var string
+   */
+  public $summary_element = null;
+  /**
+   * 指定标签前缀。
+   * 
+   * 
+   * @var string
+   */
+  public $summary_element_prefix = null;
+  /**
+   * 指定标签后缀。
+   * 
+   * 
+   * @var string
+   */
+  public $summary_element_postfix = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'summary_field',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'summary_len',
+          'type' => TType::STRING,
+          ),
+        5 => array(
+          'var' => 'summary_ellipsis',
+          'type' => TType::STRING,
+          ),
+        7 => array(
+          'var' => 'summary_snippet',
+          'type' => TType::STRING,
+          ),
+        9 => array(
+          'var' => 'summary_element',
+          'type' => TType::STRING,
+          ),
+        11 => array(
+          'var' => 'summary_element_prefix',
+          'type' => TType::STRING,
+          ),
+        13 => array(
+          'var' => 'summary_element_postfix',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['summary_field'])) {
+        $this->summary_field = $vals['summary_field'];
+      }
+      if (isset($vals['summary_len'])) {
+        $this->summary_len = $vals['summary_len'];
+      }
+      if (isset($vals['summary_ellipsis'])) {
+        $this->summary_ellipsis = $vals['summary_ellipsis'];
+      }
+      if (isset($vals['summary_snippet'])) {
+        $this->summary_snippet = $vals['summary_snippet'];
+      }
+      if (isset($vals['summary_element'])) {
+        $this->summary_element = $vals['summary_element'];
+      }
+      if (isset($vals['summary_element_prefix'])) {
+        $this->summary_element_prefix = $vals['summary_element_prefix'];
+      }
+      if (isset($vals['summary_element_postfix'])) {
+        $this->summary_element_postfix = $vals['summary_element_postfix'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Summary';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->summary_field);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->summary_len);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 5:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->summary_ellipsis);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 7:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->summary_snippet);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 9:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->summary_element);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 11:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->summary_element_prefix);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 13:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->summary_element_postfix);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Summary');
+    if ($this->summary_field !== null) {
+      $xfer += $output->writeFieldBegin('summary_field', TType::STRING, 1);
+      $xfer += $output->writeString($this->summary_field);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->summary_len !== null) {
+      $xfer += $output->writeFieldBegin('summary_len', TType::STRING, 3);
+      $xfer += $output->writeString($this->summary_len);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->summary_ellipsis !== null) {
+      $xfer += $output->writeFieldBegin('summary_ellipsis', TType::STRING, 5);
+      $xfer += $output->writeString($this->summary_ellipsis);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->summary_snippet !== null) {
+      $xfer += $output->writeFieldBegin('summary_snippet', TType::STRING, 7);
+      $xfer += $output->writeString($this->summary_snippet);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->summary_element !== null) {
+      $xfer += $output->writeFieldBegin('summary_element', TType::STRING, 9);
+      $xfer += $output->writeString($this->summary_element);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->summary_element_prefix !== null) {
+      $xfer += $output->writeFieldBegin('summary_element_prefix', TType::STRING, 11);
+      $xfer += $output->writeString($this->summary_element_prefix);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->summary_element_postfix !== null) {
+      $xfer += $output->writeFieldBegin('summary_element_postfix', TType::STRING, 13);
+      $xfer += $output->writeString($this->summary_element_postfix);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+/**
+ * 添加统计信息(aggregate)
+ * 
+ * 一个关键词通常能命中数以万计的文档,用户不太可能浏览所有文档来获取信息。而用户感兴趣的
+ * 可 能是一些统计类的信息,比如,查询“手机”这个关键词,想知道每个卖家所有商品中的最高价格。
+ * 则可以按照卖家的user_id分组,统计每个小组中最大的price值,例如:
+ * groupKey:user_id,aggFun:max(price)
+ * 
+ * 相关wiki,请查询:
+ * @link http://docs.aliyun.com/?spm=5176.2020520121.103.8.VQIcGd&tag=tun#/pub/opensearch/api-reference/query-clause&aggregate-clause
+ * 
+ */
+class Aggregate {
+  static $_TSPEC;
+
+  /**
+   * 指定需要统计的字段名称。
+   * 
+   * 
+   * @var string
+   */
+  public $groupKey = null;
+  /**
+   * 指定统计的方法。当前支持:count、max、min、sum等。
+   * 
+   * 
+   * @var string
+   */
+  public $aggFun = null;
+  /**
+   * 指定统计范围。
+   * 
+   * 
+   * @var string
+   */
+  public $range = null;
+  /**
+   * 最大组个数。
+   * 
+   * 
+   * @var string
+   */
+  public $maxGroup = null;
+  /**
+   * 指定过滤某些统计。
+   * 
+   * 
+   * @var string
+   */
+  public $aggFilter = null;
+  /**
+   * 指定抽样的阈值。
+   * 
+   * 
+   * @var string
+   */
+  public $aggSamplerThresHold = null;
+  /**
+   * 指定抽样的步长。
+   * 
+   * 
+   * @var string
+   */
+  public $aggSamplerStep = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'groupKey',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'aggFun',
+          'type' => TType::STRING,
+          ),
+        5 => array(
+          'var' => 'range',
+          'type' => TType::STRING,
+          ),
+        7 => array(
+          'var' => 'maxGroup',
+          'type' => TType::STRING,
+          ),
+        9 => array(
+          'var' => 'aggFilter',
+          'type' => TType::STRING,
+          ),
+        11 => array(
+          'var' => 'aggSamplerThresHold',
+          'type' => TType::STRING,
+          ),
+        13 => array(
+          'var' => 'aggSamplerStep',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['groupKey'])) {
+        $this->groupKey = $vals['groupKey'];
+      }
+      if (isset($vals['aggFun'])) {
+        $this->aggFun = $vals['aggFun'];
+      }
+      if (isset($vals['range'])) {
+        $this->range = $vals['range'];
+      }
+      if (isset($vals['maxGroup'])) {
+        $this->maxGroup = $vals['maxGroup'];
+      }
+      if (isset($vals['aggFilter'])) {
+        $this->aggFilter = $vals['aggFilter'];
+      }
+      if (isset($vals['aggSamplerThresHold'])) {
+        $this->aggSamplerThresHold = $vals['aggSamplerThresHold'];
+      }
+      if (isset($vals['aggSamplerStep'])) {
+        $this->aggSamplerStep = $vals['aggSamplerStep'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Aggregate';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->groupKey);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->aggFun);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 5:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->range);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 7:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->maxGroup);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 9:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->aggFilter);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 11:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->aggSamplerThresHold);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 13:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->aggSamplerStep);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Aggregate');
+    if ($this->groupKey !== null) {
+      $xfer += $output->writeFieldBegin('groupKey', TType::STRING, 1);
+      $xfer += $output->writeString($this->groupKey);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->aggFun !== null) {
+      $xfer += $output->writeFieldBegin('aggFun', TType::STRING, 3);
+      $xfer += $output->writeString($this->aggFun);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->range !== null) {
+      $xfer += $output->writeFieldBegin('range', TType::STRING, 5);
+      $xfer += $output->writeString($this->range);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->maxGroup !== null) {
+      $xfer += $output->writeFieldBegin('maxGroup', TType::STRING, 7);
+      $xfer += $output->writeString($this->maxGroup);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->aggFilter !== null) {
+      $xfer += $output->writeFieldBegin('aggFilter', TType::STRING, 9);
+      $xfer += $output->writeString($this->aggFilter);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->aggSamplerThresHold !== null) {
+      $xfer += $output->writeFieldBegin('aggSamplerThresHold', TType::STRING, 11);
+      $xfer += $output->writeString($this->aggSamplerThresHold);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->aggSamplerStep !== null) {
+      $xfer += $output->writeFieldBegin('aggSamplerStep', TType::STRING, 13);
+      $xfer += $output->writeString($this->aggSamplerStep);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+/**
+ * 聚合打散条件(distinct)
+ * 
+ * 例如:检索关键词“手机”共获得10个结果,分别为:doc1,doc2,doc3,doc4,doc5,doc6,
+ * doc7,doc8,doc9,doc10。其中前三个属于用户A,doc4-doc6属于用户B,剩余四个属于
+ * 用户C。如果前端每页仅展示5个商品,则用户C将没有展示的机会。但是如果按照user_id进行抽
+ * 取,每轮抽取1个,抽取2次,并保留抽取剩余的结果,则可以获得以下文档排列顺序:doc1、
+ * doc4、doc7、doc2、doc5、doc8、doc3、doc6、doc9、doc10。可以看出,通过distinct
+ * 排序,各个用户的 商品都得到了展示机会,结果排序更趋于合理。
+ */
+class Distinct {
+  static $_TSPEC;
+
+  /**
+   * 为用户用于做distinct抽取的字段,该字段要求为可过滤字段。
+   *  
+   * 
+   * @var string
+   */
+  public $key = null;
+  /**
+   * 为一次抽取的document数量,默认值为1。
+   *  
+   * 
+   * @var int
+   */
+  public $distCount = 1;
+  /**
+   * 为抽取的次数,默认值为1。
+   *  
+   * 
+   * @var int
+   */
+  public $distTimes = 1;
+  /**
+   * 为是否保留抽取之后剩余的结果,true为保留,false则丢弃,丢弃时totalHits的个数会减去被distinct而丢弃的个数,但这个结果不一定准确,默认为true。
+   *  
+   * 
+   * @var bool
+   */
+  public $reserved = true;
+  /**
+   * 为过滤条件,被过滤的doc不参与distinct,只在后面的 排序中,这些被过滤的doc将和被distinct出来的第一组doc一起参与排序。默认是全部参与distinct。
+   *  
+   * 
+   * @var string
+   */
+  public $distFilter = null;
+  /**
+   * 当reserved为false时,设置update_total_hit为true,则最终total_hit会减去被distinct丢弃的的数目(不一定准确),为false则不减; 默认为false。
+   *  
+   * 
+   * @var bool
+   */
+  public $updateTotalHit = false;
+  /**
+   * 指定档位划分阈值。
+   *  
+   * 
+   * @var string
+   */
+  public $grade = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'key',
+          'type' => TType::STRING,
+          ),
+        3 => array(
+          'var' => 'distCount',
+          'type' => TType::I32,
+          ),
+        5 => array(
+          'var' => 'distTimes',
+          'type' => TType::I32,
+          ),
+        7 => array(
+          'var' => 'reserved',
+          'type' => TType::BOOL,
+          ),
+        9 => array(
+          'var' => 'distFilter',
+          'type' => TType::STRING,
+          ),
+        11 => array(
+          'var' => 'updateTotalHit',
+          'type' => TType::BOOL,
+          ),
+        13 => array(
+          'var' => 'grade',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['key'])) {
+        $this->key = $vals['key'];
+      }
+      if (isset($vals['distCount'])) {
+        $this->distCount = $vals['distCount'];
+      }
+      if (isset($vals['distTimes'])) {
+        $this->distTimes = $vals['distTimes'];
+      }
+      if (isset($vals['reserved'])) {
+        $this->reserved = $vals['reserved'];
+      }
+      if (isset($vals['distFilter'])) {
+        $this->distFilter = $vals['distFilter'];
+      }
+      if (isset($vals['updateTotalHit'])) {
+        $this->updateTotalHit = $vals['updateTotalHit'];
+      }
+      if (isset($vals['grade'])) {
+        $this->grade = $vals['grade'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Distinct';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->key);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 3:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->distCount);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 5:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->distTimes);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 7:
+          if ($ftype == TType::BOOL) {
+            $xfer += $input->readBool($this->reserved);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 9:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->distFilter);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 11:
+          if ($ftype == TType::BOOL) {
+            $xfer += $input->readBool($this->updateTotalHit);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 13:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->grade);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Distinct');
+    if ($this->key !== null) {
+      $xfer += $output->writeFieldBegin('key', TType::STRING, 1);
+      $xfer += $output->writeString($this->key);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->distCount !== null) {
+      $xfer += $output->writeFieldBegin('distCount', TType::I32, 3);
+      $xfer += $output->writeI32($this->distCount);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->distTimes !== null) {
+      $xfer += $output->writeFieldBegin('distTimes', TType::I32, 5);
+      $xfer += $output->writeI32($this->distTimes);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->reserved !== null) {
+      $xfer += $output->writeFieldBegin('reserved', TType::BOOL, 7);
+      $xfer += $output->writeBool($this->reserved);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->distFilter !== null) {
+      $xfer += $output->writeFieldBegin('distFilter', TType::STRING, 9);
+      $xfer += $output->writeString($this->distFilter);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->updateTotalHit !== null) {
+      $xfer += $output->writeFieldBegin('updateTotalHit', TType::BOOL, 11);
+      $xfer += $output->writeBool($this->updateTotalHit);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->grade !== null) {
+      $xfer += $output->writeFieldBegin('grade', TType::STRING, 13);
+      $xfer += $output->writeString($this->grade);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class Suggest {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $suggestName = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'suggestName',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['suggestName'])) {
+        $this->suggestName = $vals['suggestName'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Suggest';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->suggestName);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Suggest');
+    if ($this->suggestName !== null) {
+      $xfer += $output->writeFieldBegin('suggestName', TType::STRING, 1);
+      $xfer += $output->writeString($this->suggestName);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class Abtest {
+  static $_TSPEC;
+
+  /**
+   * 场景标签。用户在控制台上配置哪些场景需要做实验,查询中只有指定了对应场景名的query才会进行实验。
+   * 
+   * @var string
+   */
+  public $sceneTag = null;
+  /**
+   * 流量分配标识。对该值进行hash,将用户查询分配到不同的实验中,该值通常可设置为最终用户的id。
+   * 
+   * @var string
+   */
+  public $flowDivider = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'sceneTag',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'flowDivider',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['sceneTag'])) {
+        $this->sceneTag = $vals['sceneTag'];
+      }
+      if (isset($vals['flowDivider'])) {
+        $this->flowDivider = $vals['flowDivider'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Abtest';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->sceneTag);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->flowDivider);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Abtest');
+    if ($this->sceneTag !== null) {
+      $xfer += $output->writeFieldBegin('sceneTag', TType::STRING, 1);
+      $xfer += $output->writeString($this->sceneTag);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->flowDivider !== null) {
+      $xfer += $output->writeFieldBegin('flowDivider', TType::STRING, 2);
+      $xfer += $output->writeString($this->flowDivider);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SearchParams {
+  static $_TSPEC;
+
+  /**
+   * config for search.
+   * 
+   * @var \OpenSearch\Generated\Search\Config
+   */
+  public $config = null;
+  /**
+   * 设定指定索引字段范围的搜索关键词(query)
+   * 
+   * 此query是查询必需的一部分,可以指定不同的索引名,并同时可指定多个查询及之间的关系
+   * (AND, OR, ANDNOT, RANK)。
+   * 
+   * 例如查询subject索引字段的query:“手机”,可以设置为 query=subject:'手机'。
+   * 
+   * 上边例子如果查询price 在1000-2000之间的手机,其查询语句为: query=subject:'手机'
+   * AND price:[1000,2000]
+   * 
+   * NOTE: text类型索引在建立时做了分词,而string类型的索引则没有分词。
+   * 
+   * @link http://docs.aliyun.com/?spm=5176.2020520121.103.8.VQIcGd&tag=tun#/pub/opensearch/api-reference/query-clause&query-clause
+   * 
+   * 
+   * @var string
+   */
+  public $query = null;
+  /**
+   * 过滤规则(filter)
+   * 
+   * @var string
+   */
+  public $filter = null;
+  /**
+   * 排序字段及排序方式(sort)
+   * 
+   * @var \OpenSearch\Generated\Search\Sort
+   */
+  public $sort = null;
+  /**
+   * @var \OpenSearch\Generated\Search\Rank
+   */
+  public $rank = null;
+  /**
+   * 添加统计信息(aggregate)相关参数
+   * 
+   * @var \OpenSearch\Generated\Search\Aggregate[]
+   */
+  public $aggregates = null;
+  /**
+   * 聚合打散条件
+   * 
+   * @var \OpenSearch\Generated\Search\Distinct[]
+   */
+  public $distincts = null;
+  /**
+   * 动态摘要(summary)信息
+   * 
+   * @var \OpenSearch\Generated\Search\Summary[]
+   */
+  public $summaries = null;
+  /**
+   * 设置查询分析规则(qp)
+   * 
+   * @var string[]
+   */
+  public $queryProcessorNames = null;
+  /**
+   * @var \OpenSearch\Generated\Search\DeepPaging
+   */
+  public $deepPaging = null;
+  /**
+   * 关闭某些功能模块(disable)
+   * 
+   * 有如下场景需要考虑:
+   * 1、如果要关闭整个qp的功能,则指定disableValue="qp"。
+   * 2、要指定某个索引关闭某个功能,则可以指定disableValue="qp:function_name:index_names",
+   *   其中index_names可以用“|”分隔,可以为index_name1|index_name2...
+   * 3、如果要关闭多个function可以用“,”分隔,例如:disableValue="qp:function_name1:index_name1,qp:function_name2:index_name1"
+   * 
+   * qp有如下模块:
+   * 1、spell_check: 检查用户查询串中的拼写错误,并给出纠错建议。
+   * 2、term_weighting: 分析查询中每个词的重要程度,并将其量化成权重,权重较低的词可能不会参与召回。
+   * 3、stop_word: 根据系统内置的停用词典过滤查询中无意义的词
+   * 4、synonym: 根据系统提供的通用同义词库和语义模型,对查询串进行同义词扩展,以便扩大召回。
+   * 
+   * example:
+   * "qp" 标示关闭整个qp
+   * "qp:spell_check" 标示关闭qp的拼音纠错功能。
+   * "qp:stop_word:index_name1|index_name2" 标示关闭qp中index_name1和index_name2上的停用词功能。
+   * 
+   * key 需要禁用的函数名称
+   * value 待禁用函数的详细说明
+   * 
+   * @var array
+   */
+  public $disableFunctions = null;
+  /**
+   * @var array
+   */
+  public $customParam = null;
+  /**
+   * 下拉提示是搜索服务的基础功能,在用户输入查询词的过程中,智能推荐候选query,减少用户输入,帮助用户尽快找到想要的内容。
+   * OpenSearch下拉提示在实现了中文前缀,拼音全拼,拼音首字母简拼查询等通用功能的基础上,实现了基于用户文档内容的query智能识别。
+   * 用户通过控制台的简单配置,就能拥有专属的定制下拉提示。此外,控制台上还提供了黑名单,推荐词条功能,让用户进一步控制下拉提示
+   * 的结果,实现更灵活的定制。
+   * 
+   * 
+   * @var \OpenSearch\Generated\Search\Suggest
+   */
+  public $suggest = null;
+  /**
+   * Abtest
+   * 
+   * @var \OpenSearch\Generated\Search\Abtest
+   */
+  public $abtest = null;
+  /**
+   * 终端用户的id,用来统计uv信息
+   * 
+   * @var string
+   */
+  public $userId = null;
+  /**
+   * 终端用户输入的query
+   * 
+   * @var string
+   */
+  public $rawQuery = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        3 => array(
+          'var' => 'config',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Search\Config',
+          ),
+        5 => array(
+          'var' => 'query',
+          'type' => TType::STRING,
+          ),
+        7 => array(
+          'var' => 'filter',
+          'type' => TType::STRING,
+          ),
+        9 => array(
+          'var' => 'sort',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Search\Sort',
+          ),
+        11 => array(
+          'var' => 'rank',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Search\Rank',
+          ),
+        13 => array(
+          'var' => 'aggregates',
+          'type' => TType::SET,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\Search\Aggregate',
+            ),
+          ),
+        15 => array(
+          'var' => 'distincts',
+          'type' => TType::SET,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\Search\Distinct',
+            ),
+          ),
+        17 => array(
+          'var' => 'summaries',
+          'type' => TType::SET,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\Search\Summary',
+            ),
+          ),
+        19 => array(
+          'var' => 'queryProcessorNames',
+          'type' => TType::LST,
+          'etype' => TType::STRING,
+          'elem' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        21 => array(
+          'var' => 'deepPaging',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Search\DeepPaging',
+          ),
+        23 => array(
+          'var' => 'disableFunctions',
+          'type' => TType::MAP,
+          'ktype' => TType::STRING,
+          'vtype' => TType::STRING,
+          'key' => array(
+            'type' => TType::STRING,
+          ),
+          'val' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        27 => array(
+          'var' => 'customParam',
+          'type' => TType::MAP,
+          'ktype' => TType::STRING,
+          'vtype' => TType::STRING,
+          'key' => array(
+            'type' => TType::STRING,
+          ),
+          'val' => array(
+            'type' => TType::STRING,
+            ),
+          ),
+        29 => array(
+          'var' => 'suggest',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Search\Suggest',
+          ),
+        30 => array(
+          'var' => 'abtest',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Search\Abtest',
+          ),
+        31 => array(
+          'var' => 'userId',
+          'type' => TType::STRING,
+          ),
+        32 => array(
+          'var' => 'rawQuery',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    $this->rank = new \OpenSearch\Generated\Search\Rank(array(
+      "reRankSize" => 200,
+    ));
+    if (is_array($vals)) {
+      if (isset($vals['config'])) {
+        $this->config = $vals['config'];
+      }
+      if (isset($vals['query'])) {
+        $this->query = $vals['query'];
+      }
+      if (isset($vals['filter'])) {
+        $this->filter = $vals['filter'];
+      }
+      if (isset($vals['sort'])) {
+        $this->sort = $vals['sort'];
+      }
+      if (isset($vals['rank'])) {
+        $this->rank = $vals['rank'];
+      }
+      if (isset($vals['aggregates'])) {
+        $this->aggregates = $vals['aggregates'];
+      }
+      if (isset($vals['distincts'])) {
+        $this->distincts = $vals['distincts'];
+      }
+      if (isset($vals['summaries'])) {
+        $this->summaries = $vals['summaries'];
+      }
+      if (isset($vals['queryProcessorNames'])) {
+        $this->queryProcessorNames = $vals['queryProcessorNames'];
+      }
+      if (isset($vals['deepPaging'])) {
+        $this->deepPaging = $vals['deepPaging'];
+      }
+      if (isset($vals['disableFunctions'])) {
+        $this->disableFunctions = $vals['disableFunctions'];
+      }
+      if (isset($vals['customParam'])) {
+        $this->customParam = $vals['customParam'];
+      }
+      if (isset($vals['suggest'])) {
+        $this->suggest = $vals['suggest'];
+      }
+      if (isset($vals['abtest'])) {
+        $this->abtest = $vals['abtest'];
+      }
+      if (isset($vals['userId'])) {
+        $this->userId = $vals['userId'];
+      }
+      if (isset($vals['rawQuery'])) {
+        $this->rawQuery = $vals['rawQuery'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SearchParams';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 3:
+          if ($ftype == TType::STRUCT) {
+            $this->config = new \OpenSearch\Generated\Search\Config();
+            $xfer += $this->config->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 5:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->query);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 7:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->filter);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 9:
+          if ($ftype == TType::STRUCT) {
+            $this->sort = new \OpenSearch\Generated\Search\Sort();
+            $xfer += $this->sort->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 11:
+          if ($ftype == TType::STRUCT) {
+            $this->rank = new \OpenSearch\Generated\Search\Rank();
+            $xfer += $this->rank->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 13:
+          if ($ftype == TType::SET) {
+            $this->aggregates = array();
+            $_size28 = 0;
+            $_etype31 = 0;
+            $xfer += $input->readSetBegin($_etype31, $_size28);
+            for ($_i32 = 0; $_i32 < $_size28; ++$_i32)
+            {
+              $elem33 = null;
+              $elem33 = new \OpenSearch\Generated\Search\Aggregate();
+              $xfer += $elem33->read($input);
+              if (is_scalar($elem33)) {
+                $this->aggregates[$elem33] = true;
+              } else {
+                $this->aggregates []= $elem33;
+              }
+            }
+            $xfer += $input->readSetEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 15:
+          if ($ftype == TType::SET) {
+            $this->distincts = array();
+            $_size34 = 0;
+            $_etype37 = 0;
+            $xfer += $input->readSetBegin($_etype37, $_size34);
+            for ($_i38 = 0; $_i38 < $_size34; ++$_i38)
+            {
+              $elem39 = null;
+              $elem39 = new \OpenSearch\Generated\Search\Distinct();
+              $xfer += $elem39->read($input);
+              if (is_scalar($elem39)) {
+                $this->distincts[$elem39] = true;
+              } else {
+                $this->distincts []= $elem39;
+              }
+            }
+            $xfer += $input->readSetEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 17:
+          if ($ftype == TType::SET) {
+            $this->summaries = array();
+            $_size40 = 0;
+            $_etype43 = 0;
+            $xfer += $input->readSetBegin($_etype43, $_size40);
+            for ($_i44 = 0; $_i44 < $_size40; ++$_i44)
+            {
+              $elem45 = null;
+              $elem45 = new \OpenSearch\Generated\Search\Summary();
+              $xfer += $elem45->read($input);
+              if (is_scalar($elem45)) {
+                $this->summaries[$elem45] = true;
+              } else {
+                $this->summaries []= $elem45;
+              }
+            }
+            $xfer += $input->readSetEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 19:
+          if ($ftype == TType::LST) {
+            $this->queryProcessorNames = array();
+            $_size46 = 0;
+            $_etype49 = 0;
+            $xfer += $input->readListBegin($_etype49, $_size46);
+            for ($_i50 = 0; $_i50 < $_size46; ++$_i50)
+            {
+              $elem51 = null;
+              $xfer += $input->readString($elem51);
+              $this->queryProcessorNames []= $elem51;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 21:
+          if ($ftype == TType::STRUCT) {
+            $this->deepPaging = new \OpenSearch\Generated\Search\DeepPaging();
+            $xfer += $this->deepPaging->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 23:
+          if ($ftype == TType::MAP) {
+            $this->disableFunctions = array();
+            $_size52 = 0;
+            $_ktype53 = 0;
+            $_vtype54 = 0;
+            $xfer += $input->readMapBegin($_ktype53, $_vtype54, $_size52);
+            for ($_i56 = 0; $_i56 < $_size52; ++$_i56)
+            {
+              $key57 = '';
+              $val58 = '';
+              $xfer += $input->readString($key57);
+              $xfer += $input->readString($val58);
+              $this->disableFunctions[$key57] = $val58;
+            }
+            $xfer += $input->readMapEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 27:
+          if ($ftype == TType::MAP) {
+            $this->customParam = array();
+            $_size59 = 0;
+            $_ktype60 = 0;
+            $_vtype61 = 0;
+            $xfer += $input->readMapBegin($_ktype60, $_vtype61, $_size59);
+            for ($_i63 = 0; $_i63 < $_size59; ++$_i63)
+            {
+              $key64 = '';
+              $val65 = '';
+              $xfer += $input->readString($key64);
+              $xfer += $input->readString($val65);
+              $this->customParam[$key64] = $val65;
+            }
+            $xfer += $input->readMapEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 29:
+          if ($ftype == TType::STRUCT) {
+            $this->suggest = new \OpenSearch\Generated\Search\Suggest();
+            $xfer += $this->suggest->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 30:
+          if ($ftype == TType::STRUCT) {
+            $this->abtest = new \OpenSearch\Generated\Search\Abtest();
+            $xfer += $this->abtest->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 31:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->userId);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 32:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->rawQuery);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SearchParams');
+    if ($this->config !== null) {
+      if (!is_object($this->config)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('config', TType::STRUCT, 3);
+      $xfer += $this->config->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->query !== null) {
+      $xfer += $output->writeFieldBegin('query', TType::STRING, 5);
+      $xfer += $output->writeString($this->query);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->filter !== null) {
+      $xfer += $output->writeFieldBegin('filter', TType::STRING, 7);
+      $xfer += $output->writeString($this->filter);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->sort !== null) {
+      if (!is_object($this->sort)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('sort', TType::STRUCT, 9);
+      $xfer += $this->sort->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->rank !== null) {
+      if (!is_object($this->rank)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('rank', TType::STRUCT, 11);
+      $xfer += $this->rank->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->aggregates !== null) {
+      if (!is_array($this->aggregates)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('aggregates', TType::SET, 13);
+      {
+        $output->writeSetBegin(TType::STRUCT, count($this->aggregates));
+        {
+          foreach ($this->aggregates as $iter66 => $iter67)
+          {
+            if (is_scalar($iter67)) {
+            $xfer += $iter66->write($output);
+            } else {
+            $xfer += $iter67->write($output);
+            }
+          }
+        }
+        $output->writeSetEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->distincts !== null) {
+      if (!is_array($this->distincts)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('distincts', TType::SET, 15);
+      {
+        $output->writeSetBegin(TType::STRUCT, count($this->distincts));
+        {
+          foreach ($this->distincts as $iter68 => $iter69)
+          {
+            if (is_scalar($iter69)) {
+            $xfer += $iter68->write($output);
+            } else {
+            $xfer += $iter69->write($output);
+            }
+          }
+        }
+        $output->writeSetEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->summaries !== null) {
+      if (!is_array($this->summaries)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('summaries', TType::SET, 17);
+      {
+        $output->writeSetBegin(TType::STRUCT, count($this->summaries));
+        {
+          foreach ($this->summaries as $iter70 => $iter71)
+          {
+            if (is_scalar($iter71)) {
+            $xfer += $iter70->write($output);
+            } else {
+            $xfer += $iter71->write($output);
+            }
+          }
+        }
+        $output->writeSetEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->queryProcessorNames !== null) {
+      if (!is_array($this->queryProcessorNames)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('queryProcessorNames', TType::LST, 19);
+      {
+        $output->writeListBegin(TType::STRING, count($this->queryProcessorNames));
+        {
+          foreach ($this->queryProcessorNames as $iter72)
+          {
+            $xfer += $output->writeString($iter72);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->deepPaging !== null) {
+      if (!is_object($this->deepPaging)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('deepPaging', TType::STRUCT, 21);
+      $xfer += $this->deepPaging->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->disableFunctions !== null) {
+      if (!is_array($this->disableFunctions)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('disableFunctions', TType::MAP, 23);
+      {
+        $output->writeMapBegin(TType::STRING, TType::STRING, count($this->disableFunctions));
+        {
+          foreach ($this->disableFunctions as $kiter73 => $viter74)
+          {
+            $xfer += $output->writeString($kiter73);
+            $xfer += $output->writeString($viter74);
+          }
+        }
+        $output->writeMapEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->customParam !== null) {
+      if (!is_array($this->customParam)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('customParam', TType::MAP, 27);
+      {
+        $output->writeMapBegin(TType::STRING, TType::STRING, count($this->customParam));
+        {
+          foreach ($this->customParam as $kiter75 => $viter76)
+          {
+            $xfer += $output->writeString($kiter75);
+            $xfer += $output->writeString($viter76);
+          }
+        }
+        $output->writeMapEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->suggest !== null) {
+      if (!is_object($this->suggest)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('suggest', TType::STRUCT, 29);
+      $xfer += $this->suggest->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->abtest !== null) {
+      if (!is_object($this->abtest)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('abtest', TType::STRUCT, 30);
+      $xfer += $this->abtest->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->userId !== null) {
+      $xfer += $output->writeFieldBegin('userId', TType::STRING, 31);
+      $xfer += $output->writeString($this->userId);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->rawQuery !== null) {
+      $xfer += $output->writeFieldBegin('rawQuery', TType::STRING, 32);
+      $xfer += $output->writeString($this->rawQuery);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+final class Constant extends \Thrift\Type\TConstant {
+  static protected $CONFIG_CLAUSE_START;
+  static protected $CONFIG_CLAUSE_HIT;
+  static protected $CONFIG_CLAUSE_RERANK_SIZE;
+  static protected $CONFIG_CLAUSE_FORMAT;
+  static protected $SORT_CLAUSE_INCREASE;
+  static protected $SORT_CLAUSE_DECREASE;
+  static protected $SORT_CLAUSE_RANK;
+  static protected $DISTINCT_CLAUSE_DIST_KEY;
+  static protected $DISTINCT_CLAUSE_DIST_COUNT;
+  static protected $DISTINCT_CLAUSE_DIST_TIMES;
+  static protected $DISTINCT_CLAUSE_RESERVED;
+  static protected $DISTINCT_CLAUSE_DIST_FILTER;
+  static protected $DISTINCT_CLAUSE_UPDATE_TOTAL_HIT;
+  static protected $DISTINCT_CLAUSE_GRADE;
+  static protected $AGGREGATE_CLAUSE_GROUP_KEY;
+  static protected $AGGREGATE_CLAUSE_AGG_FUN;
+  static protected $AGGREGATE_CLAUSE_RANGE;
+  static protected $AGGREGATE_CLAUSE_MAX_GROUP;
+  static protected $AGGREGATE_CLAUSE_AGG_FILTER;
+  static protected $AGGREGATE_CLAUSE_AGG_SAMPLER_THRESHOLD;
+  static protected $AGGREGATE_CLAUSE_AGG_SAMPLER_STEP;
+  static protected $SUMMARY_PARAM_SUMMARY_FIELD;
+  static protected $SUMMARY_PARAM_SUMMARY_LEN;
+  static protected $SUMMARY_PARAM_SUMMARY_ELLIPSIS;
+  static protected $SUMMARY_PARAM_SUMMARY_SNIPPET;
+  static protected $SUMMARY_PARAM_SUMMARY_ELEMENT;
+  static protected $SUMMARY_PARAM_SUMMARY_ELEMENT_PREFIX;
+  static protected $SUMMARY_PARAM_SUMMARY_ELEMENT_POSTFIX;
+  static protected $FORMAT_PARAM;
+  static protected $ABTEST_PARAM_SCENE_TAG;
+  static protected $ABTEST_PARAM_FLOW_DIVIDER;
+  static protected $USER_ID;
+  static protected $RAW_QUERY;
+
+  static protected function init_CONFIG_CLAUSE_START() {
+    return "start";
+  }
+
+  static protected function init_CONFIG_CLAUSE_HIT() {
+    return "hit";
+  }
+
+  static protected function init_CONFIG_CLAUSE_RERANK_SIZE() {
+    return "rerank_size";
+  }
+
+  static protected function init_CONFIG_CLAUSE_FORMAT() {
+    return "format";
+  }
+
+  static protected function init_SORT_CLAUSE_INCREASE() {
+    return "+";
+  }
+
+  static protected function init_SORT_CLAUSE_DECREASE() {
+    return "-";
+  }
+
+  static protected function init_SORT_CLAUSE_RANK() {
+    return "RANK";
+  }
+
+  static protected function init_DISTINCT_CLAUSE_DIST_KEY() {
+    return "dist_key";
+  }
+
+  static protected function init_DISTINCT_CLAUSE_DIST_COUNT() {
+    return "dist_count";
+  }
+
+  static protected function init_DISTINCT_CLAUSE_DIST_TIMES() {
+    return "dist_times";
+  }
+
+  static protected function init_DISTINCT_CLAUSE_RESERVED() {
+    return "reserved";
+  }
+
+  static protected function init_DISTINCT_CLAUSE_DIST_FILTER() {
+    return "dist_filter";
+  }
+
+  static protected function init_DISTINCT_CLAUSE_UPDATE_TOTAL_HIT() {
+    return "update_total_hit";
+  }
+
+  static protected function init_DISTINCT_CLAUSE_GRADE() {
+    return "grade";
+  }
+
+  static protected function init_AGGREGATE_CLAUSE_GROUP_KEY() {
+    return "group_key";
+  }
+
+  static protected function init_AGGREGATE_CLAUSE_AGG_FUN() {
+    return "agg_fun";
+  }
+
+  static protected function init_AGGREGATE_CLAUSE_RANGE() {
+    return "range";
+  }
+
+  static protected function init_AGGREGATE_CLAUSE_MAX_GROUP() {
+    return "max_group";
+  }
+
+  static protected function init_AGGREGATE_CLAUSE_AGG_FILTER() {
+    return "agg_filter";
+  }
+
+  static protected function init_AGGREGATE_CLAUSE_AGG_SAMPLER_THRESHOLD() {
+    return "agg_sampler_threshold";
+  }
+
+  static protected function init_AGGREGATE_CLAUSE_AGG_SAMPLER_STEP() {
+    return "agg_sampler_step";
+  }
+
+  static protected function init_SUMMARY_PARAM_SUMMARY_FIELD() {
+    return "summary_field";
+  }
+
+  static protected function init_SUMMARY_PARAM_SUMMARY_LEN() {
+    return "summary_len";
+  }
+
+  static protected function init_SUMMARY_PARAM_SUMMARY_ELLIPSIS() {
+    return "summary_ellipsis";
+  }
+
+  static protected function init_SUMMARY_PARAM_SUMMARY_SNIPPET() {
+    return "summary_snippet";
+  }
+
+  static protected function init_SUMMARY_PARAM_SUMMARY_ELEMENT() {
+    return "summary_element";
+  }
+
+  static protected function init_SUMMARY_PARAM_SUMMARY_ELEMENT_PREFIX() {
+    return "summary_element_prefix";
+  }
+
+  static protected function init_SUMMARY_PARAM_SUMMARY_ELEMENT_POSTFIX() {
+    return "summary_element_postfix";
+  }
+
+  static protected function init_FORMAT_PARAM() {
+    return "format";
+  }
+
+  static protected function init_ABTEST_PARAM_SCENE_TAG() {
+    return "scene_tag";
+  }
+
+  static protected function init_ABTEST_PARAM_FLOW_DIVIDER() {
+    return "flow_divider";
+  }
+
+  static protected function init_USER_ID() {
+    return "user_id";
+  }
+
+  static protected function init_RAW_QUERY() {
+    return "raw_query";
+  }
+}
+
+

+ 1910 - 0
php/OpenSearch/Generated/SecondRank/SecondRankService.php

@@ -0,0 +1,1910 @@
+<?php
+namespace OpenSearch\Generated\SecondRank;
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+interface SecondRankServiceIf {
+  /**
+   * @param \OpenSearch\Generated\SecondRank\SecondRank $secondRank
+   * @return \OpenSearch\Generated\SecondRank\SecondRank
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function save(\OpenSearch\Generated\SecondRank\SecondRank $secondRank);
+  /**
+   * @return \OpenSearch\Generated\SecondRank\SecondRank[]
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function listAll();
+  /**
+   * @param string $id
+   * @return \OpenSearch\Generated\SecondRank\SecondRank
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function getById($id);
+  /**
+   * @param string $appId
+   * @param string $name
+   * @return \OpenSearch\Generated\SecondRank\SecondRank[]
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function listByAppIdAndName($appId, $name);
+  /**
+   * @param string $id
+   * @param \OpenSearch\Generated\SecondRank\SecondRank $secondRank
+   * @return \OpenSearch\Generated\SecondRank\SecondRank
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function updateById($id, \OpenSearch\Generated\SecondRank\SecondRank $secondRank);
+  /**
+   * @param string $id
+   * @return \OpenSearch\Generated\SecondRank\SecondRank
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function removeById($id);
+}
+
+
+class SecondRankServiceClient implements \OpenSearch\Generated\SecondRank\SecondRankServiceIf {
+  protected $input_ = null;
+  protected $output_ = null;
+
+  protected $seqid_ = 0;
+
+  public function __construct($input, $output=null) {
+    $this->input_ = $input;
+    $this->output_ = $output ? $output : $input;
+  }
+
+  public function save(\OpenSearch\Generated\SecondRank\SecondRank $secondRank)
+  {
+    $this->send_save($secondRank);
+    return $this->recv_save();
+  }
+
+  public function send_save(\OpenSearch\Generated\SecondRank\SecondRank $secondRank)
+  {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_save_args();
+    $args->secondRank = $secondRank;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'save', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('save', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_save()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\SecondRank\SecondRankService_save_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\SecondRank\SecondRankService_save_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("save failed: unknown result");
+  }
+
+  public function listAll()
+  {
+    $this->send_listAll();
+    return $this->recv_listAll();
+  }
+
+  public function send_listAll()
+  {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_listAll_args();
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'listAll', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('listAll', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_listAll()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\SecondRank\SecondRankService_listAll_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\SecondRank\SecondRankService_listAll_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("listAll failed: unknown result");
+  }
+
+  public function getById($id)
+  {
+    $this->send_getById($id);
+    return $this->recv_getById();
+  }
+
+  public function send_getById($id)
+  {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_getById_args();
+    $args->id = $id;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'getById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('getById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_getById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\SecondRank\SecondRankService_getById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\SecondRank\SecondRankService_getById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("getById failed: unknown result");
+  }
+
+  public function listByAppIdAndName($appId, $name)
+  {
+    $this->send_listByAppIdAndName($appId, $name);
+    return $this->recv_listByAppIdAndName();
+  }
+
+  public function send_listByAppIdAndName($appId, $name)
+  {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_listByAppIdAndName_args();
+    $args->appId = $appId;
+    $args->name = $name;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'listByAppIdAndName', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('listByAppIdAndName', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_listByAppIdAndName()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\SecondRank\SecondRankService_listByAppIdAndName_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\SecondRank\SecondRankService_listByAppIdAndName_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("listByAppIdAndName failed: unknown result");
+  }
+
+  public function updateById($id, \OpenSearch\Generated\SecondRank\SecondRank $secondRank)
+  {
+    $this->send_updateById($id, $secondRank);
+    return $this->recv_updateById();
+  }
+
+  public function send_updateById($id, \OpenSearch\Generated\SecondRank\SecondRank $secondRank)
+  {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_updateById_args();
+    $args->id = $id;
+    $args->secondRank = $secondRank;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'updateById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('updateById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_updateById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\SecondRank\SecondRankService_updateById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\SecondRank\SecondRankService_updateById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("updateById failed: unknown result");
+  }
+
+  public function removeById($id)
+  {
+    $this->send_removeById($id);
+    return $this->recv_removeById();
+  }
+
+  public function send_removeById($id)
+  {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_removeById_args();
+    $args->id = $id;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'removeById', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('removeById', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_removeById()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\SecondRank\SecondRankService_removeById_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\SecondRank\SecondRankService_removeById_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("removeById failed: unknown result");
+  }
+
+}
+
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+class SecondRankService_save_args {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\SecondRank\SecondRank
+   */
+  public $secondRank = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'secondRank',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\SecondRank\SecondRank',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['secondRank'])) {
+        $this->secondRank = $vals['secondRank'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_save_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->secondRank = new \OpenSearch\Generated\SecondRank\SecondRank();
+            $xfer += $this->secondRank->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_save_args');
+    if ($this->secondRank !== null) {
+      if (!is_object($this->secondRank)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('secondRank', TType::STRUCT, 1);
+      $xfer += $this->secondRank->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_save_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\SecondRank\SecondRank
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\SecondRank\SecondRank',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_save_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\SecondRank\SecondRank();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_save_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_listAll_args {
+  static $_TSPEC;
+
+
+  public function __construct() {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        );
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_listAll_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_listAll_args');
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_listAll_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\SecondRank\SecondRank[]
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::LST,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\SecondRank\SecondRank',
+            ),
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_listAll_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::LST) {
+            $this->success = array();
+            $_size0 = 0;
+            $_etype3 = 0;
+            $xfer += $input->readListBegin($_etype3, $_size0);
+            for ($_i4 = 0; $_i4 < $_size0; ++$_i4)
+            {
+              $elem5 = null;
+              $elem5 = new \OpenSearch\Generated\SecondRank\SecondRank();
+              $xfer += $elem5->read($input);
+              $this->success []= $elem5;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_listAll_result');
+    if ($this->success !== null) {
+      if (!is_array($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::LST, 0);
+      {
+        $output->writeListBegin(TType::STRUCT, count($this->success));
+        {
+          foreach ($this->success as $iter6)
+          {
+            $xfer += $iter6->write($output);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_getById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $id = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'id',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['id'])) {
+        $this->id = $vals['id'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_getById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->id);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_getById_args');
+    if ($this->id !== null) {
+      $xfer += $output->writeFieldBegin('id', TType::STRING, 1);
+      $xfer += $output->writeString($this->id);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_getById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\SecondRank\SecondRank
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\SecondRank\SecondRank',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_getById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\SecondRank\SecondRank();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_getById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_listByAppIdAndName_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $appId = null;
+  /**
+   * @var string
+   */
+  public $name = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'appId',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'name',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['appId'])) {
+        $this->appId = $vals['appId'];
+      }
+      if (isset($vals['name'])) {
+        $this->name = $vals['name'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_listByAppIdAndName_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->appId);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->name);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_listByAppIdAndName_args');
+    if ($this->appId !== null) {
+      $xfer += $output->writeFieldBegin('appId', TType::STRING, 1);
+      $xfer += $output->writeString($this->appId);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->name !== null) {
+      $xfer += $output->writeFieldBegin('name', TType::STRING, 2);
+      $xfer += $output->writeString($this->name);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_listByAppIdAndName_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\SecondRank\SecondRank[]
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::LST,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\SecondRank\SecondRank',
+            ),
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_listByAppIdAndName_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::LST) {
+            $this->success = array();
+            $_size7 = 0;
+            $_etype10 = 0;
+            $xfer += $input->readListBegin($_etype10, $_size7);
+            for ($_i11 = 0; $_i11 < $_size7; ++$_i11)
+            {
+              $elem12 = null;
+              $elem12 = new \OpenSearch\Generated\SecondRank\SecondRank();
+              $xfer += $elem12->read($input);
+              $this->success []= $elem12;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_listByAppIdAndName_result');
+    if ($this->success !== null) {
+      if (!is_array($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::LST, 0);
+      {
+        $output->writeListBegin(TType::STRUCT, count($this->success));
+        {
+          foreach ($this->success as $iter13)
+          {
+            $xfer += $iter13->write($output);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_updateById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $id = null;
+  /**
+   * @var \OpenSearch\Generated\SecondRank\SecondRank
+   */
+  public $secondRank = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'id',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'secondRank',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\SecondRank\SecondRank',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['id'])) {
+        $this->id = $vals['id'];
+      }
+      if (isset($vals['secondRank'])) {
+        $this->secondRank = $vals['secondRank'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_updateById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->id);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->secondRank = new \OpenSearch\Generated\SecondRank\SecondRank();
+            $xfer += $this->secondRank->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_updateById_args');
+    if ($this->id !== null) {
+      $xfer += $output->writeFieldBegin('id', TType::STRING, 1);
+      $xfer += $output->writeString($this->id);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->secondRank !== null) {
+      if (!is_object($this->secondRank)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('secondRank', TType::STRUCT, 2);
+      $xfer += $this->secondRank->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_updateById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\SecondRank\SecondRank
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\SecondRank\SecondRank',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_updateById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\SecondRank\SecondRank();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_updateById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_removeById_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $id = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'id',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['id'])) {
+        $this->id = $vals['id'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_removeById_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->id);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_removeById_args');
+    if ($this->id !== null) {
+      $xfer += $output->writeFieldBegin('id', TType::STRING, 1);
+      $xfer += $output->writeString($this->id);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankService_removeById_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\SecondRank\SecondRank
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\SecondRank\SecondRank',
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRankService_removeById_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::STRUCT) {
+            $this->success = new \OpenSearch\Generated\SecondRank\SecondRank();
+            $xfer += $this->success->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRankService_removeById_result');
+    if ($this->success !== null) {
+      if (!is_object($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::STRUCT, 0);
+      $xfer += $this->success->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SecondRankServiceProcessor {
+  protected $handler_ = null;
+  public function __construct($handler) {
+    $this->handler_ = $handler;
+  }
+
+  public function process($input, $output) {
+    $rseqid = 0;
+    $fname = null;
+    $mtype = 0;
+
+    $input->readMessageBegin($fname, $mtype, $rseqid);
+    $methodname = 'process_'.$fname;
+    if (!method_exists($this, $methodname)) {
+      $input->skip(TType::STRUCT);
+      $input->readMessageEnd();
+      $x = new TApplicationException('Function '.$fname.' not implemented.', TApplicationException::UNKNOWN_METHOD);
+      $output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid);
+      $x->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+      return;
+    }
+    $this->$methodname($rseqid, $input, $output);
+    return true;
+  }
+
+  protected function process_save($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_save_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\SecondRank\SecondRankService_save_result();
+    try {
+      $result->success = $this->handler_->save($args->secondRank);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'save', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('save', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_listAll($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_listAll_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\SecondRank\SecondRankService_listAll_result();
+    try {
+      $result->success = $this->handler_->listAll();
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'listAll', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('listAll', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_getById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_getById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\SecondRank\SecondRankService_getById_result();
+    try {
+      $result->success = $this->handler_->getById($args->id);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'getById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('getById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_listByAppIdAndName($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_listByAppIdAndName_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\SecondRank\SecondRankService_listByAppIdAndName_result();
+    try {
+      $result->success = $this->handler_->listByAppIdAndName($args->appId, $args->name);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'listByAppIdAndName', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('listByAppIdAndName', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_updateById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_updateById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\SecondRank\SecondRankService_updateById_result();
+    try {
+      $result->success = $this->handler_->updateById($args->id, $args->secondRank);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'updateById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('updateById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+  protected function process_removeById($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\SecondRank\SecondRankService_removeById_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\SecondRank\SecondRankService_removeById_result();
+    try {
+      $result->success = $this->handler_->removeById($args->id);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'removeById', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('removeById', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+}
+

+ 146 - 0
php/OpenSearch/Generated/SecondRank/Types.php

@@ -0,0 +1,146 @@
+<?php
+namespace OpenSearch\Generated\SecondRank;
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+class SecondRank {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $id = null;
+  /**
+   * @var \OpenSearch\Generated\Common\AppReference
+   */
+  public $app = null;
+  /**
+   * @var string
+   */
+  public $name = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'id',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'app',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\AppReference',
+          ),
+        10 => array(
+          'var' => 'name',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['id'])) {
+        $this->id = $vals['id'];
+      }
+      if (isset($vals['app'])) {
+        $this->app = $vals['app'];
+      }
+      if (isset($vals['name'])) {
+        $this->name = $vals['name'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SecondRank';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->id);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->app = new \OpenSearch\Generated\Common\AppReference();
+            $xfer += $this->app->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 10:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->name);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SecondRank');
+    if ($this->id !== null) {
+      $xfer += $output->writeFieldBegin('id', TType::STRING, 1);
+      $xfer += $output->writeString($this->id);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->app !== null) {
+      if (!is_object($this->app)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('app', TType::STRUCT, 2);
+      $xfer += $this->app->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->name !== null) {
+      $xfer += $output->writeFieldBegin('name', TType::STRING, 10);
+      $xfer += $output->writeString($this->name);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+

+ 409 - 0
php/OpenSearch/Generated/Summary/SummaryService.php

@@ -0,0 +1,409 @@
+<?php
+namespace OpenSearch\Generated\Summary;
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+interface SummaryServiceIf {
+  /**
+   * @param string $appId
+   * @param string $group
+   * @return \OpenSearch\Generated\Summary\Summary[]
+   * @throws \OpenSearch\Generated\Common\OpenSearchException
+   * @throws \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public function listByAppIdAndGroup($appId, $group);
+}
+
+
+class SummaryServiceClient implements \OpenSearch\Generated\Summary\SummaryServiceIf {
+  protected $input_ = null;
+  protected $output_ = null;
+
+  protected $seqid_ = 0;
+
+  public function __construct($input, $output=null) {
+    $this->input_ = $input;
+    $this->output_ = $output ? $output : $input;
+  }
+
+  public function listByAppIdAndGroup($appId, $group)
+  {
+    $this->send_listByAppIdAndGroup($appId, $group);
+    return $this->recv_listByAppIdAndGroup();
+  }
+
+  public function send_listByAppIdAndGroup($appId, $group)
+  {
+    $args = new \OpenSearch\Generated\Summary\SummaryService_listByAppIdAndGroup_args();
+    $args->appId = $appId;
+    $args->group = $group;
+    $bin_accel = ($this->output_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($this->output_, 'listByAppIdAndGroup', TMessageType::CALL, $args, $this->seqid_, $this->output_->isStrictWrite());
+    }
+    else
+    {
+      $this->output_->writeMessageBegin('listByAppIdAndGroup', TMessageType::CALL, $this->seqid_);
+      $args->write($this->output_);
+      $this->output_->writeMessageEnd();
+      $this->output_->getTransport()->flush();
+    }
+  }
+
+  public function recv_listByAppIdAndGroup()
+  {
+    $bin_accel = ($this->input_ instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary');
+    if ($bin_accel) $result = thrift_protocol_read_binary($this->input_, '\OpenSearch\Generated\Summary\SummaryService_listByAppIdAndGroup_result', $this->input_->isStrictRead());
+    else
+    {
+      $rseqid = 0;
+      $fname = null;
+      $mtype = 0;
+
+      $this->input_->readMessageBegin($fname, $mtype, $rseqid);
+      if ($mtype == TMessageType::EXCEPTION) {
+        $x = new TApplicationException();
+        $x->read($this->input_);
+        $this->input_->readMessageEnd();
+        throw $x;
+      }
+      $result = new \OpenSearch\Generated\Summary\SummaryService_listByAppIdAndGroup_result();
+      $result->read($this->input_);
+      $this->input_->readMessageEnd();
+    }
+    if ($result->success !== null) {
+      return $result->success;
+    }
+    if ($result->error !== null) {
+      throw $result->error;
+    }
+    if ($result->e !== null) {
+      throw $result->e;
+    }
+    throw new \Exception("listByAppIdAndGroup failed: unknown result");
+  }
+
+}
+
+
+// HELPER FUNCTIONS AND STRUCTURES
+
+class SummaryService_listByAppIdAndGroup_args {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $appId = null;
+  /**
+   * @var string
+   */
+  public $group = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'appId',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'group',
+          'type' => TType::STRING,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['appId'])) {
+        $this->appId = $vals['appId'];
+      }
+      if (isset($vals['group'])) {
+        $this->group = $vals['group'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SummaryService_listByAppIdAndGroup_args';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->appId);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->group);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SummaryService_listByAppIdAndGroup_args');
+    if ($this->appId !== null) {
+      $xfer += $output->writeFieldBegin('appId', TType::STRING, 1);
+      $xfer += $output->writeString($this->appId);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->group !== null) {
+      $xfer += $output->writeFieldBegin('group', TType::STRING, 2);
+      $xfer += $output->writeString($this->group);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SummaryService_listByAppIdAndGroup_result {
+  static $_TSPEC;
+
+  /**
+   * @var \OpenSearch\Generated\Summary\Summary[]
+   */
+  public $success = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchException
+   */
+  public $error = null;
+  /**
+   * @var \OpenSearch\Generated\Common\OpenSearchClientException
+   */
+  public $e = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        0 => array(
+          'var' => 'success',
+          'type' => TType::LST,
+          'etype' => TType::STRUCT,
+          'elem' => array(
+            'type' => TType::STRUCT,
+            'class' => '\OpenSearch\Generated\Summary\Summary',
+            ),
+          ),
+        1 => array(
+          'var' => 'error',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchException',
+          ),
+        2 => array(
+          'var' => 'e',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\OpenSearchClientException',
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['success'])) {
+        $this->success = $vals['success'];
+      }
+      if (isset($vals['error'])) {
+        $this->error = $vals['error'];
+      }
+      if (isset($vals['e'])) {
+        $this->e = $vals['e'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'SummaryService_listByAppIdAndGroup_result';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 0:
+          if ($ftype == TType::LST) {
+            $this->success = array();
+            $_size0 = 0;
+            $_etype3 = 0;
+            $xfer += $input->readListBegin($_etype3, $_size0);
+            for ($_i4 = 0; $_i4 < $_size0; ++$_i4)
+            {
+              $elem5 = null;
+              $elem5 = new \OpenSearch\Generated\Summary\Summary();
+              $xfer += $elem5->read($input);
+              $this->success []= $elem5;
+            }
+            $xfer += $input->readListEnd();
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 1:
+          if ($ftype == TType::STRUCT) {
+            $this->error = new \OpenSearch\Generated\Common\OpenSearchException();
+            $xfer += $this->error->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->e = new \OpenSearch\Generated\Common\OpenSearchClientException();
+            $xfer += $this->e->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('SummaryService_listByAppIdAndGroup_result');
+    if ($this->success !== null) {
+      if (!is_array($this->success)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('success', TType::LST, 0);
+      {
+        $output->writeListBegin(TType::STRUCT, count($this->success));
+        {
+          foreach ($this->success as $iter6)
+          {
+            $xfer += $iter6->write($output);
+          }
+        }
+        $output->writeListEnd();
+      }
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->error !== null) {
+      $xfer += $output->writeFieldBegin('error', TType::STRUCT, 1);
+      $xfer += $this->error->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->e !== null) {
+      $xfer += $output->writeFieldBegin('e', TType::STRUCT, 2);
+      $xfer += $this->e->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+class SummaryServiceProcessor {
+  protected $handler_ = null;
+  public function __construct($handler) {
+    $this->handler_ = $handler;
+  }
+
+  public function process($input, $output) {
+    $rseqid = 0;
+    $fname = null;
+    $mtype = 0;
+
+    $input->readMessageBegin($fname, $mtype, $rseqid);
+    $methodname = 'process_'.$fname;
+    if (!method_exists($this, $methodname)) {
+      $input->skip(TType::STRUCT);
+      $input->readMessageEnd();
+      $x = new TApplicationException('Function '.$fname.' not implemented.', TApplicationException::UNKNOWN_METHOD);
+      $output->writeMessageBegin($fname, TMessageType::EXCEPTION, $rseqid);
+      $x->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+      return;
+    }
+    $this->$methodname($rseqid, $input, $output);
+    return true;
+  }
+
+  protected function process_listByAppIdAndGroup($seqid, $input, $output) {
+    $args = new \OpenSearch\Generated\Summary\SummaryService_listByAppIdAndGroup_args();
+    $args->read($input);
+    $input->readMessageEnd();
+    $result = new \OpenSearch\Generated\Summary\SummaryService_listByAppIdAndGroup_result();
+    try {
+      $result->success = $this->handler_->listByAppIdAndGroup($args->appId, $args->group);
+    } catch (\OpenSearch\Generated\Common\OpenSearchException $error) {
+      $result->error = $error;
+        } catch (\OpenSearch\Generated\Common\OpenSearchClientException $e) {
+      $result->e = $e;
+    }
+    $bin_accel = ($output instanceof TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');
+    if ($bin_accel)
+    {
+      thrift_protocol_write_binary($output, 'listByAppIdAndGroup', TMessageType::REPLY, $result, $seqid, $output->isStrictWrite());
+    }
+    else
+    {
+      $output->writeMessageBegin('listByAppIdAndGroup', TMessageType::REPLY, $seqid);
+      $result->write($output);
+      $output->writeMessageEnd();
+      $output->getTransport()->flush();
+    }
+  }
+}
+

+ 261 - 0
php/OpenSearch/Generated/Summary/Types.php

@@ -0,0 +1,261 @@
+<?php
+namespace OpenSearch\Generated\Summary;
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+use Thrift\Base\TBase;
+use Thrift\Type\TType;
+use Thrift\Type\TMessageType;
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\TProtocol;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Exception\TApplicationException;
+
+
+class Summary {
+  static $_TSPEC;
+
+  /**
+   * @var string
+   */
+  public $id = null;
+  /**
+   * @var \OpenSearch\Generated\Common\AppReference
+   */
+  public $app = null;
+  /**
+   * @var string
+   */
+  public $field = null;
+  /**
+   * @var string
+   */
+  public $group = null;
+  /**
+   * @var int
+   */
+  public $len = null;
+  /**
+   * @var string
+   */
+  public $element = null;
+  /**
+   * @var string
+   */
+  public $ellipsis = null;
+  /**
+   * @var int
+   */
+  public $snippet = null;
+
+  public function __construct($vals=null) {
+    if (!isset(self::$_TSPEC)) {
+      self::$_TSPEC = array(
+        1 => array(
+          'var' => 'id',
+          'type' => TType::STRING,
+          ),
+        2 => array(
+          'var' => 'app',
+          'type' => TType::STRUCT,
+          'class' => '\OpenSearch\Generated\Common\AppReference',
+          ),
+        10 => array(
+          'var' => 'field',
+          'type' => TType::STRING,
+          ),
+        11 => array(
+          'var' => 'group',
+          'type' => TType::STRING,
+          ),
+        12 => array(
+          'var' => 'len',
+          'type' => TType::I32,
+          ),
+        13 => array(
+          'var' => 'element',
+          'type' => TType::STRING,
+          ),
+        14 => array(
+          'var' => 'ellipsis',
+          'type' => TType::STRING,
+          ),
+        15 => array(
+          'var' => 'snippet',
+          'type' => TType::I32,
+          ),
+        );
+    }
+    if (is_array($vals)) {
+      if (isset($vals['id'])) {
+        $this->id = $vals['id'];
+      }
+      if (isset($vals['app'])) {
+        $this->app = $vals['app'];
+      }
+      if (isset($vals['field'])) {
+        $this->field = $vals['field'];
+      }
+      if (isset($vals['group'])) {
+        $this->group = $vals['group'];
+      }
+      if (isset($vals['len'])) {
+        $this->len = $vals['len'];
+      }
+      if (isset($vals['element'])) {
+        $this->element = $vals['element'];
+      }
+      if (isset($vals['ellipsis'])) {
+        $this->ellipsis = $vals['ellipsis'];
+      }
+      if (isset($vals['snippet'])) {
+        $this->snippet = $vals['snippet'];
+      }
+    }
+  }
+
+  public function getName() {
+    return 'Summary';
+  }
+
+  public function read($input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true)
+    {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      switch ($fid)
+      {
+        case 1:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->id);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 2:
+          if ($ftype == TType::STRUCT) {
+            $this->app = new \OpenSearch\Generated\Common\AppReference();
+            $xfer += $this->app->read($input);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 10:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->field);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 11:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->group);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 12:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->len);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 13:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->element);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 14:
+          if ($ftype == TType::STRING) {
+            $xfer += $input->readString($this->ellipsis);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        case 15:
+          if ($ftype == TType::I32) {
+            $xfer += $input->readI32($this->snippet);
+          } else {
+            $xfer += $input->skip($ftype);
+          }
+          break;
+        default:
+          $xfer += $input->skip($ftype);
+          break;
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+    return $xfer;
+  }
+
+  public function write($output) {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('Summary');
+    if ($this->id !== null) {
+      $xfer += $output->writeFieldBegin('id', TType::STRING, 1);
+      $xfer += $output->writeString($this->id);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->app !== null) {
+      if (!is_object($this->app)) {
+        throw new TProtocolException('Bad type in structure.', TProtocolException::INVALID_DATA);
+      }
+      $xfer += $output->writeFieldBegin('app', TType::STRUCT, 2);
+      $xfer += $this->app->write($output);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->field !== null) {
+      $xfer += $output->writeFieldBegin('field', TType::STRING, 10);
+      $xfer += $output->writeString($this->field);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->group !== null) {
+      $xfer += $output->writeFieldBegin('group', TType::STRING, 11);
+      $xfer += $output->writeString($this->group);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->len !== null) {
+      $xfer += $output->writeFieldBegin('len', TType::I32, 12);
+      $xfer += $output->writeI32($this->len);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->element !== null) {
+      $xfer += $output->writeFieldBegin('element', TType::STRING, 13);
+      $xfer += $output->writeString($this->element);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->ellipsis !== null) {
+      $xfer += $output->writeFieldBegin('ellipsis', TType::STRING, 14);
+      $xfer += $output->writeString($this->ellipsis);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($this->snippet !== null) {
+      $xfer += $output->writeFieldBegin('snippet', TType::I32, 15);
+      $xfer += $output->writeI32($this->snippet);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+    return $xfer;
+  }
+
+}
+
+

+ 380 - 0
php/OpenSearch/Thrift/Base/TBase.php

@@ -0,0 +1,380 @@
+<?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
+ */
+
+namespace Thrift\Base;
+
+use Thrift\Type\TType;
+
+/**
+ * Base class from which other Thrift structs extend. This is so that we can
+ * cut back on the size of the generated code which is turning out to have a
+ * nontrivial cost just to load thanks to the wondrously abysmal implementation
+ * of PHP. Note that code is intentionally duplicated in here to avoid making
+ * function calls for every field or member of a container..
+ */
+abstract class TBase
+{
+  static $tmethod = array(TType::BOOL   => 'Bool',
+                          TType::BYTE   => 'Byte',
+                          TType::I16    => 'I16',
+                          TType::I32    => 'I32',
+                          TType::I64    => 'I64',
+                          TType::DOUBLE => 'Double',
+                          TType::STRING => 'String');
+
+  abstract public function read($input);
+
+  abstract public function write($output);
+
+  public function __construct($spec=null, $vals=null)
+  {
+    if (is_array($spec) && is_array($vals)) {
+      foreach ($spec as $fid => $fspec) {
+        $var = $fspec['var'];
+        if (isset($vals[$var])) {
+          $this->$var = $vals[$var];
+        }
+      }
+    }
+  }
+
+  public function __wakeup()
+  {
+    $this->__construct(get_object_vars($this));
+  }
+
+  private function _readMap(&$var, $spec, $input)
+  {
+    $xfer = 0;
+    $ktype = $spec['ktype'];
+    $vtype = $spec['vtype'];
+    $kread = $vread = null;
+    if (isset(TBase::$tmethod[$ktype])) {
+      $kread = 'read'.TBase::$tmethod[$ktype];
+    } else {
+      $kspec = $spec['key'];
+    }
+    if (isset(TBase::$tmethod[$vtype])) {
+      $vread = 'read'.TBase::$tmethod[$vtype];
+    } else {
+      $vspec = $spec['val'];
+    }
+    $var = array();
+    $_ktype = $_vtype = $size = 0;
+    $xfer += $input->readMapBegin($_ktype, $_vtype, $size);
+    for ($i = 0; $i < $size; ++$i) {
+      $key = $val = null;
+      if ($kread !== null) {
+        $xfer += $input->$kread($key);
+      } else {
+        switch ($ktype) {
+        case TType::STRUCT:
+          $class = $kspec['class'];
+          $key = new $class();
+          $xfer += $key->read($input);
+          break;
+        case TType::MAP:
+          $xfer += $this->_readMap($key, $kspec, $input);
+          break;
+        case TType::LST:
+          $xfer += $this->_readList($key, $kspec, $input, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_readList($key, $kspec, $input, true);
+          break;
+        }
+      }
+      if ($vread !== null) {
+        $xfer += $input->$vread($val);
+      } else {
+        switch ($vtype) {
+        case TType::STRUCT:
+          $class = $vspec['class'];
+          $val = new $class();
+          $xfer += $val->read($input);
+          break;
+        case TType::MAP:
+          $xfer += $this->_readMap($val, $vspec, $input);
+          break;
+        case TType::LST:
+          $xfer += $this->_readList($val, $vspec, $input, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_readList($val, $vspec, $input, true);
+          break;
+        }
+      }
+      $var[$key] = $val;
+    }
+    $xfer += $input->readMapEnd();
+
+    return $xfer;
+  }
+
+  private function _readList(&$var, $spec, $input, $set=false)
+  {
+    $xfer = 0;
+    $etype = $spec['etype'];
+    $eread = $vread = null;
+    if (isset(TBase::$tmethod[$etype])) {
+      $eread = 'read'.TBase::$tmethod[$etype];
+    } else {
+      $espec = $spec['elem'];
+    }
+    $var = array();
+    $_etype = $size = 0;
+    if ($set) {
+      $xfer += $input->readSetBegin($_etype, $size);
+    } else {
+      $xfer += $input->readListBegin($_etype, $size);
+    }
+    for ($i = 0; $i < $size; ++$i) {
+      $elem = null;
+      if ($eread !== null) {
+        $xfer += $input->$eread($elem);
+      } else {
+        $espec = $spec['elem'];
+        switch ($etype) {
+        case TType::STRUCT:
+          $class = $espec['class'];
+          $elem = new $class();
+          $xfer += $elem->read($input);
+          break;
+        case TType::MAP:
+          $xfer += $this->_readMap($elem, $espec, $input);
+          break;
+        case TType::LST:
+          $xfer += $this->_readList($elem, $espec, $input, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_readList($elem, $espec, $input, true);
+          break;
+        }
+      }
+      if ($set) {
+        $var[$elem] = true;
+      } else {
+        $var []= $elem;
+      }
+    }
+    if ($set) {
+      $xfer += $input->readSetEnd();
+    } else {
+      $xfer += $input->readListEnd();
+    }
+
+    return $xfer;
+  }
+
+  protected function _read($class, $spec, $input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true) {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      if (isset($spec[$fid])) {
+        $fspec = $spec[$fid];
+        $var = $fspec['var'];
+        if ($ftype == $fspec['type']) {
+          $xfer = 0;
+          if (isset(TBase::$tmethod[$ftype])) {
+            $func = 'read'.TBase::$tmethod[$ftype];
+            $xfer += $input->$func($this->$var);
+          } else {
+            switch ($ftype) {
+            case TType::STRUCT:
+              $class = $fspec['class'];
+              $this->$var = new $class();
+              $xfer += $this->$var->read($input);
+              break;
+            case TType::MAP:
+              $xfer += $this->_readMap($this->$var, $fspec, $input);
+              break;
+            case TType::LST:
+              $xfer += $this->_readList($this->$var, $fspec, $input, false);
+              break;
+            case TType::SET:
+              $xfer += $this->_readList($this->$var, $fspec, $input, true);
+              break;
+            }
+          }
+        } else {
+          $xfer += $input->skip($ftype);
+        }
+      } else {
+        $xfer += $input->skip($ftype);
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+
+    return $xfer;
+  }
+
+  private function _writeMap($var, $spec, $output)
+  {
+    $xfer = 0;
+    $ktype = $spec['ktype'];
+    $vtype = $spec['vtype'];
+    $kwrite = $vwrite = null;
+    if (isset(TBase::$tmethod[$ktype])) {
+      $kwrite = 'write'.TBase::$tmethod[$ktype];
+    } else {
+      $kspec = $spec['key'];
+    }
+    if (isset(TBase::$tmethod[$vtype])) {
+      $vwrite = 'write'.TBase::$tmethod[$vtype];
+    } else {
+      $vspec = $spec['val'];
+    }
+    $xfer += $output->writeMapBegin($ktype, $vtype, count($var));
+    foreach ($var as $key => $val) {
+      if (isset($kwrite)) {
+        $xfer += $output->$kwrite($key);
+      } else {
+        switch ($ktype) {
+        case TType::STRUCT:
+          $xfer += $key->write($output);
+          break;
+        case TType::MAP:
+          $xfer += $this->_writeMap($key, $kspec, $output);
+          break;
+        case TType::LST:
+          $xfer += $this->_writeList($key, $kspec, $output, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_writeList($key, $kspec, $output, true);
+          break;
+        }
+      }
+      if (isset($vwrite)) {
+        $xfer += $output->$vwrite($val);
+      } else {
+        switch ($vtype) {
+        case TType::STRUCT:
+          $xfer += $val->write($output);
+          break;
+        case TType::MAP:
+          $xfer += $this->_writeMap($val, $vspec, $output);
+          break;
+        case TType::LST:
+          $xfer += $this->_writeList($val, $vspec, $output, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_writeList($val, $vspec, $output, true);
+          break;
+        }
+      }
+    }
+    $xfer += $output->writeMapEnd();
+
+    return $xfer;
+  }
+
+  private function _writeList($var, $spec, $output, $set=false)
+  {
+    $xfer = 0;
+    $etype = $spec['etype'];
+    $ewrite = null;
+    if (isset(TBase::$tmethod[$etype])) {
+      $ewrite = 'write'.TBase::$tmethod[$etype];
+    } else {
+      $espec = $spec['elem'];
+    }
+    if ($set) {
+      $xfer += $output->writeSetBegin($etype, count($var));
+    } else {
+      $xfer += $output->writeListBegin($etype, count($var));
+    }
+    foreach ($var as $key => $val) {
+      $elem = $set ? $key : $val;
+      if (isset($ewrite)) {
+        $xfer += $output->$ewrite($elem);
+      } else {
+        switch ($etype) {
+        case TType::STRUCT:
+          $xfer += $elem->write($output);
+          break;
+        case TType::MAP:
+          $xfer += $this->_writeMap($elem, $espec, $output);
+          break;
+        case TType::LST:
+          $xfer += $this->_writeList($elem, $espec, $output, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_writeList($elem, $espec, $output, true);
+          break;
+        }
+      }
+    }
+    if ($set) {
+      $xfer += $output->writeSetEnd();
+    } else {
+      $xfer += $output->writeListEnd();
+    }
+
+    return $xfer;
+  }
+
+  protected function _write($class, $spec, $output)
+  {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin($class);
+    foreach ($spec as $fid => $fspec) {
+      $var = $fspec['var'];
+      if ($this->$var !== null) {
+        $ftype = $fspec['type'];
+        $xfer += $output->writeFieldBegin($var, $ftype, $fid);
+        if (isset(TBase::$tmethod[$ftype])) {
+          $func = 'write'.TBase::$tmethod[$ftype];
+          $xfer += $output->$func($this->$var);
+        } else {
+          switch ($ftype) {
+          case TType::STRUCT:
+            $xfer += $this->$var->write($output);
+            break;
+          case TType::MAP:
+            $xfer += $this->_writeMap($this->$var, $fspec, $output);
+            break;
+          case TType::LST:
+            $xfer += $this->_writeList($this->$var, $fspec, $output, false);
+            break;
+          case TType::SET:
+            $xfer += $this->_writeList($this->$var, $fspec, $output, true);
+            break;
+          }
+        }
+        $xfer += $output->writeFieldEnd();
+      }
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+
+    return $xfer;
+  }
+}

+ 210 - 0
php/OpenSearch/Thrift/ClassLoader/ThriftClassLoader.php

@@ -0,0 +1,210 @@
+<?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.
+ *
+ * ClassLoader to load Thrift library and definitions
+ * Inspired from UniversalClassLoader from Symfony 2
+ *
+ * @package thrift.classloader
+ */
+
+namespace Thrift\ClassLoader;
+
+class ThriftClassLoader
+{
+    /**
+     * Namespaces path
+     * @var array
+     */
+    protected $namespaces = array();
+
+    /**
+     * Thrift definition paths
+     * @var type
+     */
+    protected $definitions = array();
+
+    /**
+     * Do we use APC cache ?
+     * @var boolean
+     */
+    protected $apc = false;
+
+    /**
+     * APC Cache prefix
+     * @var string
+     */
+    protected $apc_prefix;
+
+    /**
+     * Set autoloader to use APC cache
+     * @param boolean $apc
+     * @param string  $apc_prefix
+     */
+    public function __construct($apc = false, $apc_prefix = null)
+    {
+        $this->apc = $apc;
+        $this->apc_prefix = $apc_prefix;
+    }
+
+    /**
+     * Registers a namespace.
+     *
+     * @param string       $namespace The namespace
+     * @param array|string $paths     The location(s) of the namespace
+     */
+    public function registerNamespace($namespace, $paths)
+    {
+        $this->namespaces[$namespace] = (array) $paths;
+    }
+
+    /**
+     * Registers a Thrift definition namespace.
+     *
+     * @param string       $namespace The definition namespace
+     * @param array|string $paths     The location(s) of the definition namespace
+     */
+    public function registerDefinition($namespace, $paths)
+    {
+        $this->definitions[$namespace] = (array) $paths;
+    }
+
+    /**
+     * Registers this instance as an autoloader.
+     *
+     * @param Boolean $prepend Whether to prepend the autoloader or not
+     */
+    public function register($prepend = false)
+    {
+        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+    }
+
+    /**
+     * Loads the given class, definition or interface.
+     *
+     * @param string $class The name of the class
+     */
+    public function loadClass($class)
+    {
+        if (
+            (true === $this->apc && ($file = $this->findFileInApc($class))) or
+            ($file = $this->findFile($class))
+        )
+        {
+            require_once $file;
+        }
+    }
+
+    /**
+     * Loads the given class or interface in APC.
+     * @param  string $class The name of the class
+     * @return string
+     */
+    protected function findFileInApc($class)
+    {
+        if (false === $file = apc_fetch($this->apc_prefix.$class)) {
+            apc_store($this->apc_prefix.$class, $file = $this->findFile($class));
+        }
+
+        return $file;
+    }
+
+    /**
+     * Find class in namespaces or definitions directories
+     * @param  string $class
+     * @return string
+     */
+    public function findFile($class)
+    {
+        // Remove first backslash
+        if ('\\' == $class[0]) {
+            $class = substr($class, 1);
+        }
+
+        if (false !== $pos = strrpos($class, '\\')) {
+            // Namespaced class name
+            $namespace = substr($class, 0, $pos);
+
+            // Iterate in normal namespaces
+            foreach ($this->namespaces as $ns => $dirs) {
+                //Don't interfere with other autoloaders
+                if (0 !== strpos($namespace, $ns)) {
+                    continue;
+                }
+
+                foreach ($dirs as $dir) {
+                    $className = substr($class, $pos + 1);
+
+                    $file = $dir.DIRECTORY_SEPARATOR.
+                                 str_replace('\\', DIRECTORY_SEPARATOR, $namespace).
+                                 DIRECTORY_SEPARATOR.
+                                 $className.'.php';
+
+                    if (file_exists($file)) {
+                        return $file;
+                    }
+                }
+            }
+
+            // Iterate in Thrift namespaces
+
+            // Remove first part of namespace
+            $m = explode('\\', $class);
+
+            // Ignore wrong call
+            if (count($m) <= 1) {
+                return;
+            }
+
+            $class = array_pop($m);
+            $namespace = implode('\\', $m);
+
+            foreach ($this->definitions as $ns => $dirs) {
+                //Don't interfere with other autoloaders
+                if (0 !== strpos($namespace, $ns)) {
+                    continue;
+                }
+
+                foreach ($dirs as $dir) {
+                    /**
+                     * Available in service: Interface, Client, Processor, Rest
+                     * And every service methods (_.+)
+                     */
+                    if(
+                        0 === preg_match('#(.+)(if|client|processor|rest)$#i', $class, $n) and
+                        0 === preg_match('#(.+)_[a-z0-9]+_(args|result)$#i', $class, $n)
+                    )
+                    {
+                        $className = 'Types';
+                    } else {
+                        $className = $n[1];
+                    }
+
+                    $file = $dir.DIRECTORY_SEPARATOR .
+                                 str_replace('\\', DIRECTORY_SEPARATOR, $namespace) .
+                                 DIRECTORY_SEPARATOR .
+                                 $className . '.php';
+
+                    if (file_exists($file)) {
+                        return $file;
+                    }
+                }
+            }
+        }
+    }
+}

+ 76 - 0
php/OpenSearch/Thrift/Exception/TApplicationException.php

@@ -0,0 +1,76 @@
+<?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
+ */
+
+namespace Thrift\Exception;
+
+use Thrift\Type\TType;
+
+class TApplicationException extends TException
+{
+  static $_TSPEC =
+    array(1 => array('var' => 'message',
+                     'type' => TType::STRING),
+          2 => array('var' => 'code',
+                     'type' => TType::I32));
+
+  const UNKNOWN = 0;
+  const UNKNOWN_METHOD = 1;
+  const INVALID_MESSAGE_TYPE = 2;
+  const WRONG_METHOD_NAME = 3;
+  const BAD_SEQUENCE_ID = 4;
+  const MISSING_RESULT = 5;
+  const INTERNAL_ERROR = 6;
+  const PROTOCOL_ERROR = 7;
+  const INVALID_TRANSFORM = 8;
+  const INVALID_PROTOCOL = 9;
+  const UNSUPPORTED_CLIENT_TYPE = 10;
+
+  public function __construct($message=null, $code=0)
+  {
+    parent::__construct($message, $code);
+  }
+
+  public function read($output)
+  {
+    return $this->_read('TApplicationException', self::$_TSPEC, $output);
+  }
+
+  public function write($output)
+  {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin('TApplicationException');
+    if ($message = $this->getMessage()) {
+      $xfer += $output->writeFieldBegin('message', TType::STRING, 1);
+      $xfer += $output->writeString($message);
+      $xfer += $output->writeFieldEnd();
+    }
+    if ($code = $this->getCode()) {
+      $xfer += $output->writeFieldBegin('type', TType::I32, 2);
+      $xfer += $output->writeI32($code);
+      $xfer += $output->writeFieldEnd();
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+
+    return $xfer;
+  }
+}

+ 383 - 0
php/OpenSearch/Thrift/Exception/TException.php

@@ -0,0 +1,383 @@
+<?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
+ */
+
+namespace Thrift\Exception;
+
+use Thrift\Type\TType;
+use Thrift\Base\TBase;
+
+/**
+ * NOTE(mcslee): This currently contains a ton of duplicated code from TBase
+ * because we need to save CPU cycles and this is not yet in an extension.
+ * Ideally we'd multiply-inherit TException from both Exception and Base, but
+ * that's not possible in PHP and there are no modules either, so for now we
+ * apologetically take a trip to HackTown.
+ *
+ * Can be called with standard Exception constructor (message, code) or with
+ * Thrift Base object constructor (spec, vals).
+ *
+ * @param mixed $p1 Message (string) or type-spec (array)
+ * @param mixed $p2 Code (integer) or values (array)
+ */
+class TException extends \Exception
+{
+  public function __construct($p1=null, $p2=0)
+  {
+    if (is_array($p1) && is_array($p2)) {
+      $spec = $p1;
+      $vals = $p2;
+      foreach ($spec as $fid => $fspec) {
+        $var = $fspec['var'];
+        if (isset($vals[$var])) {
+          $this->$var = $vals[$var];
+        }
+      }
+    } else {
+      parent::__construct($p1, $p2);
+    }
+  }
+
+  static $tmethod = array(TType::BOOL   => 'Bool',
+                          TType::BYTE   => 'Byte',
+                          TType::I16    => 'I16',
+                          TType::I32    => 'I32',
+                          TType::I64    => 'I64',
+                          TType::DOUBLE => 'Double',
+                          TType::STRING => 'String');
+
+  private function _readMap(&$var, $spec, $input)
+  {
+    $xfer = 0;
+    $ktype = $spec['ktype'];
+    $vtype = $spec['vtype'];
+    $kread = $vread = null;
+    if (isset(TBase::$tmethod[$ktype])) {
+      $kread = 'read'.TBase::$tmethod[$ktype];
+    } else {
+      $kspec = $spec['key'];
+    }
+    if (isset(TBase::$tmethod[$vtype])) {
+      $vread = 'read'.TBase::$tmethod[$vtype];
+    } else {
+      $vspec = $spec['val'];
+    }
+    $var = array();
+    $_ktype = $_vtype = $size = 0;
+    $xfer += $input->readMapBegin($_ktype, $_vtype, $size);
+    for ($i = 0; $i < $size; ++$i) {
+      $key = $val = null;
+      if ($kread !== null) {
+        $xfer += $input->$kread($key);
+      } else {
+        switch ($ktype) {
+        case TType::STRUCT:
+          $class = $kspec['class'];
+          $key = new $class();
+          $xfer += $key->read($input);
+          break;
+        case TType::MAP:
+          $xfer += $this->_readMap($key, $kspec, $input);
+          break;
+        case TType::LST:
+          $xfer += $this->_readList($key, $kspec, $input, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_readList($key, $kspec, $input, true);
+          break;
+        }
+      }
+      if ($vread !== null) {
+        $xfer += $input->$vread($val);
+      } else {
+        switch ($vtype) {
+        case TType::STRUCT:
+          $class = $vspec['class'];
+          $val = new $class();
+          $xfer += $val->read($input);
+          break;
+        case TType::MAP:
+          $xfer += $this->_readMap($val, $vspec, $input);
+          break;
+        case TType::LST:
+          $xfer += $this->_readList($val, $vspec, $input, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_readList($val, $vspec, $input, true);
+          break;
+        }
+      }
+      $var[$key] = $val;
+    }
+    $xfer += $input->readMapEnd();
+
+    return $xfer;
+  }
+
+  private function _readList(&$var, $spec, $input, $set=false)
+  {
+    $xfer = 0;
+    $etype = $spec['etype'];
+    $eread = $vread = null;
+    if (isset(TBase::$tmethod[$etype])) {
+      $eread = 'read'.TBase::$tmethod[$etype];
+    } else {
+      $espec = $spec['elem'];
+    }
+    $var = array();
+    $_etype = $size = 0;
+    if ($set) {
+      $xfer += $input->readSetBegin($_etype, $size);
+    } else {
+      $xfer += $input->readListBegin($_etype, $size);
+    }
+    for ($i = 0; $i < $size; ++$i) {
+      $elem = null;
+      if ($eread !== null) {
+        $xfer += $input->$eread($elem);
+      } else {
+        $espec = $spec['elem'];
+        switch ($etype) {
+        case TType::STRUCT:
+          $class = $espec['class'];
+          $elem = new $class();
+          $xfer += $elem->read($input);
+          break;
+        case TType::MAP:
+          $xfer += $this->_readMap($elem, $espec, $input);
+          break;
+        case TType::LST:
+          $xfer += $this->_readList($elem, $espec, $input, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_readList($elem, $espec, $input, true);
+          break;
+        }
+      }
+      if ($set) {
+        $var[$elem] = true;
+      } else {
+        $var []= $elem;
+      }
+    }
+    if ($set) {
+      $xfer += $input->readSetEnd();
+    } else {
+      $xfer += $input->readListEnd();
+    }
+
+    return $xfer;
+  }
+
+  protected function _read($class, $spec, $input)
+  {
+    $xfer = 0;
+    $fname = null;
+    $ftype = 0;
+    $fid = 0;
+    $xfer += $input->readStructBegin($fname);
+    while (true) {
+      $xfer += $input->readFieldBegin($fname, $ftype, $fid);
+      if ($ftype == TType::STOP) {
+        break;
+      }
+      if (isset($spec[$fid])) {
+        $fspec = $spec[$fid];
+        $var = $fspec['var'];
+        if ($ftype == $fspec['type']) {
+          $xfer = 0;
+          if (isset(TBase::$tmethod[$ftype])) {
+            $func = 'read'.TBase::$tmethod[$ftype];
+            $xfer += $input->$func($this->$var);
+          } else {
+            switch ($ftype) {
+            case TType::STRUCT:
+              $class = $fspec['class'];
+              $this->$var = new $class();
+              $xfer += $this->$var->read($input);
+              break;
+            case TType::MAP:
+              $xfer += $this->_readMap($this->$var, $fspec, $input);
+              break;
+            case TType::LST:
+              $xfer += $this->_readList($this->$var, $fspec, $input, false);
+              break;
+            case TType::SET:
+              $xfer += $this->_readList($this->$var, $fspec, $input, true);
+              break;
+            }
+          }
+        } else {
+          $xfer += $input->skip($ftype);
+        }
+      } else {
+        $xfer += $input->skip($ftype);
+      }
+      $xfer += $input->readFieldEnd();
+    }
+    $xfer += $input->readStructEnd();
+
+    return $xfer;
+  }
+
+  private function _writeMap($var, $spec, $output)
+  {
+    $xfer = 0;
+    $ktype = $spec['ktype'];
+    $vtype = $spec['vtype'];
+    $kwrite = $vwrite = null;
+    if (isset(TBase::$tmethod[$ktype])) {
+      $kwrite = 'write'.TBase::$tmethod[$ktype];
+    } else {
+      $kspec = $spec['key'];
+    }
+    if (isset(TBase::$tmethod[$vtype])) {
+      $vwrite = 'write'.TBase::$tmethod[$vtype];
+    } else {
+      $vspec = $spec['val'];
+    }
+    $xfer += $output->writeMapBegin($ktype, $vtype, count($var));
+    foreach ($var as $key => $val) {
+      if (isset($kwrite)) {
+        $xfer += $output->$kwrite($key);
+      } else {
+        switch ($ktype) {
+        case TType::STRUCT:
+          $xfer += $key->write($output);
+          break;
+        case TType::MAP:
+          $xfer += $this->_writeMap($key, $kspec, $output);
+          break;
+        case TType::LST:
+          $xfer += $this->_writeList($key, $kspec, $output, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_writeList($key, $kspec, $output, true);
+          break;
+        }
+      }
+      if (isset($vwrite)) {
+        $xfer += $output->$vwrite($val);
+      } else {
+        switch ($vtype) {
+        case TType::STRUCT:
+          $xfer += $val->write($output);
+          break;
+        case TType::MAP:
+          $xfer += $this->_writeMap($val, $vspec, $output);
+          break;
+        case TType::LST:
+          $xfer += $this->_writeList($val, $vspec, $output, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_writeList($val, $vspec, $output, true);
+          break;
+        }
+      }
+    }
+    $xfer += $output->writeMapEnd();
+
+    return $xfer;
+  }
+
+  private function _writeList($var, $spec, $output, $set=false)
+  {
+    $xfer = 0;
+    $etype = $spec['etype'];
+    $ewrite = null;
+    if (isset(TBase::$tmethod[$etype])) {
+      $ewrite = 'write'.TBase::$tmethod[$etype];
+    } else {
+      $espec = $spec['elem'];
+    }
+    if ($set) {
+      $xfer += $output->writeSetBegin($etype, count($var));
+    } else {
+      $xfer += $output->writeListBegin($etype, count($var));
+    }
+    foreach ($var as $key => $val) {
+      $elem = $set ? $key : $val;
+      if (isset($ewrite)) {
+        $xfer += $output->$ewrite($elem);
+      } else {
+        switch ($etype) {
+        case TType::STRUCT:
+          $xfer += $elem->write($output);
+          break;
+        case TType::MAP:
+          $xfer += $this->_writeMap($elem, $espec, $output);
+          break;
+        case TType::LST:
+          $xfer += $this->_writeList($elem, $espec, $output, false);
+          break;
+        case TType::SET:
+          $xfer += $this->_writeList($elem, $espec, $output, true);
+          break;
+        }
+      }
+    }
+    if ($set) {
+      $xfer += $output->writeSetEnd();
+    } else {
+      $xfer += $output->writeListEnd();
+    }
+
+    return $xfer;
+  }
+
+  protected function _write($class, $spec, $output)
+  {
+    $xfer = 0;
+    $xfer += $output->writeStructBegin($class);
+    foreach ($spec as $fid => $fspec) {
+      $var = $fspec['var'];
+      if ($this->$var !== null) {
+        $ftype = $fspec['type'];
+        $xfer += $output->writeFieldBegin($var, $ftype, $fid);
+        if (isset(TBase::$tmethod[$ftype])) {
+          $func = 'write'.TBase::$tmethod[$ftype];
+          $xfer += $output->$func($this->$var);
+        } else {
+          switch ($ftype) {
+          case TType::STRUCT:
+            $xfer += $this->$var->write($output);
+            break;
+          case TType::MAP:
+            $xfer += $this->_writeMap($this->$var, $fspec, $output);
+            break;
+          case TType::LST:
+            $xfer += $this->_writeList($this->$var, $fspec, $output, false);
+            break;
+          case TType::SET:
+            $xfer += $this->_writeList($this->$var, $fspec, $output, true);
+            break;
+          }
+        }
+        $xfer += $output->writeFieldEnd();
+      }
+    }
+    $xfer += $output->writeFieldStop();
+    $xfer += $output->writeStructEnd();
+
+    return $xfer;
+  }
+
+}

+ 50 - 0
php/OpenSearch/Thrift/Exception/TProtocolException.php

@@ -0,0 +1,50 @@
+<?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.protocol
+ * @author: rmarin (marin.radu@facebook.com)
+ */
+
+namespace Thrift\Exception;
+
+/**
+ * Protocol module. Contains all the types and definitions needed to implement
+ * a protocol encoder/decoder.
+ *
+ * @package thrift.protocol
+ */
+
+/**
+ * Protocol exceptions
+ */
+class TProtocolException extends TException
+{
+  const UNKNOWN = 0;
+  const INVALID_DATA = 1;
+  const NEGATIVE_SIZE = 2;
+  const SIZE_LIMIT = 3;
+  const BAD_VERSION = 4;
+  const NOT_IMPLEMENTED = 5;
+  const DEPTH_LIMIT = 6;
+
+  public function __construct($message=null, $code=0)
+  {
+    parent::__construct($message, $code);
+  }
+}

+ 40 - 0
php/OpenSearch/Thrift/Exception/TTransportException.php

@@ -0,0 +1,40 @@
+<?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.transport
+ */
+
+namespace Thrift\Exception;
+
+/**
+ * Transport exceptions
+ */
+class TTransportException extends TException
+{
+  const UNKNOWN = 0;
+  const NOT_OPEN = 1;
+  const ALREADY_OPEN = 2;
+  const TIMED_OUT = 3;
+  const END_OF_FILE = 4;
+
+  public function __construct($message=null, $code=0)
+  {
+    parent::__construct($message, $code);
+  }
+}

+ 45 - 0
php/OpenSearch/Thrift/Factory/TBinaryProtocolFactory.php

@@ -0,0 +1,45 @@
+<?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.protocol
+ */
+
+namespace Thrift\Factory;
+
+use Thrift\Protocol\TBinaryProtocol;
+
+/**
+ * Binary Protocol Factory
+ */
+class TBinaryProtocolFactory implements TProtocolFactory
+{
+  private $strictRead_ = false;
+  private $strictWrite_ = false;
+
+  public function __construct($strictRead=false, $strictWrite=false)
+  {
+    $this->strictRead_ = $strictRead;
+    $this->strictWrite_ = $strictWrite;
+  }
+
+  public function getProtocol($trans)
+  {
+    return new TBinaryProtocol($trans, $this->strictRead_, $this->strictWrite_);
+  }
+}

+ 40 - 0
php/OpenSearch/Thrift/Factory/TCompactProtocolFactory.php

@@ -0,0 +1,40 @@
+<?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.protocol
+ */
+
+namespace Thrift\Factory;
+
+use Thrift\Protocol\TCompactProtocol;
+
+/**
+ * Compact Protocol Factory
+ */
+class TCompactProtocolFactory implements TProtocolFactory
+{
+  public function __construct()
+  {
+  }
+
+  public function getProtocol($trans)
+  {
+    return new TCompactProtocol($trans);
+  }
+}

+ 40 - 0
php/OpenSearch/Thrift/Factory/TJSONProtocolFactory.php

@@ -0,0 +1,40 @@
+<?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.protocol
+ */
+
+namespace Thrift\Factory;
+
+use Thrift\Protocol\TJSONProtocol;
+
+/**
+ * JSON Protocol Factory
+ */
+class TJSONProtocolFactory implements TProtocolFactory
+{
+    public function __construct()
+    {
+    }
+
+    public function getProtocol($trans)
+    {
+        return new TJSONProtocol($trans);
+    }
+}

+ 36 - 0
php/OpenSearch/Thrift/Factory/TProtocolFactory.php

@@ -0,0 +1,36 @@
+<?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.protocol
+ */
+
+namespace Thrift\Factory;
+
+/**
+ * Protocol factory creates protocol objects from transports
+ */
+interface TProtocolFactory
+{
+  /**
+   * Build a protocol from the base transport
+   *
+   * @return Thrift\Protocol\TProtocol protocol
+   */
+  public function getProtocol($trans);
+}

+ 66 - 0
php/OpenSearch/Thrift/Factory/TStringFuncFactory.php

@@ -0,0 +1,66 @@
+<?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.
+ *
+ */
+
+namespace Thrift\Factory;
+
+use Thrift\StringFunc\Mbstring;
+use Thrift\StringFunc\Core;
+
+class TStringFuncFactory
+{
+    private static $_instance;
+
+    /**
+     * Get the Singleton instance of TStringFunc implementation that is
+     * compatible with the current system's mbstring.func_overload settings.
+     *
+     * @return TStringFunc
+     */
+    public static function create()
+    {
+        if (!self::$_instance) {
+            self::_setInstance();
+        }
+
+        return self::$_instance;
+    }
+
+    private static function _setInstance()
+    {
+        /**
+         * Cannot use str* functions for byte counting because multibyte
+         * characters will be read a single bytes.
+         *
+         * See: http://us.php.net/manual/en/mbstring.overload.php
+         */
+        if (ini_get('mbstring.func_overload') & 2) {
+            self::$_instance = new Mbstring();
+        }
+        /**
+         * mbstring is not installed or does not have function overloading
+         * of the str* functions enabled so use PHP core str* functions for
+         * byte counting.
+         */
+        else {
+            self::$_instance = new Core();
+        }
+    }
+}

+ 18 - 0
php/OpenSearch/Thrift/Factory/TTransportFactory.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace Thrift\Factory;
+
+use Thrift\Transport\TTransport;
+
+class TTransportFactory
+{
+  /**
+   * @static
+   * @param TTransport $transport
+   * @return TTransport
+   */
+  public static function getTransport(TTransport $transport)
+  {
+    return $transport;
+  }
+}

+ 39 - 0
php/OpenSearch/Thrift/Protocol/JSON/BaseContext.php

@@ -0,0 +1,39 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol\JSON;
+
+class BaseContext
+{
+    public function escapeNum()
+    {
+        return false;
+    }
+
+    public function write()
+    {
+    }
+
+    public function read()
+    {
+    }
+}

+ 54 - 0
php/OpenSearch/Thrift/Protocol/JSON/ListContext.php

@@ -0,0 +1,54 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol\JSON;
+
+use Thrift\Protocol\TJSONProtocol;
+
+class ListContext extends BaseContext
+{
+    private $first_ = true;
+    private $p_;
+
+    public function __construct($p)
+    {
+        $this->p_ = $p;
+    }
+
+    public function write()
+    {
+        if ($this->first_) {
+            $this->first_ = false;
+        } else {
+            $this->p_->getTransport()->write(TJSONProtocol::COMMA);
+        }
+    }
+
+    public function read()
+    {
+        if ($this->first_) {
+            $this->first_ = false;
+        } else {
+            $this->p_->readJSONSyntaxChar(TJSONProtocol::COMMA);
+        }
+    }
+}

+ 57 - 0
php/OpenSearch/Thrift/Protocol/JSON/LookaheadReader.php

@@ -0,0 +1,57 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol\JSON;
+
+class LookaheadReader
+{
+    private $hasData_ = false;
+    private $data_ = array();
+    private $p_;
+
+    public function __construct($p)
+    {
+        $this->p_ = $p;
+    }
+
+    public function read()
+    {
+        if ($this->hasData_) {
+            $this->hasData_ = false;
+        } else {
+            $this->data_ = $this->p_->getTransport()->readAll(1);
+        }
+
+        return substr($this->data_, 0, 1);
+    }
+
+    public function peek()
+    {
+        if (!$this->hasData_) {
+            $this->data_ = $this->p_->getTransport()->readAll(1);
+        }
+
+        $this->hasData_ = true;
+
+        return substr($this->data_, 0, 1);
+    }
+}

+ 64 - 0
php/OpenSearch/Thrift/Protocol/JSON/PairContext.php

@@ -0,0 +1,64 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol\JSON;
+
+use Thrift\Protocol\TJSONProtocol;
+
+class PairContext extends BaseContext
+{
+    private $first_ = true;
+    private $colon_ = true;
+    private $p_ = null;
+
+    public function __construct($p)
+    {
+        $this->p_ = $p;
+    }
+
+    public function write()
+    {
+        if ($this->first_) {
+            $this->first_ = false;
+            $this->colon_ = true;
+        } else {
+            $this->p_->getTransport()->write($this->colon_ ? TJSONProtocol::COLON : TJSONProtocol::COMMA);
+            $this->colon_ = !$this->colon_;
+        }
+    }
+
+    public function read()
+    {
+        if ($this->first_) {
+            $this->first_ = false;
+            $this->colon_ = true;
+        } else {
+            $this->p_->readJSONSyntaxChar($this->colon_ ? TJSONProtocol::COLON : TJSONProtocol::COMMA);
+            $this->colon_ = !$this->colon_;
+        }
+    }
+
+    public function escapeNum()
+    {
+        return $this->colon_;
+    }
+}

+ 33 - 0
php/OpenSearch/Thrift/Protocol/SimpleJSON/CollectionMapKeyException.php

@@ -0,0 +1,33 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol\SimpleJSON;
+
+use Thrift\Exception\TException;
+
+class CollectionMapKeyException extends TException
+{
+    public function __construct($message)
+    {
+        parent::__construct($message);
+    }
+}

+ 36 - 0
php/OpenSearch/Thrift/Protocol/SimpleJSON/Context.php

@@ -0,0 +1,36 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol\SimpleJSON;
+
+class Context
+{
+    public function write()
+    {
+    }
+
+    public function isMapKey()
+    {
+        return false;
+    }
+}
+

+ 45 - 0
php/OpenSearch/Thrift/Protocol/SimpleJSON/ListContext.php

@@ -0,0 +1,45 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol\SimpleJSON;
+
+use Thrift\Protocol\TSimpleJSONProtocol;
+
+class ListContext extends Context
+{
+    protected $first_ = true;
+    private $p_;
+
+    public function __construct($p)
+    {
+        $this->p_ = $p;
+    }
+
+    public function write()
+    {
+        if ($this->first_) {
+            $this->first_ = false;
+        } else {
+            $this->p_->getTransport()->write(TSimpleJSONProtocol::COMMA);
+        }
+    }
+}

+ 51 - 0
php/OpenSearch/Thrift/Protocol/SimpleJSON/MapContext.php

@@ -0,0 +1,51 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol\SimpleJSON;
+
+use Thrift\Protocol\TSimpleJSONProtocol;
+
+class MapContext extends StructContext
+{
+    protected $isKey = true;
+    private $p_;
+
+    public function __construct($p)
+    {
+        parent::__construct($p);
+    }
+
+    public function write()
+    {
+        parent::write();
+        $this->isKey = !$this->isKey;
+    }
+
+    public function isMapKey()
+    {
+        // we want to coerce map keys to json strings regardless
+        // of their type
+        return $this->isKey;
+    }
+}
+
+

+ 53 - 0
php/OpenSearch/Thrift/Protocol/SimpleJSON/StructContext.php

@@ -0,0 +1,53 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol\SimpleJSON;
+
+use Thrift\Protocol\TSimpleJSONProtocol;
+
+class StructContext extends Context
+{
+    protected $first_ = true;
+    protected $colon_ = true;
+    private $p_;
+
+    public function __construct($p)
+    {
+        $this->p_ = $p;
+    }
+
+    public function write()
+    {
+        if ($this->first_) {
+            $this->first_ = false;
+            $this->colon_ = true;
+        } else {
+            $this->p_->getTransport()->write(
+                $this->colon_ ?
+                TSimpleJSONProtocol::COLON :
+                TSimpleJSONProtocol::COMMA
+            );
+            $this->colon_ = !$this->colon_;
+        }
+    }
+}
+

+ 453 - 0
php/OpenSearch/Thrift/Protocol/TBinaryProtocol.php

@@ -0,0 +1,453 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Type\TType;
+use Thrift\Exception\TProtocolException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Binary implementation of the Thrift protocol.
+ *
+ */
+class TBinaryProtocol extends TProtocol
+{
+  const VERSION_MASK = 0xffff0000;
+  const VERSION_1 = 0x80010000;
+
+  protected $strictRead_ = false;
+  protected $strictWrite_ = true;
+
+  public function __construct($trans, $strictRead=false, $strictWrite=true)
+  {
+    parent::__construct($trans);
+    $this->strictRead_ = $strictRead;
+    $this->strictWrite_ = $strictWrite;
+  }
+
+  public function writeMessageBegin($name, $type, $seqid)
+  {
+    if ($this->strictWrite_) {
+      $version = self::VERSION_1 | $type;
+
+      return
+        $this->writeI32($version) +
+        $this->writeString($name) +
+        $this->writeI32($seqid);
+    } else {
+      return
+        $this->writeString($name) +
+        $this->writeByte($type) +
+        $this->writeI32($seqid);
+    }
+  }
+
+  public function writeMessageEnd()
+  {
+    return 0;
+  }
+
+  public function writeStructBegin($name)
+  {
+    return 0;
+  }
+
+  public function writeStructEnd()
+  {
+    return 0;
+  }
+
+  public function writeFieldBegin($fieldName, $fieldType, $fieldId)
+  {
+    return
+      $this->writeByte($fieldType) +
+      $this->writeI16($fieldId);
+  }
+
+  public function writeFieldEnd()
+  {
+    return 0;
+  }
+
+  public function writeFieldStop()
+  {
+    return
+      $this->writeByte(TType::STOP);
+  }
+
+  public function writeMapBegin($keyType, $valType, $size)
+  {
+    return
+      $this->writeByte($keyType) +
+      $this->writeByte($valType) +
+      $this->writeI32($size);
+  }
+
+  public function writeMapEnd()
+  {
+    return 0;
+  }
+
+  public function writeListBegin($elemType, $size)
+  {
+    return
+      $this->writeByte($elemType) +
+      $this->writeI32($size);
+  }
+
+  public function writeListEnd()
+  {
+    return 0;
+  }
+
+  public function writeSetBegin($elemType, $size)
+  {
+    return
+      $this->writeByte($elemType) +
+      $this->writeI32($size);
+  }
+
+  public function writeSetEnd()
+  {
+    return 0;
+  }
+
+  public function writeBool($value)
+  {
+    $data = pack('c', $value ? 1 : 0);
+    $this->trans_->write($data, 1);
+
+    return 1;
+  }
+
+  public function writeByte($value)
+  {
+    $data = pack('c', $value);
+    $this->trans_->write($data, 1);
+
+    return 1;
+  }
+
+  public function writeI16($value)
+  {
+    $data = pack('n', $value);
+    $this->trans_->write($data, 2);
+
+    return 2;
+  }
+
+  public function writeI32($value)
+  {
+    $data = pack('N', $value);
+    $this->trans_->write($data, 4);
+
+    return 4;
+  }
+
+  public function writeI64($value)
+  {
+    // If we are on a 32bit architecture we have to explicitly deal with
+    // 64-bit twos-complement arithmetic since PHP wants to treat all ints
+    // as signed and any int over 2^31 - 1 as a float
+    if (PHP_INT_SIZE == 4) {
+      $neg = $value < 0;
+
+      if ($neg) {
+        $value *= -1;
+      }
+
+      $hi = (int) ($value / 4294967296);
+      $lo = (int) $value;
+
+      if ($neg) {
+        $hi = ~$hi;
+        $lo = ~$lo;
+        if (($lo & (int) 0xffffffff) == (int) 0xffffffff) {
+          $lo = 0;
+          $hi++;
+        } else {
+          $lo++;
+        }
+      }
+      $data = pack('N2', $hi, $lo);
+
+    } else {
+      $hi = $value >> 32;
+      $lo = $value & 0xFFFFFFFF;
+      $data = pack('N2', $hi, $lo);
+    }
+
+    $this->trans_->write($data, 8);
+
+    return 8;
+  }
+
+  public function writeDouble($value)
+  {
+    $data = pack('d', $value);
+    $this->trans_->write(strrev($data), 8);
+
+    return 8;
+  }
+
+  public function writeString($value)
+  {
+    $len = TStringFuncFactory::create()->strlen($value);
+    $result = $this->writeI32($len);
+    if ($len) {
+      $this->trans_->write($value, $len);
+    }
+
+    return $result + $len;
+  }
+
+  public function readMessageBegin(&$name, &$type, &$seqid)
+  {
+    $result = $this->readI32($sz);
+    if ($sz < 0) {
+      $version = (int) ($sz & self::VERSION_MASK);
+      if ($version != (int) self::VERSION_1) {
+        throw new TProtocolException('Bad version identifier: '.$sz, TProtocolException::BAD_VERSION);
+      }
+      $type = $sz & 0x000000ff;
+      $result +=
+        $this->readString($name) +
+        $this->readI32($seqid);
+    } else {
+      if ($this->strictRead_) {
+        throw new TProtocolException('No version identifier, old protocol client?', TProtocolException::BAD_VERSION);
+      } else {
+        // Handle pre-versioned input
+        $name = $this->trans_->readAll($sz);
+        $result +=
+          $sz +
+          $this->readByte($type) +
+          $this->readI32($seqid);
+      }
+    }
+
+    return $result;
+  }
+
+  public function readMessageEnd()
+  {
+    return 0;
+  }
+
+  public function readStructBegin(&$name)
+  {
+    $name = '';
+
+    return 0;
+  }
+
+  public function readStructEnd()
+  {
+    return 0;
+  }
+
+  public function readFieldBegin(&$name, &$fieldType, &$fieldId)
+  {
+    $result = $this->readByte($fieldType);
+    if ($fieldType == TType::STOP) {
+      $fieldId = 0;
+
+      return $result;
+    }
+    $result += $this->readI16($fieldId);
+
+    return $result;
+  }
+
+  public function readFieldEnd()
+  {
+    return 0;
+  }
+
+  public function readMapBegin(&$keyType, &$valType, &$size)
+  {
+    return
+      $this->readByte($keyType) +
+      $this->readByte($valType) +
+      $this->readI32($size);
+  }
+
+  public function readMapEnd()
+  {
+    return 0;
+  }
+
+  public function readListBegin(&$elemType, &$size)
+  {
+    return
+      $this->readByte($elemType) +
+      $this->readI32($size);
+  }
+
+  public function readListEnd()
+  {
+    return 0;
+  }
+
+  public function readSetBegin(&$elemType, &$size)
+  {
+    return
+      $this->readByte($elemType) +
+      $this->readI32($size);
+  }
+
+  public function readSetEnd()
+  {
+    return 0;
+  }
+
+  public function readBool(&$value)
+  {
+    $data = $this->trans_->readAll(1);
+    $arr = unpack('c', $data);
+    $value = $arr[1] == 1;
+
+    return 1;
+  }
+
+  public function readByte(&$value)
+  {
+    $data = $this->trans_->readAll(1);
+    $arr = unpack('c', $data);
+    $value = $arr[1];
+
+    return 1;
+  }
+
+  public function readI16(&$value)
+  {
+    $data = $this->trans_->readAll(2);
+    $arr = unpack('n', $data);
+    $value = $arr[1];
+    if ($value > 0x7fff) {
+      $value = 0 - (($value - 1) ^ 0xffff);
+    }
+
+    return 2;
+  }
+
+  public function readI32(&$value)
+  {
+    $data = $this->trans_->readAll(4);
+    $arr = unpack('N', $data);
+    $value = $arr[1];
+    if ($value > 0x7fffffff) {
+      $value = 0 - (($value - 1) ^ 0xffffffff);
+    }
+
+    return 4;
+  }
+
+  public function readI64(&$value)
+  {
+    $data = $this->trans_->readAll(8);
+
+    $arr = unpack('N2', $data);
+
+    // If we are on a 32bit architecture we have to explicitly deal with
+    // 64-bit twos-complement arithmetic since PHP wants to treat all ints
+    // as signed and any int over 2^31 - 1 as a float
+    if (PHP_INT_SIZE == 4) {
+
+      $hi = $arr[1];
+      $lo = $arr[2];
+      $isNeg = $hi  < 0;
+
+      // Check for a negative
+      if ($isNeg) {
+        $hi = ~$hi & (int) 0xffffffff;
+        $lo = ~$lo & (int) 0xffffffff;
+
+        if ($lo == (int) 0xffffffff) {
+          $hi++;
+          $lo = 0;
+        } else {
+          $lo++;
+        }
+      }
+
+      // Force 32bit words in excess of 2G to pe positive - we deal wigh sign
+      // explicitly below
+
+      if ($hi & (int) 0x80000000) {
+        $hi &= (int) 0x7fffffff;
+        $hi += 0x80000000;
+      }
+
+      if ($lo & (int) 0x80000000) {
+        $lo &= (int) 0x7fffffff;
+        $lo += 0x80000000;
+      }
+
+      $value = $hi * 4294967296 + $lo;
+
+      if ($isNeg) {
+        $value = 0 - $value;
+      }
+    } else {
+
+      // Upcast negatives in LSB bit
+      if ($arr[2] & 0x80000000) {
+        $arr[2] = $arr[2] & 0xffffffff;
+      }
+
+      // Check for a negative
+      if ($arr[1] & 0x80000000) {
+        $arr[1] = $arr[1] & 0xffffffff;
+        $arr[1] = $arr[1] ^ 0xffffffff;
+        $arr[2] = $arr[2] ^ 0xffffffff;
+        $value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
+      } else {
+        $value = $arr[1]*4294967296 + $arr[2];
+      }
+    }
+
+    return 8;
+  }
+
+  public function readDouble(&$value)
+  {
+    $data = strrev($this->trans_->readAll(8));
+    $arr = unpack('d', $data);
+    $value = $arr[1];
+
+    return 8;
+  }
+
+  public function readString(&$value)
+  {
+    $result = $this->readI32($len);
+    if ($len) {
+      $value = $this->trans_->readAll($len);
+    } else {
+      $value = '';
+    }
+
+    return $result + $len;
+  }
+}

+ 65 - 0
php/OpenSearch/Thrift/Protocol/TBinaryProtocolAccelerated.php

@@ -0,0 +1,65 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Transport\TBufferedTransport;
+
+/**
+ * Accelerated binary protocol: used in conjunction with the thrift_protocol
+ * extension for faster deserialization
+ */
+class TBinaryProtocolAccelerated extends TBinaryProtocol
+{
+  public function __construct($trans, $strictRead=false, $strictWrite=true)
+  {
+    // If the transport doesn't implement putBack, wrap it in a
+    // TBufferedTransport (which does)
+
+    // NOTE (t.heintz): This is very evil to do, because the TBufferedTransport may swallow bytes, which
+    // are then never written to the underlying transport. This happens precisely when a number of bytes
+    // less than the max buffer size (512 by default) is written to the transport and then flush() is NOT
+    // called. In that case the data stays in the writeBuffer of the transport, from where it can never be
+    // accessed again (for example through read()).
+    //
+    // Since the caller of this method does not know about the wrapping transport, this creates bugs which
+    // are very difficult to find. Hence the wrapping of a transport in a buffer should be left to the
+    // calling code. An interface could used to mandate the presence of the putBack() method in the transport.
+    //
+    // I am leaving this code in nonetheless, because there may be applications depending on this behavior.
+    //
+    // @see THRIFT-1579
+
+    if (!method_exists($trans, 'putBack')) {
+      $trans = new TBufferedTransport($trans);
+    }
+    parent::__construct($trans, $strictRead, $strictWrite);
+  }
+  public function isStrictRead()
+  {
+    return $this->strictRead_;
+  }
+  public function isStrictWrite()
+  {
+    return $this->strictWrite_;
+  }
+}

+ 739 - 0
php/OpenSearch/Thrift/Protocol/TCompactProtocol.php

@@ -0,0 +1,739 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Type\TType;
+use Thrift\Exception\TProtocolException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Compact implementation of the Thrift protocol.
+ *
+ */
+class TCompactProtocol extends TProtocol
+{
+  const COMPACT_STOP = 0x00;
+  const COMPACT_TRUE = 0x01;
+  const COMPACT_FALSE = 0x02;
+  const COMPACT_BYTE = 0x03;
+  const COMPACT_I16 = 0x04;
+  const COMPACT_I32 = 0x05;
+  const COMPACT_I64 = 0x06;
+  const COMPACT_DOUBLE = 0x07;
+  const COMPACT_BINARY = 0x08;
+  const COMPACT_LIST = 0x09;
+  const COMPACT_SET = 0x0A;
+  const COMPACT_MAP = 0x0B;
+  const COMPACT_STRUCT = 0x0C;
+
+  const STATE_CLEAR = 0;
+  const STATE_FIELD_WRITE = 1;
+  const STATE_VALUE_WRITE = 2;
+  const STATE_CONTAINER_WRITE = 3;
+  const STATE_BOOL_WRITE = 4;
+  const STATE_FIELD_READ = 5;
+  const STATE_CONTAINER_READ = 6;
+  const STATE_VALUE_READ = 7;
+  const STATE_BOOL_READ = 8;
+
+  const VERSION_MASK = 0x1f;
+  const VERSION = 1;
+  const PROTOCOL_ID = 0x82;
+  const TYPE_MASK = 0xe0;
+  const TYPE_BITS = 0x07;
+  const TYPE_SHIFT_AMOUNT = 5;
+
+  protected static $ctypes = array(
+    TType::STOP => TCompactProtocol::COMPACT_STOP,
+    TType::BOOL => TCompactProtocol::COMPACT_TRUE, // used for collection
+    TType::BYTE => TCompactProtocol::COMPACT_BYTE,
+    TType::I16 => TCompactProtocol::COMPACT_I16,
+    TType::I32 => TCompactProtocol::COMPACT_I32,
+    TType::I64 => TCompactProtocol::COMPACT_I64,
+    TType::DOUBLE => TCompactProtocol::COMPACT_DOUBLE,
+    TType::STRING => TCompactProtocol::COMPACT_BINARY,
+    TType::STRUCT => TCompactProtocol::COMPACT_STRUCT,
+    TType::LST => TCompactProtocol::COMPACT_LIST,
+    TType::SET => TCompactProtocol::COMPACT_SET,
+    TType::MAP => TCompactProtocol::COMPACT_MAP,
+  );
+
+  protected static $ttypes = array(
+    TCompactProtocol::COMPACT_STOP => TType::STOP ,
+    TCompactProtocol::COMPACT_TRUE => TType::BOOL, // used for collection
+    TCompactProtocol::COMPACT_FALSE => TType::BOOL,
+    TCompactProtocol::COMPACT_BYTE => TType::BYTE,
+    TCompactProtocol::COMPACT_I16 => TType::I16,
+    TCompactProtocol::COMPACT_I32 => TType::I32,
+    TCompactProtocol::COMPACT_I64 => TType::I64,
+    TCompactProtocol::COMPACT_DOUBLE => TType::DOUBLE,
+    TCompactProtocol::COMPACT_BINARY => TType::STRING,
+    TCompactProtocol::COMPACT_STRUCT => TType::STRUCT,
+    TCompactProtocol::COMPACT_LIST => TType::LST,
+    TCompactProtocol::COMPACT_SET => TType::SET,
+    TCompactProtocol::COMPACT_MAP => TType::MAP,
+  );
+
+  protected $state = TCompactProtocol::STATE_CLEAR;
+  protected $lastFid = 0;
+  protected $boolFid = null;
+  protected $boolValue = null;
+  protected $structs = array();
+  protected $containers = array();
+
+  // Some varint / zigzag helper methods
+  public function toZigZag($n, $bits)
+  {
+    return ($n << 1) ^ ($n >> ($bits - 1));
+  }
+
+  public function fromZigZag($n)
+  {
+    return ($n >> 1) ^ -($n & 1);
+  }
+
+  public function getVarint($data)
+  {
+    $out = "";
+    while (true) {
+      if (($data & ~0x7f) === 0) {
+        $out .= chr($data);
+        break;
+      } else {
+        $out .= chr(($data & 0xff) | 0x80);
+        $data = $data >> 7;
+      }
+    }
+
+    return $out;
+  }
+
+  public function writeVarint($data)
+  {
+    $out = $this->getVarint($data);
+    $result = TStringFuncFactory::create()->strlen($out);
+    $this->trans_->write($out, $result);
+
+    return $result;
+  }
+
+  public function readVarint(&$result)
+  {
+    $idx = 0;
+    $shift = 0;
+    $result = 0;
+    while (true) {
+      $x = $this->trans_->readAll(1);
+      $arr = unpack('C', $x);
+      $byte = $arr[1];
+      $idx += 1;
+      $result |= ($byte & 0x7f) << $shift;
+      if (($byte >> 7) === 0) {
+        return $idx;
+      }
+      $shift += 7;
+    }
+
+    return $idx;
+  }
+
+  public function __construct($trans)
+  {
+    parent::__construct($trans);
+  }
+
+  public function writeMessageBegin($name, $type, $seqid)
+  {
+    $written =
+      $this->writeUByte(TCompactProtocol::PROTOCOL_ID) +
+      $this->writeUByte(TCompactProtocol::VERSION |
+                        ($type << TCompactProtocol::TYPE_SHIFT_AMOUNT)) +
+      $this->writeVarint($seqid) +
+      $this->writeString($name);
+    $this->state = TCompactProtocol::STATE_VALUE_WRITE;
+
+    return $written;
+  }
+
+  public function writeMessageEnd()
+  {
+    $this->state = TCompactProtocol::STATE_CLEAR;
+
+    return 0;
+  }
+
+  public function writeStructBegin($name)
+  {
+    $this->structs[] = array($this->state, $this->lastFid);
+    $this->state = TCompactProtocol::STATE_FIELD_WRITE;
+    $this->lastFid = 0;
+
+    return 0;
+  }
+
+  public function writeStructEnd()
+  {
+    $old_values = array_pop($this->structs);
+    $this->state = $old_values[0];
+    $this->lastFid = $old_values[1];
+
+    return 0;
+  }
+
+  public function writeFieldStop()
+  {
+    return $this->writeByte(0);
+  }
+
+  public function writeFieldHeader($type, $fid)
+  {
+    $written = 0;
+    $delta = $fid - $this->lastFid;
+    if (0 < $delta && $delta <= 15) {
+      $written = $this->writeUByte(($delta << 4) | $type);
+    } else {
+      $written = $this->writeByte($type) +
+        $this->writeI16($fid);
+    }
+    $this->lastFid = $fid;
+
+    return $written;
+  }
+
+  public function writeFieldBegin($field_name, $field_type, $field_id)
+  {
+    if ($field_type == TTYPE::BOOL) {
+      $this->state = TCompactProtocol::STATE_BOOL_WRITE;
+      $this->boolFid = $field_id;
+
+      return 0;
+    } else {
+      $this->state = TCompactProtocol::STATE_VALUE_WRITE;
+
+      return $this->writeFieldHeader(self::$ctypes[$field_type], $field_id);
+    }
+  }
+
+  public function writeFieldEnd()
+  {
+    $this->state = TCompactProtocol::STATE_FIELD_WRITE;
+
+    return 0;
+  }
+
+  public function writeCollectionBegin($etype, $size)
+  {
+    $written = 0;
+    if ($size <= 14) {
+      $written = $this->writeUByte($size << 4 |
+                                    self::$ctypes[$etype]);
+    } else {
+      $written = $this->writeUByte(0xf0 |
+                                   self::$ctypes[$etype]) +
+        $this->writeVarint($size);
+    }
+    $this->containers[] = $this->state;
+    $this->state = TCompactProtocol::STATE_CONTAINER_WRITE;
+
+    return $written;
+  }
+
+  public function writeMapBegin($key_type, $val_type, $size)
+  {
+    $written = 0;
+    if ($size == 0) {
+      $written = $this->writeByte(0);
+    } else {
+      $written = $this->writeVarint($size) +
+        $this->writeUByte(self::$ctypes[$key_type] << 4 |
+                          self::$ctypes[$val_type]);
+    }
+    $this->containers[] = $this->state;
+
+    return $written;
+  }
+
+  public function writeCollectionEnd()
+  {
+    $this->state = array_pop($this->containers);
+
+    return 0;
+  }
+
+  public function writeMapEnd()
+  {
+    return $this->writeCollectionEnd();
+  }
+
+  public function writeListBegin($elem_type, $size)
+  {
+    return $this->writeCollectionBegin($elem_type, $size);
+  }
+
+  public function writeListEnd()
+  {
+    return $this->writeCollectionEnd();
+  }
+
+  public function writeSetBegin($elem_type, $size)
+  {
+    return $this->writeCollectionBegin($elem_type, $size);
+  }
+
+  public function writeSetEnd()
+  {
+    return $this->writeCollectionEnd();
+  }
+
+  public function writeBool($value)
+  {
+    if ($this->state == TCompactProtocol::STATE_BOOL_WRITE) {
+      $ctype = TCompactProtocol::COMPACT_FALSE;
+      if ($value) {
+        $ctype = TCompactProtocol::COMPACT_TRUE;
+      }
+
+      return $this->writeFieldHeader($ctype, $this->boolFid);
+    } elseif ($this->state == TCompactProtocol::STATE_CONTAINER_WRITE) {
+      return $this->writeByte($value ? 1 : 0);
+    } else {
+      throw new TProtocolException('Invalid state in compact protocol');
+    }
+  }
+
+  public function writeByte($value)
+  {
+    $data = pack('c', $value);
+    $this->trans_->write($data, 1);
+
+    return 1;
+  }
+
+  public function writeUByte($byte)
+  {
+    $this->trans_->write(pack('C', $byte), 1);
+
+    return 1;
+  }
+
+  public function writeI16($value)
+  {
+    $thing = $this->toZigZag($value, 16);
+
+    return $this->writeVarint($thing);
+  }
+
+  public function writeI32($value)
+  {
+    $thing = $this->toZigZag($value, 32);
+
+    return $this->writeVarint($thing);
+  }
+
+  public function writeDouble($value)
+  {
+    $data = pack('d', $value);
+    $this->trans_->write($data, 8);
+
+    return 8;
+  }
+
+  public function writeString($value)
+  {
+    $len = TStringFuncFactory::create()->strlen($value);
+    $result = $this->writeVarint($len);
+    if ($len) {
+      $this->trans_->write($value, $len);
+    }
+
+    return $result + $len;
+  }
+
+  public function readFieldBegin(&$name, &$field_type, &$field_id)
+  {
+    $result = $this->readUByte($compact_type_and_delta);
+
+    $compact_type = $compact_type_and_delta & 0x0f;
+
+    if ($compact_type == TType::STOP) {
+      $field_type = $compact_type;
+      $field_id = 0;
+
+      return $result;
+    }
+    $delta = $compact_type_and_delta >> 4;
+    if ($delta == 0) {
+      $result += $this->readI16($field_id);
+    } else {
+      $field_id = $this->lastFid + $delta;
+    }
+    $this->lastFid = $field_id;
+    $field_type = $this->getTType($compact_type);
+
+    if ($compact_type == TCompactProtocol::COMPACT_TRUE) {
+      $this->state = TCompactProtocol::STATE_BOOL_READ;
+      $this->boolValue = true;
+    } elseif ($compact_type == TCompactProtocol::COMPACT_FALSE) {
+      $this->state = TCompactProtocol::STATE_BOOL_READ;
+      $this->boolValue = false;
+    } else {
+      $this->state = TCompactProtocol::STATE_VALUE_READ;
+    }
+
+    return $result;
+  }
+
+  public function readFieldEnd()
+  {
+    $this->state = TCompactProtocol::STATE_FIELD_READ;
+
+    return 0;
+  }
+
+  public function readUByte(&$value)
+  {
+    $data = $this->trans_->readAll(1);
+    $arr = unpack('C', $data);
+    $value = $arr[1];
+
+    return 1;
+  }
+
+  public function readByte(&$value)
+  {
+    $data = $this->trans_->readAll(1);
+    $arr = unpack('c', $data);
+    $value = $arr[1];
+
+    return 1;
+  }
+
+  public function readZigZag(&$value)
+  {
+    $result = $this->readVarint($value);
+    $value = $this->fromZigZag($value);
+
+    return $result;
+  }
+
+  public function readMessageBegin(&$name, &$type, &$seqid)
+  {
+    $protoId = 0;
+    $result = $this->readUByte($protoId);
+    if ($protoId != TCompactProtocol::PROTOCOL_ID) {
+      throw new TProtocolException('Bad protocol id in TCompact message');
+    }
+    $verType = 0;
+    $result += $this->readUByte($verType);
+    $type = ($verType >> TCompactProtocol::TYPE_SHIFT_AMOUNT) & TCompactProtocol::TYPE_BITS;
+    $version = $verType & TCompactProtocol::VERSION_MASK;
+    if ($version != TCompactProtocol::VERSION) {
+      throw new TProtocolException('Bad version in TCompact message');
+    }
+    $result += $this->readVarint($seqid);
+    $result += $this->readString($name);
+
+    return $result;
+  }
+
+  public function readMessageEnd()
+  {
+    return 0;
+  }
+
+  public function readStructBegin(&$name)
+  {
+    $name = ''; // unused
+    $this->structs[] = array($this->state, $this->lastFid);
+    $this->state = TCompactProtocol::STATE_FIELD_READ;
+    $this->lastFid = 0;
+
+    return 0;
+  }
+
+  public function readStructEnd()
+  {
+    $last = array_pop($this->structs);
+    $this->state = $last[0];
+    $this->lastFid = $last[1];
+
+    return 0;
+  }
+
+  public function readCollectionBegin(&$type, &$size)
+  {
+    $sizeType = 0;
+    $result = $this->readUByte($sizeType);
+    $size = $sizeType >> 4;
+    $type = $this->getTType($sizeType);
+    if ($size == 15) {
+      $result += $this->readVarint($size);
+    }
+    $this->containers[] = $this->state;
+    $this->state = TCompactProtocol::STATE_CONTAINER_READ;
+
+    return $result;
+  }
+
+  public function readMapBegin(&$key_type, &$val_type, &$size)
+  {
+    $result = $this->readVarint($size);
+    $types = 0;
+    if ($size > 0) {
+      $result += $this->readUByte($types);
+    }
+    $val_type = $this->getTType($types);
+    $key_type = $this->getTType($types >> 4);
+    $this->containers[] = $this->state;
+    $this->state = TCompactProtocol::STATE_CONTAINER_READ;
+
+    return $result;
+  }
+
+  public function readCollectionEnd()
+  {
+    $this->state = array_pop($this->containers);
+
+    return 0;
+  }
+
+  public function readMapEnd()
+  {
+    return $this->readCollectionEnd();
+  }
+
+  public function readListBegin(&$elem_type, &$size)
+  {
+    return $this->readCollectionBegin($elem_type, $size);
+  }
+
+  public function readListEnd()
+  {
+    return $this->readCollectionEnd();
+  }
+
+  public function readSetBegin(&$elem_type, &$size)
+  {
+    return $this->readCollectionBegin($elem_type, $size);
+  }
+
+  public function readSetEnd()
+  {
+    return $this->readCollectionEnd();
+  }
+
+  public function readBool(&$value)
+  {
+    if ($this->state == TCompactProtocol::STATE_BOOL_READ) {
+      $value = $this->boolValue;
+
+      return 0;
+    } elseif ($this->state == TCompactProtocol::STATE_CONTAINER_READ) {
+      return $this->readByte($value);
+    } else {
+      throw new TProtocolException('Invalid state in compact protocol');
+    }
+  }
+
+  public function readI16(&$value)
+  {
+    return $this->readZigZag($value);
+  }
+
+  public function readI32(&$value)
+  {
+    return $this->readZigZag($value);
+  }
+
+  public function readDouble(&$value)
+  {
+    $data = $this->trans_->readAll(8);
+    $arr = unpack('d', $data);
+    $value = $arr[1];
+
+    return 8;
+  }
+
+  public function readString(&$value)
+  {
+    $result = $this->readVarint($len);
+    if ($len) {
+      $value = $this->trans_->readAll($len);
+    } else {
+      $value = '';
+    }
+
+    return $result + $len;
+  }
+
+  public function getTType($byte)
+  {
+    return self::$ttypes[$byte & 0x0f];
+  }
+
+  // If we are on a 32bit architecture we have to explicitly deal with
+  // 64-bit twos-complement arithmetic since PHP wants to treat all ints
+  // as signed and any int over 2^31 - 1 as a float
+
+  // Read and write I64 as two 32 bit numbers $hi and $lo
+
+  public function readI64(&$value)
+  {
+    // Read varint from wire
+    $hi = 0;
+    $lo = 0;
+
+    $idx = 0;
+    $shift = 0;
+
+    while (true) {
+      $x = $this->trans_->readAll(1);
+      $arr = unpack('C', $x);
+      $byte = $arr[1];
+      $idx += 1;
+      // Shift hi and lo together.
+      if ($shift < 28) {
+        $lo |= (($byte & 0x7f) << $shift);
+      } elseif ($shift == 28) {
+        $lo |= (($byte & 0x0f) << 28);
+        $hi |= (($byte & 0x70) >> 4);
+      } else {
+        $hi |= (($byte & 0x7f) << ($shift - 32));
+      }
+      if (($byte >> 7) === 0) {
+        break;
+      }
+      $shift += 7;
+    }
+
+    // Now, unzig it.
+    $xorer = 0;
+    if ($lo & 1) {
+      $xorer = 0xffffffff;
+    }
+    $lo = ($lo >> 1) & 0x7fffffff;
+    $lo = $lo | (($hi & 1) << 31);
+    $hi = ($hi >> 1) ^ $xorer;
+    $lo = $lo ^ $xorer;
+
+    // Now put $hi and $lo back together
+    $isNeg = $hi < 0 || $hi & 0x80000000;
+
+    // Check for a negative
+    if ($isNeg) {
+      $hi = ~$hi & (int) 0xffffffff;
+      $lo = ~$lo & (int) 0xffffffff;
+
+      if ($lo == (int) 0xffffffff) {
+        $hi++;
+        $lo = 0;
+      } else {
+        $lo++;
+      }
+    }
+
+    // Force 32bit words in excess of 2G to be positive - we deal with sign
+    // explicitly below
+
+    if ($hi & (int) 0x80000000) {
+      $hi &= (int) 0x7fffffff;
+      $hi += 0x80000000;
+    }
+
+    if ($lo & (int) 0x80000000) {
+      $lo &= (int) 0x7fffffff;
+      $lo += 0x80000000;
+    }
+
+    // Create as negative value first, since we can store -2^63 but not 2^63
+    $value = -$hi * 4294967296 - $lo;
+
+    if (!$isNeg) {
+      $value = -$value;
+    }
+
+    return $idx;
+  }
+
+  public function writeI64($value)
+  {
+    // If we are in an I32 range, use the easy method below.
+    if (($value > 4294967296) || ($value < -4294967296)) {
+      // Convert $value to $hi and $lo
+      $neg = $value < 0;
+
+      if ($neg) {
+        $value *= -1;
+      }
+
+      $hi = (int) $value >> 32;
+      $lo = (int) $value & 0xffffffff;
+
+      if ($neg) {
+        $hi = ~$hi;
+        $lo = ~$lo;
+        if (($lo & (int) 0xffffffff) == (int) 0xffffffff) {
+          $lo = 0;
+          $hi++;
+        } else {
+          $lo++;
+        }
+      }
+
+      // Now do the zigging and zagging.
+      $xorer = 0;
+      if ($neg) {
+        $xorer = 0xffffffff;
+      }
+      $lowbit = ($lo >> 31) & 1;
+      $hi = ($hi << 1) | $lowbit;
+      $lo = ($lo << 1);
+      $lo = ($lo ^ $xorer) & 0xffffffff;
+      $hi = ($hi ^ $xorer) & 0xffffffff;
+
+      // now write out the varint, ensuring we shift both hi and lo
+      $out = "";
+      while (true) {
+        if (($lo & ~0x7f) === 0 &&
+           $hi === 0) {
+          $out .= chr($lo);
+          break;
+        } else {
+          $out .= chr(($lo & 0xff) | 0x80);
+          $lo = $lo >> 7;
+          $lo = $lo | ($hi << 25);
+          $hi = $hi >> 7;
+          // Right shift carries sign, but we don't want it to.
+          $hi = $hi & (127 << 25);
+        }
+      }
+
+      $ret = TStringFuncFactory::create()->strlen($out);
+      $this->trans_->write($out, $ret);
+
+      return $ret;
+    } else {
+      return $this->writeVarint($this->toZigZag($value, 64));
+    }
+  }
+}

+ 807 - 0
php/OpenSearch/Thrift/Protocol/TJSONProtocol.php

@@ -0,0 +1,807 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Type\TType;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\JSON\BaseContext;
+use Thrift\Protocol\JSON\LookaheadReader;
+use Thrift\Protocol\JSON\PairContext;
+use Thrift\Protocol\JSON\ListContext;
+
+/**
+ * JSON implementation of thrift protocol, ported from Java.
+ */
+class TJSONProtocol extends TProtocol
+{
+    const COMMA = ',';
+    const COLON = ':';
+    const LBRACE = '{';
+    const RBRACE = '}';
+    const LBRACKET = '[';
+    const RBRACKET = ']';
+    const QUOTE = '"';
+    const BACKSLASH = '\\';
+    const ZERO = '0';
+    const ESCSEQ = '\\';
+    const DOUBLEESC = '__DOUBLE_ESCAPE_SEQUENCE__';
+
+    const VERSION = 1;
+
+    public static $JSON_CHAR_TABLE = array(
+        /*  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */
+        0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, // 0
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
+        1, 1, '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+    );
+
+    public static $ESCAPE_CHARS = array('"', '\\', '/', "b", "f", "n", "r", "t");
+
+    public static $ESCAPE_CHAR_VALS = array(
+        '"', '\\', '/', "\x08", "\f", "\n", "\r", "\t",
+    );
+
+    const NAME_BOOL = "tf";
+    const NAME_BYTE = "i8";
+    const NAME_I16 = "i16";
+    const NAME_I32 = "i32";
+    const NAME_I64 = "i64";
+    const NAME_DOUBLE = "dbl";
+    const NAME_STRUCT = "rec";
+    const NAME_STRING = "str";
+    const NAME_MAP = "map";
+    const NAME_LIST = "lst";
+    const NAME_SET = "set";
+
+    private function getTypeNameForTypeID($typeID)
+    {
+        switch ($typeID) {
+            case TType::BOOL:
+                return self::NAME_BOOL;
+            case TType::BYTE:
+                return self::NAME_BYTE;
+            case TType::I16:
+                return self::NAME_I16;
+            case TType::I32:
+                return self::NAME_I32;
+            case TType::I64:
+                return self::NAME_I64;
+            case TType::DOUBLE:
+                return self::NAME_DOUBLE;
+            case TType::STRING:
+                return self::NAME_STRING;
+            case TType::STRUCT:
+                return self::NAME_STRUCT;
+            case TType::MAP:
+                return self::NAME_MAP;
+            case TType::SET:
+                return self::NAME_SET;
+            case TType::LST:
+                return self::NAME_LIST;
+            default:
+                throw new TProtocolException("Unrecognized type", TProtocolException::UNKNOWN);
+        }
+    }
+
+    private function getTypeIDForTypeName($name)
+    {
+        $result = TType::STOP;
+
+        if (strlen($name) > 1) {
+            switch (substr($name, 0, 1)) {
+                case 'd':
+                    $result = TType::DOUBLE;
+                    break;
+                case 'i':
+                    switch (substr($name, 1, 1)) {
+                        case '8':
+                            $result = TType::BYTE;
+                            break;
+                        case '1':
+                            $result = TType::I16;
+                            break;
+                        case '3':
+                            $result = TType::I32;
+                            break;
+                        case '6':
+                            $result = TType::I64;
+                            break;
+                    }
+                    break;
+                case 'l':
+                    $result = TType::LST;
+                    break;
+                case 'm':
+                    $result = TType::MAP;
+                    break;
+                case 'r':
+                    $result = TType::STRUCT;
+                    break;
+                case 's':
+                    if (substr($name, 1, 1) == 't') {
+                        $result = TType::STRING;
+                    } elseif (substr($name, 1, 1) == 'e') {
+                        $result = TType::SET;
+                    }
+                    break;
+                case 't':
+                    $result = TType::BOOL;
+                    break;
+            }
+        }
+        if ($result == TType::STOP) {
+            throw new TProtocolException("Unrecognized type", TProtocolException::INVALID_DATA);
+        }
+
+        return $result;
+    }
+
+    public $contextStack_ = array();
+    public $context_;
+    public $reader_;
+
+    private function pushContext($c)
+    {
+        array_push($this->contextStack_, $this->context_);
+        $this->context_ = $c;
+    }
+
+    private function popContext()
+    {
+        $this->context_ = array_pop($this->contextStack_);
+    }
+
+    public function __construct($trans)
+    {
+        parent::__construct($trans);
+        $this->context_ = new BaseContext();
+        $this->reader_ = new LookaheadReader($this);
+    }
+
+    public function reset()
+    {
+        $this->contextStack_ = array();
+        $this->context_ = new BaseContext();
+        $this->reader_ = new LookaheadReader($this);
+    }
+
+    private $tmpbuf_ = array(4);
+
+    public function readJSONSyntaxChar($b)
+    {
+        $ch = $this->reader_->read();
+
+        if (substr($ch, 0, 1) != $b) {
+            throw new TProtocolException("Unexpected character: " . $ch, TProtocolException::INVALID_DATA);
+        }
+    }
+
+    private function hexVal($s)
+    {
+        for ($i = 0; $i < strlen($s); $i++) {
+            $ch = substr($s, $i, 1);
+
+            if (!($ch >= "a" && $ch <= "f") && !($ch >= "0" && $ch <= "9")) {
+                throw new TProtocolException("Expected hex character " . $ch, TProtocolException::INVALID_DATA);
+            }
+        }
+
+        return hexdec($s);
+    }
+
+    private function hexChar($val)
+    {
+        return dechex($val);
+    }
+
+    private function hasJSONUnescapedUnicode()
+    {
+        if (PHP_MAJOR_VERSION > 5
+            || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4))
+            return true;
+
+        return false;
+    }
+
+    private function unescapedUnicode($str)
+    {
+        if ($this->hasJSONUnescapedUnicode()) {
+            return json_encode($str, JSON_UNESCAPED_UNICODE);
+        }
+
+        $json = json_encode($str);
+
+        /*
+         * Unescaped character outside the Basic Multilingual Plane
+         * High surrogate: 0xD800 - 0xDBFF
+         * Low surrogate: 0xDC00 - 0xDFFF
+         */
+        $json = preg_replace_callback('/\\\\u(d[89ab][0-9a-f]{2})\\\\u(d[cdef][0-9a-f]{2})/i',
+            function ($matches) {
+                return mb_convert_encoding(pack('H*', $matches[1].$matches[2]), 'UTF-8', 'UTF-16BE');
+            }, $json);
+
+        /*
+         * Unescaped characters within the Basic Multilingual Plane
+         */
+        $json = preg_replace_callback('/\\\\u([0-9a-f]{4})/i',
+            function ($matches) {
+                return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UTF-16BE');
+            }, $json);
+
+        return $json;
+    }
+
+    private function writeJSONString($b)
+    {
+        $this->context_->write();
+
+        if (is_numeric($b) && $this->context_->escapeNum()) {
+            $this->trans_->write(self::QUOTE);
+        }
+
+        $this->trans_->write($this->unescapedUnicode($b));
+
+        if (is_numeric($b) && $this->context_->escapeNum()) {
+            $this->trans_->write(self::QUOTE);
+        }
+    }
+
+    private function writeJSONInteger($num)
+    {
+        $this->context_->write();
+
+        if ($this->context_->escapeNum()) {
+            $this->trans_->write(self::QUOTE);
+        }
+
+        $this->trans_->write($num);
+
+        if ($this->context_->escapeNum()) {
+            $this->trans_->write(self::QUOTE);
+        }
+    }
+
+    private function writeJSONDouble($num)
+    {
+        $this->context_->write();
+
+        if ($this->context_->escapeNum()) {
+            $this->trans_->write(self::QUOTE);
+        }
+
+        $this->trans_->write(json_encode($num));
+
+        if ($this->context_->escapeNum()) {
+            $this->trans_->write(self::QUOTE);
+        }
+    }
+
+    private function writeJSONBase64($data)
+    {
+        $this->context_->write();
+        $this->trans_->write(self::QUOTE);
+        $this->trans_->write(json_encode(base64_encode($data)));
+        $this->trans_->write(self::QUOTE);
+    }
+
+    private function writeJSONObjectStart()
+    {
+      $this->context_->write();
+      $this->trans_->write(self::LBRACE);
+      $this->pushContext(new PairContext($this));
+    }
+
+    private function writeJSONObjectEnd()
+    {
+      $this->popContext();
+      $this->trans_->write(self::RBRACE);
+    }
+
+    private function writeJSONArrayStart()
+    {
+      $this->context_->write();
+      $this->trans_->write(self::LBRACKET);
+      $this->pushContext(new ListContext($this));
+    }
+
+    private function writeJSONArrayEnd()
+    {
+      $this->popContext();
+      $this->trans_->write(self::RBRACKET);
+    }
+
+    private function readJSONString($skipContext)
+    {
+      if (!$skipContext) {
+        $this->context_->read();
+      }
+
+      $jsonString = '';
+      $lastChar = null;
+      while (true) {
+        $ch = $this->reader_->read();
+        $jsonString .= $ch;
+        if ($ch == self::QUOTE &&
+          $lastChar !== NULL &&
+            $lastChar !== self::ESCSEQ) {
+          break;
+        }
+        if ($ch == self::ESCSEQ && $lastChar == self::ESCSEQ) {
+          $lastChar = self::DOUBLEESC;
+        } else {
+          $lastChar = $ch;
+        }
+      }
+
+      return json_decode($jsonString);
+    }
+
+    private function isJSONNumeric($b)
+    {
+        switch ($b) {
+            case '+':
+            case '-':
+            case '.':
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            case 'E':
+            case 'e':
+              return true;
+            }
+
+        return false;
+    }
+
+    private function readJSONNumericChars()
+    {
+        $strbld = array();
+
+        while (true) {
+            $ch = $this->reader_->peek();
+
+            if (!$this->isJSONNumeric($ch)) {
+                break;
+            }
+
+            $strbld[] = $this->reader_->read();
+        }
+
+        return implode("", $strbld);
+    }
+
+    private function readJSONInteger()
+    {
+        $this->context_->read();
+
+        if ($this->context_->escapeNum()) {
+            $this->readJSONSyntaxChar(self::QUOTE);
+        }
+
+        $str = $this->readJSONNumericChars();
+
+        if ($this->context_->escapeNum()) {
+            $this->readJSONSyntaxChar(self::QUOTE);
+        }
+
+        if (!is_numeric($str)) {
+            throw new TProtocolException("Invalid data in numeric: " . $str, TProtocolException::INVALID_DATA);
+        }
+
+        return intval($str);
+    }
+
+    /**
+     * Identical to readJSONInteger but without the final cast.
+     * Needed for proper handling of i64 on 32 bit machines.  Why a
+     * separate function?  So we don't have to force the rest of the
+     * use cases through the extra conditional.
+     */
+    private function readJSONIntegerAsString()
+    {
+        $this->context_->read();
+
+        if ($this->context_->escapeNum()) {
+            $this->readJSONSyntaxChar(self::QUOTE);
+        }
+
+        $str = $this->readJSONNumericChars();
+
+        if ($this->context_->escapeNum()) {
+            $this->readJSONSyntaxChar(self::QUOTE);
+        }
+
+        if (!is_numeric($str)) {
+            throw new TProtocolException("Invalid data in numeric: " . $str, TProtocolException::INVALID_DATA);
+        }
+
+        return $str;
+    }
+
+    private function readJSONDouble()
+    {
+        $this->context_->read();
+
+        if (substr($this->reader_->peek(), 0, 1) == self::QUOTE) {
+            $arr = $this->readJSONString(true);
+
+            if ($arr == "NaN") {
+                return NAN;
+            } elseif ($arr == "Infinity") {
+                return INF;
+            } elseif (!$this->context_->escapeNum()) {
+                throw new TProtocolException("Numeric data unexpectedly quoted " . $arr,
+                                              TProtocolException::INVALID_DATA);
+            }
+
+            return floatval($arr);
+        } else {
+            if ($this->context_->escapeNum()) {
+                $this->readJSONSyntaxChar(self::QUOTE);
+            }
+
+            return floatval($this->readJSONNumericChars());
+        }
+    }
+
+    private function readJSONBase64()
+    {
+        $arr = $this->readJSONString(false);
+        $data = base64_decode($arr, true);
+
+        if ($data === false) {
+            throw new TProtocolException("Invalid base64 data " . $arr, TProtocolException::INVALID_DATA);
+        }
+
+        return $data;
+    }
+
+    private function readJSONObjectStart()
+    {
+        $this->context_->read();
+        $this->readJSONSyntaxChar(self::LBRACE);
+        $this->pushContext(new PairContext($this));
+    }
+
+    private function readJSONObjectEnd()
+    {
+        $this->readJSONSyntaxChar(self::RBRACE);
+        $this->popContext();
+    }
+
+    private function readJSONArrayStart()
+    {
+        $this->context_->read();
+        $this->readJSONSyntaxChar(self::LBRACKET);
+        $this->pushContext(new ListContext($this));
+    }
+
+    private function readJSONArrayEnd()
+    {
+        $this->readJSONSyntaxChar(self::RBRACKET);
+        $this->popContext();
+    }
+
+    /**
+     * Writes the message header
+     *
+     * @param string $name  Function name
+     * @param int    $type  message type TMessageType::CALL or TMessageType::REPLY
+     * @param int    $seqid The sequence id of this message
+     */
+    public function writeMessageBegin($name, $type, $seqid)
+    {
+        $this->writeJSONArrayStart();
+        $this->writeJSONInteger(self::VERSION);
+        $this->writeJSONString($name);
+        $this->writeJSONInteger($type);
+        $this->writeJSONInteger($seqid);
+    }
+
+    /**
+     * Close the message
+     */
+    public function writeMessageEnd()
+    {
+        $this->writeJSONArrayEnd();
+    }
+
+    /**
+     * Writes a struct header.
+     *
+     * @param  string     $name Struct name
+     * @throws TException on write error
+     * @return int        How many bytes written
+     */
+    public function writeStructBegin($name)
+    {
+        $this->writeJSONObjectStart();
+    }
+
+    /**
+     * Close a struct.
+     *
+     * @throws TException on write error
+     * @return int        How many bytes written
+     */
+    public function writeStructEnd()
+    {
+        $this->writeJSONObjectEnd();
+    }
+
+    public function writeFieldBegin($fieldName, $fieldType, $fieldId)
+    {
+        $this->writeJSONInteger($fieldId);
+        $this->writeJSONObjectStart();
+        $this->writeJSONString($this->getTypeNameForTypeID($fieldType));
+    }
+
+    public function writeFieldEnd()
+    {
+        $this->writeJsonObjectEnd();
+    }
+
+    public function writeFieldStop()
+    {
+    }
+
+    public function writeMapBegin($keyType, $valType, $size)
+    {
+        $this->writeJSONArrayStart();
+        $this->writeJSONString($this->getTypeNameForTypeID($keyType));
+        $this->writeJSONString($this->getTypeNameForTypeID($valType));
+        $this->writeJSONInteger($size);
+        $this->writeJSONObjectStart();
+    }
+
+    public function writeMapEnd()
+    {
+        $this->writeJSONObjectEnd();
+        $this->writeJSONArrayEnd();
+    }
+
+    public function writeListBegin($elemType, $size)
+    {
+        $this->writeJSONArrayStart();
+        $this->writeJSONString($this->getTypeNameForTypeID($elemType));
+        $this->writeJSONInteger($size);
+    }
+
+    public function writeListEnd()
+    {
+        $this->writeJSONArrayEnd();
+    }
+
+    public function writeSetBegin($elemType, $size)
+    {
+        $this->writeJSONArrayStart();
+        $this->writeJSONString($this->getTypeNameForTypeID($elemType));
+        $this->writeJSONInteger($size);
+    }
+
+    public function writeSetEnd()
+    {
+        $this->writeJSONArrayEnd();
+    }
+
+    public function writeBool($bool)
+    {
+        $this->writeJSONInteger($bool ? 1 : 0);
+    }
+
+    public function writeByte($byte)
+    {
+        $this->writeJSONInteger($byte);
+    }
+
+    public function writeI16($i16)
+    {
+        $this->writeJSONInteger($i16);
+    }
+
+    public function writeI32($i32)
+    {
+        $this->writeJSONInteger($i32);
+    }
+
+    public function writeI64($i64)
+    {
+        $this->writeJSONInteger($i64);
+    }
+
+    public function writeDouble($dub)
+    {
+        $this->writeJSONDouble($dub);
+    }
+
+    public function writeString($str)
+    {
+        $this->writeJSONString($str);
+    }
+
+    /**
+     * Reads the message header
+     *
+     * @param string $name Function name
+     * @param int    $type message type TMessageType::CALL or TMessageType::REPLY
+     * @parem int $seqid The sequence id of this message
+     */
+    public function readMessageBegin(&$name, &$type, &$seqid)
+    {
+        $this->readJSONArrayStart();
+
+        if ($this->readJSONInteger() != self::VERSION) {
+            throw new TProtocolException("Message contained bad version", TProtocolException::BAD_VERSION);
+        }
+
+        $name = $this->readJSONString(false);
+        $type = $this->readJSONInteger();
+        $seqid = $this->readJSONInteger();
+
+        return true;
+    }
+
+    /**
+     * Read the close of message
+     */
+    public function readMessageEnd()
+    {
+        $this->readJSONArrayEnd();
+    }
+
+    public function readStructBegin(&$name)
+    {
+        $this->readJSONObjectStart();
+
+        return 0;
+    }
+
+    public function readStructEnd()
+    {
+        $this->readJSONObjectEnd();
+    }
+
+    public function readFieldBegin(&$name, &$fieldType, &$fieldId)
+    {
+        $ch = $this->reader_->peek();
+        $name = "";
+
+        if (substr($ch, 0, 1) == self::RBRACE) {
+            $fieldType = TType::STOP;
+        } else {
+            $fieldId = $this->readJSONInteger();
+            $this->readJSONObjectStart();
+            $fieldType = $this->getTypeIDForTypeName($this->readJSONString(false));
+        }
+    }
+
+    public function readFieldEnd()
+    {
+        $this->readJSONObjectEnd();
+    }
+
+    public function readMapBegin(&$keyType, &$valType, &$size)
+    {
+        $this->readJSONArrayStart();
+        $keyType = $this->getTypeIDForTypeName($this->readJSONString(false));
+        $valType = $this->getTypeIDForTypeName($this->readJSONString(false));
+        $size = $this->readJSONInteger();
+        $this->readJSONObjectStart();
+    }
+
+    public function readMapEnd()
+    {
+        $this->readJSONObjectEnd();
+        $this->readJSONArrayEnd();
+    }
+
+    public function readListBegin(&$elemType, &$size)
+    {
+        $this->readJSONArrayStart();
+        $elemType = $this->getTypeIDForTypeName($this->readJSONString(false));
+        $size = $this->readJSONInteger();
+
+        return true;
+    }
+
+    public function readListEnd()
+    {
+        $this->readJSONArrayEnd();
+    }
+
+    public function readSetBegin(&$elemType, &$size)
+    {
+        $this->readJSONArrayStart();
+        $elemType = $this->getTypeIDForTypeName($this->readJSONString(false));
+        $size = $this->readJSONInteger();
+
+        return true;
+    }
+
+    public function readSetEnd()
+    {
+        $this->readJSONArrayEnd();
+    }
+
+    public function readBool(&$bool)
+    {
+        $bool = $this->readJSONInteger() == 0 ? false : true;
+
+        return true;
+    }
+
+    public function readByte(&$byte)
+    {
+        $byte = $this->readJSONInteger();
+
+        return true;
+    }
+
+    public function readI16(&$i16)
+    {
+        $i16 = $this->readJSONInteger();
+
+        return true;
+    }
+
+    public function readI32(&$i32)
+    {
+        $i32 = $this->readJSONInteger();
+
+        return true;
+    }
+
+    public function readI64(&$i64)
+    {
+        if (PHP_INT_SIZE === 4) {
+            $i64 = $this->readJSONIntegerAsString();
+        } else {
+            $i64 = $this->readJSONInteger();
+        }
+
+        return true;
+    }
+
+    public function readDouble(&$dub)
+    {
+        $dub = $this->readJSONDouble();
+
+        return true;
+    }
+
+    public function readString(&$str)
+    {
+        $str = $this->readJSONString(false);
+
+        return true;
+    }
+}

+ 85 - 0
php/OpenSearch/Thrift/Protocol/TMultiplexedProtocol.php

@@ -0,0 +1,85 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Type\TMessageType;
+
+/**
+ * <code>TMultiplexedProtocol</code> is a protocol-independent concrete decorator
+ * that allows a Thrift client to communicate with a multiplexing Thrift server,
+ * by prepending the service name to the function name during function calls.
+ *
+ * @package Thrift\Protocol
+ */
+class TMultiplexedProtocol extends TProtocolDecorator
+{
+    /**
+     * Separator between service name and function name.
+     * Should be the same as used at multiplexed Thrift server.
+     *
+     * @var string
+     */
+    const SEPARATOR = ":";
+
+    /**
+     * The name of service.
+     *
+     * @var string
+     */
+    private $serviceName_;
+
+    /**
+     * Constructor of <code>TMultiplexedProtocol</code> class.
+     *
+     * Wrap the specified protocol, allowing it to be used to communicate with a
+     * multiplexing server.  The <code>$serviceName</code> is required as it is
+     * prepended to the message header so that the multiplexing server can broker
+     * the function call to the proper service.
+     *
+     * @param TProtocol $protocol
+     * @param string    $serviceName The name of service.
+     */
+    public function __construct(TProtocol $protocol, $serviceName)
+    {
+        parent::__construct($protocol);
+        $this->serviceName_ = $serviceName;
+    }
+
+    /**
+     * Writes the message header.
+     * Prepends the service name to the function name, separated by <code>TMultiplexedProtocol::SEPARATOR</code>.
+     *
+     * @param string $name  Function name.
+     * @param int    $type  Message type.
+     * @param int    $seqid The sequence id of this message.
+     */
+    public function writeMessageBegin($name, $type, $seqid)
+    {
+        if ($type == TMessageType::CALL || $type == TMessageType::ONEWAY) {
+            $nameWithService = $this->serviceName_ . self::SEPARATOR . $name;
+            parent::writeMessageBegin($nameWithService, $type, $seqid);
+        } else {
+            parent::writeMessageBegin($name, $type, $seqid);
+        }
+    }
+}

+ 352 - 0
php/OpenSearch/Thrift/Protocol/TProtocol.php

@@ -0,0 +1,352 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Type\TType;
+use Thrift\Exception\TProtocolException;
+
+/**
+ * Protocol base class module.
+ */
+abstract class TProtocol
+{
+  /**
+   * Underlying transport
+   *
+   * @var TTransport
+   */
+  protected $trans_;
+
+  /**
+   * Constructor
+   */
+  protected function __construct($trans)
+  {
+    $this->trans_ = $trans;
+  }
+
+  /**
+   * Accessor for transport
+   *
+   * @return TTransport
+   */
+  public function getTransport()
+  {
+    return $this->trans_;
+  }
+
+  /**
+   * Writes the message header
+   *
+   * @param string $name Function name
+   * @param int $type message type TMessageType::CALL or TMessageType::REPLY
+   * @param int $seqid The sequence id of this message
+   */
+  abstract public function writeMessageBegin($name, $type, $seqid);
+
+  /**
+   * Close the message
+   */
+  abstract public function writeMessageEnd();
+
+  /**
+   * Writes a struct header.
+   *
+   * @param string     $name Struct name
+   * @throws TException on write error
+   * @return int How many bytes written
+   */
+  abstract public function writeStructBegin($name);
+
+  /**
+   * Close a struct.
+   *
+   * @throws TException on write error
+   * @return int How many bytes written
+   */
+  abstract public function writeStructEnd();
+
+  /*
+   * Starts a field.
+   *
+   * @param string     $name Field name
+   * @param int        $type Field type
+   * @param int        $fid  Field id
+   * @throws TException on write error
+   * @return int How many bytes written
+   */
+  abstract public function writeFieldBegin($fieldName, $fieldType, $fieldId);
+
+  abstract public function writeFieldEnd();
+
+  abstract public function writeFieldStop();
+
+  abstract public function writeMapBegin($keyType, $valType, $size);
+
+  abstract public function writeMapEnd();
+
+  abstract public function writeListBegin($elemType, $size);
+
+  abstract public function writeListEnd();
+
+  abstract public function writeSetBegin($elemType, $size);
+
+  abstract public function writeSetEnd();
+
+  abstract public function writeBool($bool);
+
+  abstract public function writeByte($byte);
+
+  abstract public function writeI16($i16);
+
+  abstract public function writeI32($i32);
+
+  abstract public function writeI64($i64);
+
+  abstract public function writeDouble($dub);
+
+  abstract public function writeString($str);
+
+  /**
+   * Reads the message header
+   *
+   * @param string $name Function name
+   * @param int $type message type TMessageType::CALL or TMessageType::REPLY
+   * @parem int $seqid The sequence id of this message
+   */
+  abstract public function readMessageBegin(&$name, &$type, &$seqid);
+
+  /**
+   * Read the close of message
+   */
+  abstract public function readMessageEnd();
+
+  abstract public function readStructBegin(&$name);
+
+  abstract public function readStructEnd();
+
+  abstract public function readFieldBegin(&$name, &$fieldType, &$fieldId);
+
+  abstract public function readFieldEnd();
+
+  abstract public function readMapBegin(&$keyType, &$valType, &$size);
+
+  abstract public function readMapEnd();
+
+  abstract public function readListBegin(&$elemType, &$size);
+
+  abstract public function readListEnd();
+
+  abstract public function readSetBegin(&$elemType, &$size);
+
+  abstract public function readSetEnd();
+
+  abstract public function readBool(&$bool);
+
+  abstract public function readByte(&$byte);
+
+  abstract public function readI16(&$i16);
+
+  abstract public function readI32(&$i32);
+
+  abstract public function readI64(&$i64);
+
+  abstract public function readDouble(&$dub);
+
+  abstract public function readString(&$str);
+
+  /**
+   * The skip function is a utility to parse over unrecognized date without
+   * causing corruption.
+   *
+   * @param TType $type What type is it
+   */
+  public function skip($type)
+  {
+    switch ($type) {
+    case TType::BOOL:
+      return $this->readBool($bool);
+    case TType::BYTE:
+      return $this->readByte($byte);
+    case TType::I16:
+      return $this->readI16($i16);
+    case TType::I32:
+      return $this->readI32($i32);
+    case TType::I64:
+      return $this->readI64($i64);
+    case TType::DOUBLE:
+      return $this->readDouble($dub);
+    case TType::STRING:
+      return $this->readString($str);
+    case TType::STRUCT:
+      {
+        $result = $this->readStructBegin($name);
+        while (true) {
+          $result += $this->readFieldBegin($name, $ftype, $fid);
+          if ($ftype == TType::STOP) {
+            break;
+          }
+          $result += $this->skip($ftype);
+          $result += $this->readFieldEnd();
+        }
+        $result += $this->readStructEnd();
+
+        return $result;
+      }
+    case TType::MAP:
+      {
+        $result = $this->readMapBegin($keyType, $valType, $size);
+        for ($i = 0; $i < $size; $i++) {
+          $result += $this->skip($keyType);
+          $result += $this->skip($valType);
+        }
+        $result += $this->readMapEnd();
+
+        return $result;
+      }
+    case TType::SET:
+      {
+        $result = $this->readSetBegin($elemType, $size);
+        for ($i = 0; $i < $size; $i++) {
+          $result += $this->skip($elemType);
+        }
+        $result += $this->readSetEnd();
+
+        return $result;
+      }
+    case TType::LST:
+      {
+        $result = $this->readListBegin($elemType, $size);
+        for ($i = 0; $i < $size; $i++) {
+          $result += $this->skip($elemType);
+        }
+        $result += $this->readListEnd();
+
+        return $result;
+      }
+    default:
+      throw new TProtocolException('Unknown field type: '.$type,
+                                   TProtocolException::INVALID_DATA);
+    }
+  }
+
+  /**
+   * Utility for skipping binary data
+   *
+   * @param TTransport $itrans TTransport object
+   * @param int        $type   Field type
+   */
+  public static function skipBinary($itrans, $type)
+  {
+    switch ($type) {
+    case TType::BOOL:
+      return $itrans->readAll(1);
+    case TType::BYTE:
+      return $itrans->readAll(1);
+    case TType::I16:
+      return $itrans->readAll(2);
+    case TType::I32:
+      return $itrans->readAll(4);
+    case TType::I64:
+      return $itrans->readAll(8);
+    case TType::DOUBLE:
+      return $itrans->readAll(8);
+    case TType::STRING:
+      $len = unpack('N', $itrans->readAll(4));
+      $len = $len[1];
+      if ($len > 0x7fffffff) {
+        $len = 0 - (($len - 1) ^ 0xffffffff);
+      }
+
+      return 4 + $itrans->readAll($len);
+    case TType::STRUCT:
+      {
+        $result = 0;
+        while (true) {
+          $ftype = 0;
+          $fid = 0;
+          $data = $itrans->readAll(1);
+          $arr = unpack('c', $data);
+          $ftype = $arr[1];
+          if ($ftype == TType::STOP) {
+            break;
+          }
+          // I16 field id
+          $result += $itrans->readAll(2);
+          $result += self::skipBinary($itrans, $ftype);
+        }
+
+        return $result;
+      }
+    case TType::MAP:
+      {
+        // Ktype
+        $data = $itrans->readAll(1);
+        $arr = unpack('c', $data);
+        $ktype = $arr[1];
+        // Vtype
+        $data = $itrans->readAll(1);
+        $arr = unpack('c', $data);
+        $vtype = $arr[1];
+        // Size
+        $data = $itrans->readAll(4);
+        $arr = unpack('N', $data);
+        $size = $arr[1];
+        if ($size > 0x7fffffff) {
+          $size = 0 - (($size - 1) ^ 0xffffffff);
+        }
+        $result = 6;
+        for ($i = 0; $i < $size; $i++) {
+          $result += self::skipBinary($itrans, $ktype);
+          $result += self::skipBinary($itrans, $vtype);
+        }
+
+        return $result;
+      }
+    case TType::SET:
+    case TType::LST:
+      {
+        // Vtype
+        $data = $itrans->readAll(1);
+        $arr = unpack('c', $data);
+        $vtype = $arr[1];
+        // Size
+        $data = $itrans->readAll(4);
+        $arr = unpack('N', $data);
+        $size = $arr[1];
+        if ($size > 0x7fffffff) {
+          $size = 0 - (($size - 1) ^ 0xffffffff);
+        }
+        $result = 5;
+        for ($i = 0; $i < $size; $i++) {
+          $result += self::skipBinary($itrans, $vtype);
+        }
+
+        return $result;
+      }
+    default:
+      throw new TProtocolException('Unknown field type: '.$type,
+                                   TProtocolException::INVALID_DATA);
+    }
+  }
+}

+ 284 - 0
php/OpenSearch/Thrift/Protocol/TProtocolDecorator.php

@@ -0,0 +1,284 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol;
+use Thrift\Exception\TException;
+
+/**
+ * <code>TProtocolDecorator</code> forwards all requests to an enclosed
+ * <code>TProtocol</code> instance, providing a way to author concise
+ * concrete decorator subclasses. While it has no abstract methods, it
+ * is marked abstract as a reminder that by itself, it does not modify
+ * the behaviour of the enclosed <code>TProtocol</code>.
+ *
+ * @package Thrift\Protocol
+ */
+abstract class TProtocolDecorator extends TProtocol
+{
+    /**
+     * Instance of protocol, to which all operations will be forwarded.
+     *
+     * @var TProtocol
+     */
+    private $concreteProtocol_;
+
+    /**
+     * Constructor of <code>TProtocolDecorator</code> class.
+     * Encloses the specified protocol.
+     *
+     * @param TProtocol $protocol All operations will be forward to this instance. Must be non-null.
+     */
+    protected function __construct(TProtocol $protocol)
+    {
+        parent::__construct($protocol->getTransport());
+        $this->concreteProtocol_ = $protocol;
+    }
+
+    /**
+     * Writes the message header.
+     *
+     * @param string $name  Function name
+     * @param int    $type  message type TMessageType::CALL or TMessageType::REPLY
+     * @param int    $seqid The sequence id of this message
+     */
+    public function writeMessageBegin($name, $type, $seqid)
+    {
+        return $this->concreteProtocol_->writeMessageBegin($name, $type, $seqid);
+    }
+
+    /**
+     * Closes the message.
+     */
+    public function writeMessageEnd()
+    {
+        return $this->concreteProtocol_->writeMessageEnd();
+    }
+
+    /**
+     * Writes a struct header.
+     *
+     * @param string $name Struct name
+     *
+     * @throws TException on write error
+     * @return int        How many bytes written
+     */
+    public function writeStructBegin($name)
+    {
+        return $this->concreteProtocol_->writeStructBegin($name);
+    }
+
+    /**
+     * Close a struct.
+     *
+     * @throws TException on write error
+     * @return int        How many bytes written
+     */
+    public function writeStructEnd()
+    {
+        return $this->concreteProtocol_->writeStructEnd();
+    }
+
+    public function writeFieldBegin($fieldName, $fieldType, $fieldId)
+    {
+        return $this->concreteProtocol_->writeFieldBegin($fieldName, $fieldType, $fieldId);
+    }
+
+    public function writeFieldEnd()
+    {
+        return $this->concreteProtocol_->writeFieldEnd();
+    }
+
+    public function writeFieldStop()
+    {
+        return $this->concreteProtocol_->writeFieldStop();
+    }
+
+    public function writeMapBegin($keyType, $valType, $size)
+    {
+        return $this->concreteProtocol_->writeMapBegin($keyType, $valType, $size);
+    }
+
+    public function writeMapEnd()
+    {
+        return $this->concreteProtocol_->writeMapEnd();
+    }
+
+    public function writeListBegin($elemType, $size)
+    {
+        return $this->concreteProtocol_->writeListBegin($elemType, $size);
+    }
+
+    public function writeListEnd()
+    {
+        return $this->concreteProtocol_->writeListEnd();
+    }
+
+    public function writeSetBegin($elemType, $size)
+    {
+        return $this->concreteProtocol_->writeSetBegin($elemType, $size);
+    }
+
+    public function writeSetEnd()
+    {
+        return $this->concreteProtocol_->writeSetEnd();
+    }
+
+    public function writeBool($bool)
+    {
+        return $this->concreteProtocol_->writeBool($bool);
+    }
+
+    public function writeByte($byte)
+    {
+        return $this->concreteProtocol_->writeByte($byte);
+    }
+
+    public function writeI16($i16)
+    {
+        return $this->concreteProtocol_->writeI16($i16);
+    }
+
+    public function writeI32($i32)
+    {
+        return $this->concreteProtocol_->writeI32($i32);
+    }
+
+    public function writeI64($i64)
+    {
+        return $this->concreteProtocol_->writeI64($i64);
+    }
+
+    public function writeDouble($dub)
+    {
+        return $this->concreteProtocol_->writeDouble($dub);
+    }
+
+    public function writeString($str)
+    {
+        return $this->concreteProtocol_->writeString($str);
+    }
+
+    /**
+     * Reads the message header
+     *
+     * @param string $name  Function name
+     * @param int    $type  message type TMessageType::CALL or TMessageType::REPLY
+     * @param int    $seqid The sequence id of this message
+     */
+    public function readMessageBegin(&$name, &$type, &$seqid)
+    {
+        return $this->concreteProtocol_->readMessageBegin($name, $type, $seqid);
+    }
+
+    /**
+     * Read the close of message
+     */
+    public function readMessageEnd()
+    {
+        return $this->concreteProtocol_->readMessageEnd();
+    }
+
+    public function readStructBegin(&$name)
+    {
+        return $this->concreteProtocol_->readStructBegin($name);
+    }
+
+    public function readStructEnd()
+    {
+        return $this->concreteProtocol_->readStructEnd();
+    }
+
+    public function readFieldBegin(&$name, &$fieldType, &$fieldId)
+    {
+        return $this->concreteProtocol_->readFieldBegin($name, $fieldType, $fieldId);
+    }
+
+    public function readFieldEnd()
+    {
+        return $this->concreteProtocol_->readFieldEnd();
+    }
+
+    public function readMapBegin(&$keyType, &$valType, &$size)
+    {
+        $this->concreteProtocol_->readMapBegin($keyType, $valType, $size);
+    }
+
+    public function readMapEnd()
+    {
+        return $this->concreteProtocol_->readMapEnd();
+    }
+
+    public function readListBegin(&$elemType, &$size)
+    {
+        $this->concreteProtocol_->readListBegin($elemType, $size);
+    }
+
+    public function readListEnd()
+    {
+        return $this->concreteProtocol_->readListEnd();
+    }
+
+    public function readSetBegin(&$elemType, &$size)
+    {
+        return $this->concreteProtocol_->readSetBegin($elemType, $size);
+    }
+
+    public function readSetEnd()
+    {
+        return $this->concreteProtocol_->readSetEnd();
+    }
+
+    public function readBool(&$bool)
+    {
+        return $this->concreteProtocol_->readBool($bool);
+    }
+
+    public function readByte(&$byte)
+    {
+        return $this->concreteProtocol_->readByte($byte);
+    }
+
+    public function readI16(&$i16)
+    {
+        return $this->concreteProtocol_->readI16($i16);
+    }
+
+    public function readI32(&$i32)
+    {
+        return $this->concreteProtocol_->readI32($i32);
+    }
+
+    public function readI64(&$i64)
+    {
+        return $this->concreteProtocol_->readI64($i64);
+    }
+
+    public function readDouble(&$dub)
+    {
+        return $this->concreteProtocol_->readDouble($dub);
+    }
+
+    public function readString(&$str)
+    {
+        return $this->concreteProtocol_->readString($str);
+    }
+}

+ 371 - 0
php/OpenSearch/Thrift/Protocol/TSimpleJSONProtocol.php

@@ -0,0 +1,371 @@
+<?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.protocol
+ */
+
+namespace Thrift\Protocol;
+
+use Thrift\Exception\TException;
+use Thrift\Exception\TProtocolException;
+use Thrift\Protocol\SimpleJSON\Context;
+use Thrift\Protocol\SimpleJSON\ListContext;
+use Thrift\Protocol\SimpleJSON\StructContext;
+use Thrift\Protocol\SimpleJSON\MapContext;
+use Thrift\Protocol\SimpleJSON\CollectionMapKeyException;
+
+/**
+ * SimpleJSON implementation of thrift protocol, ported from Java.
+ */
+class TSimpleJSONProtocol extends TProtocol
+{
+    const COMMA = ',';
+    const COLON = ':';
+    const LBRACE = '{';
+    const RBRACE = '}';
+    const LBRACKET = '[';
+    const RBRACKET = ']';
+    const QUOTE = '"';
+
+    const NAME_MAP = "map";
+    const NAME_LIST = "lst";
+    const NAME_SET = "set";
+
+    protected $writeContext_ = null;
+    protected $writeContextStack_ = [];
+
+    /**
+     * Push a new write context onto the stack.
+     */
+    protected function pushWriteContext(Context $c) {
+        $this->writeContextStack_[] = $this->writeContext_;
+        $this->writeContext_ = $c;
+    }
+
+    /**
+     * Pop the last write context off the stack
+     */
+    protected function popWriteContext() {
+        $this->writeContext_ = array_pop($this->writeContextStack_);
+    }
+
+    /**
+     * Used to make sure that we are not encountering a map whose keys are containers
+     */
+    protected function assertContextIsNotMapKey($invalidKeyType) {
+        if ($this->writeContext_->isMapKey()) {
+            throw new CollectionMapKeyException(
+                "Cannot serialize a map with keys that are of type " .
+                $invalidKeyType
+            );
+        }
+    }
+
+    private function writeJSONString($b)
+    {
+        $this->writeContext_->write();
+
+        $this->trans_->write(json_encode((string)$b));
+    }
+
+    private function writeJSONInteger($num)
+    {
+        $isMapKey = $this->writeContext_->isMapKey();
+
+        $this->writeContext_->write();
+
+        if ($isMapKey) {
+            $this->trans_->write(self::QUOTE);
+        }
+
+        $this->trans_->write((int)$num);
+
+        if ($isMapKey) {
+            $this->trans_->write(self::QUOTE);
+        }
+    }
+
+    private function writeJSONDouble($num)
+    {
+        $isMapKey = $this->writeContext_->isMapKey();
+
+        $this->writeContext_->write();
+
+        if ($isMapKey) {
+            $this->trans_->write(self::QUOTE);
+        }
+
+        $this->trans_->write(json_encode((float)$num));
+
+        if ($isMapKey) {
+            $this->trans_->write(self::QUOTE);
+        }
+    }
+
+    /**
+     * Constructor
+     */
+    public function __construct($trans)
+    {
+        parent::__construct($trans);
+        $this->writeContext_ = new Context();
+    }
+
+    /**
+     * Writes the message header
+     *
+     * @param string $name  Function name
+     * @param int    $type  message type TMessageType::CALL or TMessageType::REPLY
+     * @param int    $seqid The sequence id of this message
+     */
+    public function writeMessageBegin($name, $type, $seqid)
+    {
+        $this->trans_->write(self::LBRACKET);
+        $this->pushWriteContext(new ListContext($this));
+        $this->writeJSONString($name);
+        $this->writeJSONInteger($type);
+        $this->writeJSONInteger($seqid);
+    }
+
+    /**
+     * Close the message
+     */
+    public function writeMessageEnd()
+    {
+        $this->popWriteContext();
+        $this->trans_->write(self::RBRACKET);
+    }
+
+    /**
+     * Writes a struct header.
+     *
+     * @param  string     $name Struct name
+     */
+    public function writeStructBegin($name)
+    {
+        $this->writeContext_->write();
+        $this->trans_->write(self::LBRACE);
+        $this->pushWriteContext(new StructContext($this));
+    }
+
+    /**
+     * Close a struct.
+     */
+    public function writeStructEnd()
+    {
+        $this->popWriteContext();
+        $this->trans_->write(self::RBRACE);
+    }
+
+    public function writeFieldBegin($fieldName, $fieldType, $fieldId)
+    {
+        $this->writeJSONString($fieldName);
+    }
+
+    public function writeFieldEnd()
+    {
+    }
+
+    public function writeFieldStop()
+    {
+    }
+
+    public function writeMapBegin($keyType, $valType, $size)
+    {
+        $this->assertContextIsNotMapKey(self::NAME_MAP);
+        $this->writeContext_->write();
+        $this->trans_->write(self::LBRACE);
+        $this->pushWriteContext(new MapContext($this));
+    }
+
+    public function writeMapEnd()
+    {
+        $this->popWriteContext();
+        $this->trans_->write(self::RBRACE);
+    }
+
+    public function writeListBegin($elemType, $size)
+    {
+        $this->assertContextIsNotMapKey(self::NAME_LIST);
+        $this->writeContext_->write();
+        $this->trans_->write(self::LBRACKET);
+        $this->pushWriteContext(new ListContext($this));
+        // No metadata!
+    }
+
+    public function writeListEnd()
+    {
+        $this->popWriteContext();
+        $this->trans_->write(self::RBRACKET);
+    }
+
+    public function writeSetBegin($elemType, $size)
+    {
+        $this->assertContextIsNotMapKey(self::NAME_SET);
+        $this->writeContext_->write();
+        $this->trans_->write(self::LBRACKET);
+        $this->pushWriteContext(new ListContext($this));
+        // No metadata!
+    }
+
+    public function writeSetEnd()
+    {
+        $this->popWriteContext();
+        $this->trans_->write(self::RBRACKET);
+    }
+
+    public function writeBool($bool)
+    {
+        $this->writeJSONInteger($bool ? 1 : 0);
+    }
+
+    public function writeByte($byte)
+    {
+        $this->writeJSONInteger($byte);
+    }
+
+    public function writeI16($i16)
+    {
+        $this->writeJSONInteger($i16);
+    }
+
+    public function writeI32($i32)
+    {
+        $this->writeJSONInteger($i32);
+    }
+
+    public function writeI64($i64)
+    {
+        $this->writeJSONInteger($i64);
+    }
+
+    public function writeDouble($dub)
+    {
+        $this->writeJSONDouble($dub);
+    }
+
+    public function writeString($str)
+    {
+        $this->writeJSONString($str);
+    }
+
+    /**
+     * Reading methods.
+     *
+     * simplejson is not meant to be read back into thrift
+     * - see http://wiki.apache.org/thrift/ThriftUsageJava
+     * - use JSON instead
+     */
+
+    public function readMessageBegin(&$name, &$type, &$seqid)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readMessageEnd()
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readStructBegin(&$name)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readStructEnd()
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readFieldBegin(&$name, &$fieldType, &$fieldId)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readFieldEnd()
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readMapBegin(&$keyType, &$valType, &$size)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readMapEnd()
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readListBegin(&$elemType, &$size)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readListEnd()
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readSetBegin(&$elemType, &$size)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readSetEnd()
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readBool(&$bool)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readByte(&$byte)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readI16(&$i16)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readI32(&$i32)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readI64(&$i64)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readDouble(&$dub)
+    {
+        throw new TException("Not implemented");
+    }
+
+    public function readString(&$str)
+    {
+        throw new TException("Not implemented");
+    }
+}

+ 85 - 0
php/OpenSearch/Thrift/Serializer/TBinarySerializer.php

@@ -0,0 +1,85 @@
+<?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.protocol
+ * @author: rmarin (marin.radu@facebook.com)
+ */
+
+namespace Thrift\Serializer;
+
+use Thrift\Transport\TMemoryBuffer;
+use Thrift\Protocol\TBinaryProtocolAccelerated;
+use Thrift\Type\TMessageType;
+
+/**
+ * Utility class for serializing and deserializing
+ * a thrift object using TBinaryProtocolAccelerated.
+ */
+class TBinarySerializer
+{
+  // NOTE(rmarin): Because thrift_protocol_write_binary
+  // adds a begin message prefix, you cannot specify
+  // a transport in which to serialize an object. It has to
+  // be a string. Otherwise we will break the compatibility with
+  // normal deserialization.
+  public static function serialize($object)
+  {
+    $transport = new TMemoryBuffer();
+    $protocol = new TBinaryProtocolAccelerated($transport);
+    if (function_exists('thrift_protocol_write_binary')) {
+      thrift_protocol_write_binary($protocol, $object->getName(),
+                                   TMessageType::REPLY, $object,
+                                   0, $protocol->isStrictWrite());
+
+      $protocol->readMessageBegin($unused_name, $unused_type,
+                                  $unused_seqid);
+    } else {
+      $object->write($protocol);
+    }
+    $protocol->getTransport()->flush();
+
+    return $transport->getBuffer();
+  }
+
+  public static function deserialize($string_object, $class_name, $buffer_size  = 8192)
+  {
+     $transport = new TMemoryBuffer();
+     $protocol = new TBinaryProtocolAccelerated($transport);
+     if (function_exists('thrift_protocol_read_binary')) {
+       // NOTE (t.heintz) TBinaryProtocolAccelerated internally wraps our TMemoryBuffer in a
+       // TBufferedTransport, so we have to retrieve it again or risk losing data when writing
+       // less than 512 bytes to the transport (see the comment there as well).
+       // @see THRIFT-1579
+       $protocol->writeMessageBegin('', TMessageType::REPLY, 0);
+       $protocolTransport = $protocol->getTransport();
+       $protocolTransport->write($string_object);
+       $protocolTransport->flush();
+
+       return thrift_protocol_read_binary($protocol, $class_name,
+                                          $protocol->isStrictRead(),
+                                          $buffer_size);
+     } else {
+       $transport->write($string_object);
+       $object = new $class_name();
+       $object->read($protocol);
+
+       return $object;
+     }
+  }
+}

+ 120 - 0
php/OpenSearch/Thrift/Server/TForkingServer.php

@@ -0,0 +1,120 @@
+<?php
+
+namespace Thrift\Server;
+
+use Thrift\Transport\TTransport;
+use Thrift\Exception\TException;
+use Thrift\Exception\TTransportException;
+
+/**
+ * A forking implementation of a Thrift server.
+ *
+ * @package thrift.server
+ */
+class TForkingServer extends TServer
+{
+  /**
+   * Flag for the main serving loop
+   *
+   * @var bool
+   */
+  private $stop_ = false;
+
+  /**
+   * List of children.
+   *
+   * @var array
+   */
+  protected $children_ = array();
+
+  /**
+   * Listens for new client using the supplied
+   * transport. We fork when a new connection
+   * arrives.
+   *
+   * @return void
+   */
+  public function serve()
+  {
+    $this->transport_->listen();
+
+    while (!$this->stop_) {
+      try {
+        $transport = $this->transport_->accept();
+
+        if ($transport != null) {
+          $pid = pcntl_fork();
+
+          if ($pid > 0) {
+            $this->handleParent($transport, $pid);
+          } elseif ($pid === 0) {
+            $this->handleChild($transport);
+          } else {
+            throw new TException('Failed to fork');
+          }
+        }
+      } catch (TTransportException $e) { }
+
+      $this->collectChildren();
+    }
+  }
+
+  /**
+   * Code run by the parent
+   *
+   * @param TTransport $transport
+   * @param int $pid
+   * @return void
+   */
+  private function handleParent(TTransport $transport, $pid)
+  {
+    $this->children_[$pid] = $transport;
+  }
+
+  /**
+   * Code run by the child.
+   *
+   * @param TTransport $transport
+   * @return void
+   */
+  private function handleChild(TTransport $transport)
+  {
+    try {
+      $inputTransport = $this->inputTransportFactory_->getTransport($transport);
+      $outputTransport = $this->outputTransportFactory_->getTransport($transport);
+      $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
+      $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
+      while ($this->processor_->process($inputProtocol, $outputProtocol)) { }
+      @$transport->close();
+    } catch (TTransportException $e) { }
+
+    exit(0);
+  }
+
+  /**
+   * Collects any children we may have
+   *
+   * @return void
+   */
+  private function collectChildren()
+  {
+    foreach ($this->children_ as $pid => $transport) {
+      if (pcntl_waitpid($pid, $status, WNOHANG) > 0) {
+        unset($this->children_[$pid]);
+        if ($transport) @$transport->close();
+      }
+    }
+  }
+
+  /**
+   * Stops the server running. Kills the transport
+   * and then stops the main serving loop
+   *
+   * @return void
+   */
+  public function stop()
+  {
+    $this->transport_->close();
+    $this->stop_ = true;
+  }
+}

+ 94 - 0
php/OpenSearch/Thrift/Server/TSSLServerSocket.php

@@ -0,0 +1,94 @@
+<?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.
+ *
+ */
+
+namespace Thrift\Server;
+
+use Thrift\Transport\TSSLSocket;
+
+/**
+ * Socket implementation of a server agent.
+ *
+ * @package thrift.transport
+ */
+class TSSLServerSocket extends TServerSocket
+{
+  /**
+   * Remote port
+   *
+   * @var resource
+   */
+  protected $context_ = null;
+
+  /**
+   * ServerSocket constructor
+   *
+   * @param string $host        Host to listen on
+   * @param int $port           Port to listen on
+   * @param resource   $context      Stream context
+   * @return void
+   */
+  public function __construct($host = 'localhost', $port = 9090, $context = null)
+  {
+    $ssl_host = $this->getSSLHost($host);
+    parent::__construct($ssl_host, $port);
+    $this->context_ = $context;
+  }
+
+  public function getSSLHost($host)
+  {
+    $transport_protocol_loc = strpos($host, "://");
+    if ($transport_protocol_loc === false) {
+      $host = 'ssl://'.$host;
+    }
+    return $host;
+  }
+
+  /**
+   * Opens a new socket server handle
+   *
+   * @return void
+   */
+  public function listen()
+  {
+    $this->listener_ = @stream_socket_server(
+      $this->host_ . ':' . $this->port_,
+      $errno,
+      $errstr,
+      STREAM_SERVER_BIND|STREAM_SERVER_LISTEN,
+      $this->context_);
+  }
+
+  /**
+   * Implementation of accept. If not client is accepted in the given time
+   *
+   * @return TSocket
+   */
+  protected function acceptImpl()
+  {
+    $handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0);
+    if(!$handle) return null;
+
+    $socket = new TSSLSocket();
+    $socket->setHandle($handle);
+
+    return $socket;
+  }
+}

+ 100 - 0
php/OpenSearch/Thrift/Server/TServer.php

@@ -0,0 +1,100 @@
+<?php
+
+namespace Thrift\Server;
+
+use Thrift\Factory\TTransportFactory;
+use Thrift\Factory\TProtocolFactory;
+
+/**
+ * Generic class for a Thrift server.
+ *
+ * @package thrift.server
+ */
+abstract class TServer
+{
+  /**
+   * Processor to handle new clients
+   *
+   * @var TProcessor
+   */
+  protected $processor_;
+
+  /**
+   * Server transport to be used for listening
+   * and accepting new clients
+   *
+   * @var TServerTransport
+   */
+  protected $transport_;
+
+  /**
+   * Input transport factory
+   *
+   * @var TTransportFactory
+   */
+  protected $inputTransportFactory_;
+
+  /**
+   * Output transport factory
+   *
+   * @var TTransportFactory
+   */
+  protected $outputTransportFactory_;
+
+  /**
+   * Input protocol factory
+   *
+   * @var TProtocolFactory
+   */
+  protected $inputProtocolFactory_;
+
+  /**
+   * Output protocol factory
+   *
+   * @var TProtocolFactory
+   */
+  protected $outputProtocolFactory_;
+
+  /**
+   * Sets up all the factories, etc
+   *
+   * @param object $processor
+   * @param TServerTransport $transport
+   * @param TTransportFactory $inputTransportFactory
+   * @param TTransportFactory $outputTransportFactory
+   * @param TProtocolFactory $inputProtocolFactory
+   * @param TProtocolFactory $outputProtocolFactory
+   * @return void
+   */
+  public function __construct($processor,
+                              TServerTransport $transport,
+                              TTransportFactory $inputTransportFactory,
+                              TTransportFactory $outputTransportFactory,
+                              TProtocolFactory $inputProtocolFactory,
+                              TProtocolFactory $outputProtocolFactory) {
+    $this->processor_ = $processor;
+    $this->transport_ = $transport;
+    $this->inputTransportFactory_ = $inputTransportFactory;
+    $this->outputTransportFactory_ = $outputTransportFactory;
+    $this->inputProtocolFactory_ = $inputProtocolFactory;
+    $this->outputProtocolFactory_ = $outputProtocolFactory;
+  }
+
+  /**
+   * Serves the server. This should never return
+   * unless a problem permits it to do so or it
+   * is interrupted intentionally
+   *
+   * @abstract
+   * @return void
+   */
+  abstract public function serve();
+
+  /**
+   * Stops the server serving
+   *
+   * @abstract
+   * @return void
+   */
+  abstract public function stop();
+}

+ 122 - 0
php/OpenSearch/Thrift/Server/TServerSocket.php

@@ -0,0 +1,122 @@
+<?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.transport
+ */
+
+namespace Thrift\Server;
+
+use Thrift\Transport\TSocket;
+
+/**
+ * Socket implementation of a server agent.
+ *
+ * @package thrift.transport
+ */
+class TServerSocket extends TServerTransport
+{
+  /**
+   * Handle for the listener socket
+   *
+   * @var resource
+   */
+  protected $listener_;
+
+  /**
+   * Port for the listener to listen on
+   *
+   * @var int
+   */
+  protected $port_;
+
+  /**
+   * Timeout when listening for a new client
+   *
+   * @var int
+   */
+  protected $acceptTimeout_ = 30000;
+
+  /**
+   * Host to listen on
+   *
+   * @var string
+   */
+  protected $host_;
+
+  /**
+   * ServerSocket constructor
+   *
+   * @param string $host        Host to listen on
+   * @param int $port           Port to listen on
+   * @return void
+   */
+  public function __construct($host = 'localhost', $port = 9090)
+  {
+    $this->host_ = $host;
+    $this->port_ = $port;
+  }
+
+  /**
+   * Sets the accept timeout
+   *
+   * @param int $acceptTimeout
+   * @return void
+   */
+  public function setAcceptTimeout($acceptTimeout)
+  {
+    $this->acceptTimeout_ = $acceptTimeout;
+  }
+
+  /**
+   * Opens a new socket server handle
+   *
+   * @return void
+   */
+  public function listen()
+  {
+    $this->listener_ = stream_socket_server('tcp://' . $this->host_ . ':' . $this->port_);
+  }
+
+  /**
+   * Closes the socket server handle
+   *
+   * @return void
+   */
+  public function close()
+  {
+    @fclose($this->listener_);
+    $this->listener_ = null;
+  }
+
+  /**
+   * Implementation of accept. If not client is accepted in the given time
+   *
+   * @return TSocket
+   */
+  protected function acceptImpl()
+  {
+    $handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0);
+    if(!$handle) return null;
+
+    $socket = new TSocket();
+    $socket->setHandle($handle);
+
+    return $socket;
+  }
+}

+ 56 - 0
php/OpenSearch/Thrift/Server/TServerTransport.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace Thrift\Server;
+
+use Thrift\Exception\TTransportException;
+
+/**
+ * Generic class for Server agent.
+ *
+ * @package thrift.transport
+ */
+abstract class TServerTransport
+{
+  /**
+   * List for new clients
+   *
+   * @abstract
+   * @return void
+   */
+  abstract public function listen();
+
+  /**
+   * Close the server
+   *
+   * @abstract
+   * @return void
+   */
+  abstract public function close();
+
+  /**
+   * Subclasses should use this to implement
+   * accept.
+   *
+   * @abstract
+   * @return TTransport
+   */
+  abstract protected function acceptImpl();
+
+  /**
+   * Uses the accept implemtation. If null is returned, an
+   * exception is thrown.
+   *
+   * @throws TTransportException
+   * @return TTransport
+   */
+  public function accept()
+  {
+    $transport = $this->acceptImpl();
+
+    if ($transport == null) {
+      throw new TTransportException("accept() may not return NULL");
+    }
+
+    return $transport;
+  }
+}

+ 58 - 0
php/OpenSearch/Thrift/Server/TSimpleServer.php

@@ -0,0 +1,58 @@
+<?php
+
+namespace Thrift\Server;
+
+use Thrift\Exception\TTransportException;
+
+/**
+ * Simple implemtation of a Thrift server.
+ *
+ * @package thrift.server
+ */
+class TSimpleServer extends TServer
+{
+  /**
+   * Flag for the main serving loop
+   *
+   * @var bool
+   */
+  private $stop_ = false;
+
+  /**
+   * Listens for new client using the supplied
+   * transport. It handles TTransportExceptions
+   * to avoid timeouts etc killing it
+   *
+   * @return void
+   */
+  public function serve()
+  {
+    $this->transport_->listen();
+
+    while (!$this->stop_) {
+      try {
+        $transport = $this->transport_->accept();
+
+        if ($transport != null) {
+          $inputTransport = $this->inputTransportFactory_->getTransport($transport);
+          $outputTransport = $this->outputTransportFactory_->getTransport($transport);
+          $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
+          $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
+          while ($this->processor_->process($inputProtocol, $outputProtocol)) { }
+        }
+      } catch (TTransportException $e) { }
+    }
+  }
+
+  /**
+   * Stops the server running. Kills the transport
+   * and then stops the main serving loop
+   *
+   * @return void
+   */
+  public function stop()
+  {
+    $this->transport_->close();
+    $this->stop_ = true;
+  }
+}

+ 40 - 0
php/OpenSearch/Thrift/StringFunc/Core.php

@@ -0,0 +1,40 @@
+<?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.
+ *
+ */
+
+namespace Thrift\StringFunc;
+
+class Core implements TStringFunc
+{
+    public function substr($str, $start, $length = null)
+    {
+        // specifying a null $length would return an empty string
+        if ($length === null) {
+            return substr($str, $start);
+        }
+
+        return substr($str, $start, $length);
+    }
+
+    public function strlen($str)
+    {
+        return strlen($str);
+    }
+}

+ 46 - 0
php/OpenSearch/Thrift/StringFunc/Mbstring.php

@@ -0,0 +1,46 @@
+<?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.
+ *
+ */
+
+namespace Thrift\StringFunc;
+
+class Mbstring implements TStringFunc
+{
+    public function substr($str, $start, $length = null)
+    {
+        /**
+         * We need to set the charset parameter, which is the second
+         * optional parameter and the first optional parameter can't
+         * be null or false as a "magic" value because that would
+         * cause an empty string to be returned, so we need to
+         * actually calculate the proper length value.
+         */
+        if ($length === null) {
+            $length = $this->strlen($str) - $start;
+        }
+
+        return mb_substr($str, $start, $length, '8bit');
+    }
+
+    public function strlen($str)
+    {
+        return mb_strlen($str, '8bit');
+    }
+}

+ 28 - 0
php/OpenSearch/Thrift/StringFunc/TStringFunc.php

@@ -0,0 +1,28 @@
+<?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.
+ *
+ */
+
+namespace Thrift\StringFunc;
+
+interface TStringFunc
+{
+    public function substr($str, $start, $length = null);
+    public function strlen($str);
+}

+ 143 - 0
php/OpenSearch/Thrift/TMultiplexedProcessor.php

@@ -0,0 +1,143 @@
+<?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\Exception\TException;
+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, usually 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_;
+    }
+}

+ 181 - 0
php/OpenSearch/Thrift/Transport/TBufferedTransport.php

@@ -0,0 +1,181 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Buffered transport. Stores data to an internal buffer that it doesn't
+ * actually write out until flush is called. For reading, we do a greedy
+ * read and then serve data out of the internal buffer.
+ *
+ * @package thrift.transport
+ */
+class TBufferedTransport extends TTransport
+{
+  /**
+   * Constructor. Creates a buffered transport around an underlying transport
+   */
+  public function __construct($transport=null, $rBufSize=512, $wBufSize=512)
+  {
+    $this->transport_ = $transport;
+    $this->rBufSize_ = $rBufSize;
+    $this->wBufSize_ = $wBufSize;
+  }
+
+  /**
+   * The underlying transport
+   *
+   * @var TTransport
+   */
+  protected $transport_ = null;
+
+  /**
+   * The receive buffer size
+   *
+   * @var int
+   */
+  protected $rBufSize_ = 512;
+
+  /**
+   * The write buffer size
+   *
+   * @var int
+   */
+  protected $wBufSize_ = 512;
+
+  /**
+   * The write buffer.
+   *
+   * @var string
+   */
+  protected $wBuf_ = '';
+
+  /**
+   * The read buffer.
+   *
+   * @var string
+   */
+  protected $rBuf_ = '';
+
+  public function isOpen()
+  {
+    return $this->transport_->isOpen();
+  }
+
+  public function open()
+  {
+    $this->transport_->open();
+  }
+
+  public function close()
+  {
+    $this->transport_->close();
+  }
+
+  public function putBack($data)
+  {
+    if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
+      $this->rBuf_ = $data;
+    } else {
+      $this->rBuf_ = ($data . $this->rBuf_);
+    }
+  }
+
+  /**
+   * The reason that we customize readAll here is that the majority of PHP
+   * streams are already internally buffered by PHP. The socket stream, for
+   * example, buffers internally and blocks if you call read with $len greater
+   * than the amount of data available, unlike recv() in C.
+   *
+   * Therefore, use the readAll method of the wrapped transport inside
+   * the buffered readAll.
+   */
+  public function readAll($len)
+  {
+    $have = TStringFuncFactory::create()->strlen($this->rBuf_);
+    if ($have == 0) {
+      $data = $this->transport_->readAll($len);
+    } elseif ($have < $len) {
+      $data = $this->rBuf_;
+      $this->rBuf_ = '';
+      $data .= $this->transport_->readAll($len - $have);
+    } elseif ($have == $len) {
+      $data = $this->rBuf_;
+      $this->rBuf_ = '';
+    } elseif ($have > $len) {
+      $data = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
+      $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
+    }
+
+    return $data;
+  }
+
+  public function read($len)
+  {
+    if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
+      $this->rBuf_ = $this->transport_->read($this->rBufSize_);
+    }
+
+    if (TStringFuncFactory::create()->strlen($this->rBuf_) <= $len) {
+      $ret = $this->rBuf_;
+      $this->rBuf_ = '';
+
+      return $ret;
+    }
+
+    $ret = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
+    $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
+
+    return $ret;
+  }
+
+  public function write($buf)
+  {
+    $this->wBuf_ .= $buf;
+    if (TStringFuncFactory::create()->strlen($this->wBuf_) >= $this->wBufSize_) {
+      $out = $this->wBuf_;
+
+      // Note that we clear the internal wBuf_ prior to the underlying write
+      // to ensure we're in a sane state (i.e. internal buffer cleaned)
+      // if the underlying write throws up an exception
+      $this->wBuf_ = '';
+      $this->transport_->write($out);
+    }
+  }
+
+  public function flush()
+  {
+    if (TStringFuncFactory::create()->strlen($this->wBuf_) > 0) {
+      $out = $this->wBuf_;
+
+      // Note that we clear the internal wBuf_ prior to the underlying write
+      // to ensure we're in a sane state (i.e. internal buffer cleaned)
+      // if the underlying write throws up an exception
+      $this->wBuf_ = '';
+      $this->transport_->write($out);
+    }
+    $this->transport_->flush();
+  }
+
+}

+ 249 - 0
php/OpenSearch/Thrift/Transport/TCurlClient.php

@@ -0,0 +1,249 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * HTTP client for Thrift
+ *
+ * @package thrift.transport
+ */
+class TCurlClient extends TTransport
+{
+  private static $curlHandle;
+
+  /**
+   * The host to connect to
+   *
+   * @var string
+   */
+  protected $host_;
+
+  /**
+   * The port to connect on
+   *
+   * @var int
+   */
+  protected $port_;
+
+  /**
+   * The URI to request
+   *
+   * @var string
+   */
+  protected $uri_;
+
+  /**
+   * The scheme to use for the request, i.e. http, https
+   *
+   * @var string
+   */
+  protected $scheme_;
+
+  /**
+   * Buffer for the HTTP request data
+   *
+   * @var string
+   */
+  protected $request_;
+
+  /**
+   * Buffer for the HTTP response data.
+   *
+   * @var binary string
+   */
+  protected $response_;
+
+  /**
+   * Read timeout
+   *
+   * @var float
+   */
+  protected $timeout_;
+
+  /**
+   * http headers
+   *
+   * @var array
+   */
+  protected $headers_;
+
+  /**
+   * Make a new HTTP client.
+   *
+   * @param string $host
+   * @param int    $port
+   * @param string $uri
+   */
+  public function __construct($host, $port=80, $uri='', $scheme = 'http')
+  {
+    if ((TStringFuncFactory::create()->strlen($uri) > 0) && ($uri{0} != '/')) {
+      $uri = '/'.$uri;
+    }
+    $this->scheme_ = $scheme;
+    $this->host_ = $host;
+    $this->port_ = $port;
+    $this->uri_ = $uri;
+    $this->request_ = '';
+    $this->response_ = null;
+    $this->timeout_ = null;
+    $this->headers_ = array();
+  }
+
+  /**
+   * Set read timeout
+   *
+   * @param float $timeout
+   */
+  public function setTimeoutSecs($timeout)
+  {
+    $this->timeout_ = $timeout;
+  }
+
+  /**
+   * Whether this transport is open.
+   *
+   * @return boolean true if open
+   */
+  public function isOpen()
+  {
+    return true;
+  }
+
+  /**
+   * Open the transport for reading/writing
+   *
+   * @throws TTransportException if cannot open
+   */
+  public function open()
+  {
+  }
+
+  /**
+   * Close the transport.
+   */
+  public function close()
+  {
+    $this->request_ = '';
+    $this->response_ = null;
+  }
+
+  /**
+   * Read some data into the array.
+   *
+   * @param int    $len How much to read
+   * @return string The data that has been read
+   * @throws TTransportException if cannot read any more data
+   */
+  public function read($len)
+  {
+    if ($len >= strlen($this->response_)) {
+      return $this->response_;
+    } else {
+      $ret = substr($this->response_, 0, $len);
+      $this->response_ = substr($this->response_, $len);
+
+      return $ret;
+    }
+  }
+
+  /**
+   * Writes some data into the pending buffer
+   *
+   * @param string $buf  The data to write
+   * @throws TTransportException if writing fails
+   */
+  public function write($buf)
+  {
+    $this->request_ .= $buf;
+  }
+
+  /**
+   * Opens and sends the actual request over the HTTP connection
+   *
+   * @throws TTransportException if a writing error occurs
+   */
+  public function flush()
+  {
+    if (!self::$curlHandle) {
+      register_shutdown_function(array('Thrift\\Transport\\TCurlClient', 'closeCurlHandle'));
+      self::$curlHandle = curl_init();
+      curl_setopt(self::$curlHandle, CURLOPT_RETURNTRANSFER, true);
+      curl_setopt(self::$curlHandle, CURLOPT_BINARYTRANSFER, true);
+      curl_setopt(self::$curlHandle, CURLOPT_USERAGENT, 'PHP/TCurlClient');
+      curl_setopt(self::$curlHandle, CURLOPT_CUSTOMREQUEST, 'POST');
+      curl_setopt(self::$curlHandle, CURLOPT_FOLLOWLOCATION, true);
+      curl_setopt(self::$curlHandle, CURLOPT_MAXREDIRS, 1);
+    }
+    // God, PHP really has some esoteric ways of doing simple things.
+    $host = $this->host_.($this->port_ != 80 ? ':'.$this->port_ : '');
+    $fullUrl = $this->scheme_."://".$host.$this->uri_;
+
+    $headers = array();
+    $defaultHeaders = array('Accept' => 'application/x-thrift',
+                     'Content-Type' => 'application/x-thrift',
+                     'Content-Length' => TStringFuncFactory::create()->strlen($this->request_));
+    foreach (array_merge($defaultHeaders, $this->headers_) as $key => $value) {
+      $headers[] = "$key: $value";
+    }
+
+    curl_setopt(self::$curlHandle, CURLOPT_HTTPHEADER, $headers);
+
+    if ($this->timeout_ > 0) {
+      curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT, $this->timeout_);
+    }
+    curl_setopt(self::$curlHandle, CURLOPT_POSTFIELDS, $this->request_);
+    $this->request_ = '';
+
+    curl_setopt(self::$curlHandle, CURLOPT_URL, $fullUrl);
+    $this->response_ = curl_exec(self::$curlHandle);
+
+    // Connect failed?
+    if (!$this->response_) {
+      curl_close(self::$curlHandle);
+      self::$curlHandle = null;
+      $error = 'TCurlClient: Could not connect to '.$fullUrl;
+      throw new TTransportException($error, TTransportException::NOT_OPEN);
+    }
+  }
+
+  public static function closeCurlHandle()
+  {
+    try {
+      if (self::$curlHandle) {
+        curl_close(self::$curlHandle);
+        self::$curlHandle = null;
+      }
+    } catch (\Exception $x) {
+      error_log('There was an error closing the curl handle: ' . $x->getMessage());
+    }
+  }
+
+  public function addHeaders($headers)
+  {
+    $this->headers_ = array_merge($this->headers_, $headers);
+  }
+
+}

+ 193 - 0
php/OpenSearch/Thrift/Transport/TFramedTransport.php

@@ -0,0 +1,193 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Framed transport. Writes and reads data in chunks that are stamped with
+ * their length.
+ *
+ * @package thrift.transport
+ */
+class TFramedTransport extends TTransport
+{
+  /**
+   * Underlying transport object.
+   *
+   * @var TTransport
+   */
+  private $transport_;
+
+  /**
+   * Buffer for read data.
+   *
+   * @var string
+   */
+  private $rBuf_;
+
+  /**
+   * Buffer for queued output data
+   *
+   * @var string
+   */
+  private $wBuf_;
+
+  /**
+   * Whether to frame reads
+   *
+   * @var bool
+   */
+  private $read_;
+
+  /**
+   * Whether to frame writes
+   *
+   * @var bool
+   */
+  private $write_;
+
+  /**
+   * Constructor.
+   *
+   * @param TTransport $transport Underlying transport
+   */
+  public function __construct($transport=null, $read=true, $write=true)
+  {
+    $this->transport_ = $transport;
+    $this->read_ = $read;
+    $this->write_ = $write;
+  }
+
+  public function isOpen()
+  {
+    return $this->transport_->isOpen();
+  }
+
+  public function open()
+  {
+    $this->transport_->open();
+  }
+
+  public function close()
+  {
+    $this->transport_->close();
+  }
+
+  /**
+   * Reads from the buffer. When more data is required reads another entire
+   * chunk and serves future reads out of that.
+   *
+   * @param int $len How much data
+   */
+  public function read($len)
+  {
+    if (!$this->read_) {
+      return $this->transport_->read($len);
+    }
+
+    if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
+      $this->readFrame();
+    }
+
+    // Just return full buff
+    if ($len >= TStringFuncFactory::create()->strlen($this->rBuf_)) {
+      $out = $this->rBuf_;
+      $this->rBuf_ = null;
+
+      return $out;
+    }
+
+    // Return TStringFuncFactory::create()->substr
+    $out = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len);
+    $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len);
+
+    return $out;
+  }
+
+  /**
+   * Put previously read data back into the buffer
+   *
+   * @param string $data data to return
+   */
+  public function putBack($data)
+  {
+    if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) {
+      $this->rBuf_ = $data;
+    } else {
+      $this->rBuf_ = ($data . $this->rBuf_);
+    }
+  }
+
+  /**
+   * Reads a chunk of data into the internal read buffer.
+   */
+  private function readFrame()
+  {
+    $buf = $this->transport_->readAll(4);
+    $val = unpack('N', $buf);
+    $sz = $val[1];
+
+    $this->rBuf_ = $this->transport_->readAll($sz);
+  }
+
+  /**
+   * Writes some data to the pending output buffer.
+   *
+   * @param string $buf The data
+   * @param int    $len Limit of bytes to write
+   */
+  public function write($buf, $len=null)
+  {
+    if (!$this->write_) {
+      return $this->transport_->write($buf, $len);
+    }
+
+    if ($len !== null && $len < TStringFuncFactory::create()->strlen($buf)) {
+      $buf = TStringFuncFactory::create()->substr($buf, 0, $len);
+    }
+    $this->wBuf_ .= $buf;
+  }
+
+  /**
+   * Writes the output buffer to the stream in the format of a 4-byte length
+   * followed by the actual data.
+   */
+  public function flush()
+  {
+    if (!$this->write_ || TStringFuncFactory::create()->strlen($this->wBuf_) == 0) {
+      return $this->transport_->flush();
+    }
+
+    $out = pack('N', TStringFuncFactory::create()->strlen($this->wBuf_));
+    $out .= $this->wBuf_;
+
+    // Note that we clear the internal wBuf_ prior to the underlying write
+    // to ensure we're in a sane state (i.e. internal buffer cleaned)
+    // if the underlying write throws up an exception
+    $this->wBuf_ = '';
+    $this->transport_->write($out);
+    $this->transport_->flush();
+  }
+
+}

+ 229 - 0
php/OpenSearch/Thrift/Transport/THttpClient.php

@@ -0,0 +1,229 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * HTTP client for Thrift
+ *
+ * @package thrift.transport
+ */
+class THttpClient extends TTransport
+{
+  /**
+   * The host to connect to
+   *
+   * @var string
+   */
+  protected $host_;
+
+  /**
+   * The port to connect on
+   *
+   * @var int
+   */
+  protected $port_;
+
+  /**
+   * The URI to request
+   *
+   * @var string
+   */
+  protected $uri_;
+
+  /**
+   * The scheme to use for the request, i.e. http, https
+   *
+   * @var string
+   */
+  protected $scheme_;
+
+  /**
+   * Buffer for the HTTP request data
+   *
+   * @var string
+   */
+  protected $buf_;
+
+  /**
+   * Input socket stream.
+   *
+   * @var resource
+   */
+  protected $handle_;
+
+  /**
+   * Read timeout
+   *
+   * @var float
+   */
+  protected $timeout_;
+
+  /**
+   * http headers
+   *
+   * @var array
+   */
+  protected $headers_;
+
+  /**
+   * Make a new HTTP client.
+   *
+   * @param string $host
+   * @param int    $port
+   * @param string $uri
+   */
+  public function __construct($host, $port=80, $uri='', $scheme = 'http')
+  {
+    if ((TStringFuncFactory::create()->strlen($uri) > 0) && ($uri{0} != '/')) {
+      $uri = '/'.$uri;
+    }
+    $this->scheme_ = $scheme;
+    $this->host_ = $host;
+    $this->port_ = $port;
+    $this->uri_ = $uri;
+    $this->buf_ = '';
+    $this->handle_ = null;
+    $this->timeout_ = null;
+    $this->headers_ = array();
+  }
+
+  /**
+   * Set read timeout
+   *
+   * @param float $timeout
+   */
+  public function setTimeoutSecs($timeout)
+  {
+    $this->timeout_ = $timeout;
+  }
+
+  /**
+   * Whether this transport is open.
+   *
+   * @return boolean true if open
+   */
+  public function isOpen()
+  {
+    return true;
+  }
+
+  /**
+   * Open the transport for reading/writing
+   *
+   * @throws TTransportException if cannot open
+   */
+  public function open() {}
+
+  /**
+   * Close the transport.
+   */
+  public function close()
+  {
+    if ($this->handle_) {
+      @fclose($this->handle_);
+      $this->handle_ = null;
+    }
+  }
+
+  /**
+   * Read some data into the array.
+   *
+   * @param int    $len How much to read
+   * @return string The data that has been read
+   * @throws TTransportException if cannot read any more data
+   */
+  public function read($len)
+  {
+    $data = @fread($this->handle_, $len);
+    if ($data === FALSE || $data === '') {
+      $md = stream_get_meta_data($this->handle_);
+      if ($md['timed_out']) {
+        throw new TTransportException('THttpClient: timed out reading '.$len.' bytes from '.$this->host_.':'.$this->port_.$this->uri_, TTransportException::TIMED_OUT);
+      } else {
+        throw new TTransportException('THttpClient: Could not read '.$len.' bytes from '.$this->host_.':'.$this->port_.$this->uri_, TTransportException::UNKNOWN);
+      }
+    }
+
+    return $data;
+  }
+
+  /**
+   * Writes some data into the pending buffer
+   *
+   * @param string $buf  The data to write
+   * @throws TTransportException if writing fails
+   */
+  public function write($buf)
+  {
+    $this->buf_ .= $buf;
+  }
+
+  /**
+   * Opens and sends the actual request over the HTTP connection
+   *
+   * @throws TTransportException if a writing error occurs
+   */
+  public function flush()
+  {
+    // God, PHP really has some esoteric ways of doing simple things.
+    $host = $this->host_.($this->port_ != 80 ? ':'.$this->port_ : '');
+
+    $headers = array();
+    $defaultHeaders = array('Host' => $host,
+                            'Accept' => 'application/x-thrift',
+                            'User-Agent' => 'PHP/THttpClient',
+                            'Content-Type' => 'application/x-thrift',
+                            'Content-Length' => TStringFuncFactory::create()->strlen($this->buf_));
+    foreach (array_merge($defaultHeaders, $this->headers_) as $key => $value) {
+        $headers[] = "$key: $value";
+    }
+
+    $options = array('method' => 'POST',
+                     'header' => implode("\r\n", $headers),
+                     'max_redirects' => 1,
+                     'content' => $this->buf_);
+    if ($this->timeout_ > 0) {
+      $options['timeout'] = $this->timeout_;
+    }
+    $this->buf_ = '';
+
+    $contextid = stream_context_create(array('http' => $options));
+    $this->handle_ = @fopen($this->scheme_.'://'.$host.$this->uri_, 'r', false, $contextid);
+
+    // Connect failed?
+    if ($this->handle_ === FALSE) {
+      $this->handle_ = null;
+      $error = 'THttpClient: Could not connect to '.$host.$this->uri_;
+      throw new TTransportException($error, TTransportException::NOT_OPEN);
+    }
+  }
+
+  public function addHeaders($headers)
+  {
+    $this->headers_ = array_merge($this->headers_, $headers);
+  }
+
+}

+ 100 - 0
php/OpenSearch/Thrift/Transport/TMemoryBuffer.php

@@ -0,0 +1,100 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * A memory buffer is a tranpsort that simply reads from and writes to an
+ * in-memory string buffer. Anytime you call write on it, the data is simply
+ * placed into a buffer, and anytime you call read, data is read from that
+ * buffer.
+ *
+ * @package thrift.transport
+ */
+class TMemoryBuffer extends TTransport
+{
+  /**
+   * Constructor. Optionally pass an initial value
+   * for the buffer.
+   */
+  public function __construct($buf = '')
+  {
+    $this->buf_ = $buf;
+  }
+
+  protected $buf_ = '';
+
+  public function isOpen()
+  {
+    return true;
+  }
+
+  public function open() {}
+
+  public function close() {}
+
+  public function write($buf)
+  {
+    $this->buf_ .= $buf;
+  }
+
+  public function read($len)
+  {
+    $bufLength = TStringFuncFactory::create()->strlen($this->buf_);
+
+    if ($bufLength === 0) {
+      throw new TTransportException('TMemoryBuffer: Could not read ' .
+                                    $len . ' bytes from buffer.',
+                                    TTransportException::UNKNOWN);
+    }
+
+    if ($bufLength <= $len) {
+      $ret = $this->buf_;
+      $this->buf_ = '';
+
+      return $ret;
+    }
+
+    $ret = TStringFuncFactory::create()->substr($this->buf_, 0, $len);
+    $this->buf_ = TStringFuncFactory::create()->substr($this->buf_, $len);
+
+    return $ret;
+  }
+
+  public function getBuffer()
+  {
+    return $this->buf_;
+  }
+
+  public function available()
+  {
+    return TStringFuncFactory::create()->strlen($this->buf_);
+  }
+
+  public function putBack($data)
+  {
+    $this->buf_ = $data.$this->buf_;
+  }
+}

+ 51 - 0
php/OpenSearch/Thrift/Transport/TNullTransport.php

@@ -0,0 +1,51 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TTransportException;
+
+/**
+ * Transport that only accepts writes and ignores them.
+ * This is useful for measuring the serialized size of structures.
+ *
+ * @package thrift.transport
+ */
+class TNullTransport extends TTransport
+{
+  public function isOpen()
+  {
+    return true;
+  }
+
+  public function open() {}
+
+  public function close() {}
+
+  public function read($len)
+  {
+    throw new TTransportException("Can't read from TNullTransport.");
+  }
+
+  public function write($buf) {}
+
+}

+ 123 - 0
php/OpenSearch/Thrift/Transport/TPhpStream.php

@@ -0,0 +1,123 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Php stream transport. Reads to and writes from the php standard streams
+ * php://input and php://output
+ *
+ * @package thrift.transport
+ */
+class TPhpStream extends TTransport
+{
+  const MODE_R = 1;
+  const MODE_W = 2;
+
+  private $inStream_ = null;
+
+  private $outStream_ = null;
+
+  private $read_ = false;
+
+  private $write_ = false;
+
+  public function __construct($mode)
+  {
+    $this->read_ = $mode & self::MODE_R;
+    $this->write_ = $mode & self::MODE_W;
+  }
+
+  public function open()
+  {
+    if ($this->read_) {
+      $this->inStream_ = @fopen(self::inStreamName(), 'r');
+      if (!is_resource($this->inStream_)) {
+        throw new TException('TPhpStream: Could not open php://input');
+      }
+    }
+    if ($this->write_) {
+      $this->outStream_ = @fopen('php://output', 'w');
+      if (!is_resource($this->outStream_)) {
+        throw new TException('TPhpStream: Could not open php://output');
+      }
+    }
+  }
+
+  public function close()
+  {
+    if ($this->read_) {
+      @fclose($this->inStream_);
+      $this->inStream_ = null;
+    }
+    if ($this->write_) {
+      @fclose($this->outStream_);
+      $this->outStream_ = null;
+    }
+  }
+
+  public function isOpen()
+  {
+    return
+      (!$this->read_ || is_resource($this->inStream_)) &&
+      (!$this->write_ || is_resource($this->outStream_));
+  }
+
+  public function read($len)
+  {
+    $data = @fread($this->inStream_, $len);
+    if ($data === FALSE || $data === '') {
+      throw new TException('TPhpStream: Could not read '.$len.' bytes');
+    }
+
+    return $data;
+  }
+
+  public function write($buf)
+  {
+    while (TStringFuncFactory::create()->strlen($buf) > 0) {
+      $got = @fwrite($this->outStream_, $buf);
+      if ($got === 0 || $got === FALSE) {
+        throw new TException('TPhpStream: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes');
+      }
+      $buf = TStringFuncFactory::create()->substr($buf, $got);
+    }
+  }
+
+  public function flush()
+  {
+    @fflush($this->outStream_);
+  }
+
+  private static function inStreamName()
+  {
+    if (php_sapi_name() == 'cli') {
+      return 'php://stdin';
+    }
+
+    return 'php://input';
+  }
+
+}

+ 112 - 0
php/OpenSearch/Thrift/Transport/TSSLSocket.php

@@ -0,0 +1,112 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TException;
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Sockets implementation of the TTransport interface.
+ *
+ * @package thrift.transport
+ */
+class TSSLSocket extends TSocket
+{
+  /**
+   * Remote port
+   *
+   * @var resource
+   */
+  protected $context_ = null;
+
+  /**
+   * Socket constructor
+   *
+   * @param string     $host         Remote hostname
+   * @param int        $port         Remote port
+   * @param resource   $context      Stream context
+   * @param bool       $persist      Whether to use a persistent socket
+   * @param string     $debugHandler Function to call for error logging
+   */
+  public function __construct($host='localhost',
+                              $port=9090,
+                              $context=null,
+                              $debugHandler=null) {
+    $this->host_ = $this->getSSLHost($host);
+    $this->port_ = $port;
+    $this->context_ = $context;
+    $this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
+  }
+
+  /**
+   * Creates a host name with SSL transport protocol
+   * if no transport protocol already specified in
+   * the host name.
+   *
+   * @param string $host    Host to listen on
+   * @return string $host   Host name with transport protocol
+   */
+  private function getSSLHost($host)
+  {
+    $transport_protocol_loc = strpos($host, "://");
+    if ($transport_protocol_loc === false) {
+      $host = 'ssl://'.$host;
+    }
+    return $host;
+  }
+
+  /**
+   * Connects the socket.
+   */
+  public function open()
+  {
+    if ($this->isOpen()) {
+      throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN);
+    }
+
+    if (empty($this->host_)) {
+      throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN);
+    }
+
+    if ($this->port_ <= 0) {
+      throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN);
+    }
+
+    $this->handle_ = @stream_socket_client($this->host_.':'.$this->port_,
+                                          $errno,
+                                          $errstr,
+                                          $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000),
+                                          STREAM_CLIENT_CONNECT,
+                                          $this->context_);
+
+    // Connect failed?
+    if ($this->handle_ === FALSE) {
+      $error = 'TSocket: Could not connect to '.$this->host_.':'.$this->port_.' ('.$errstr.' ['.$errno.'])';
+      if ($this->debug_) {
+        call_user_func($this->debugHandler_, $error);
+      }
+      throw new TException($error);
+    }
+  }
+}

+ 337 - 0
php/OpenSearch/Thrift/Transport/TSocket.php

@@ -0,0 +1,337 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TException;
+use Thrift\Exception\TTransportException;
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Sockets implementation of the TTransport interface.
+ *
+ * @package thrift.transport
+ */
+class TSocket extends TTransport
+{
+  /**
+   * Handle to PHP socket
+   *
+   * @var resource
+   */
+  protected $handle_ = null;
+
+  /**
+   * Remote hostname
+   *
+   * @var string
+   */
+  protected $host_ = 'localhost';
+
+  /**
+   * Remote port
+   *
+   * @var int
+   */
+  protected $port_ = '9090';
+
+  /**
+   * Send timeout in seconds.
+   *
+   * Combined with sendTimeoutUsec this is used for send timeouts.
+   *
+   * @var int
+   */
+  protected $sendTimeoutSec_ = 0;
+
+  /**
+   * Send timeout in microseconds.
+   *
+   * Combined with sendTimeoutSec this is used for send timeouts.
+   *
+   * @var int
+   */
+  protected $sendTimeoutUsec_ = 100000;
+
+  /**
+   * Recv timeout in seconds
+   *
+   * Combined with recvTimeoutUsec this is used for recv timeouts.
+   *
+   * @var int
+   */
+  protected $recvTimeoutSec_ = 0;
+
+  /**
+   * Recv timeout in microseconds
+   *
+   * Combined with recvTimeoutSec this is used for recv timeouts.
+   *
+   * @var int
+   */
+  protected $recvTimeoutUsec_ = 750000;
+
+  /**
+   * Persistent socket or plain?
+   *
+   * @var bool
+   */
+  protected $persist_ = false;
+
+  /**
+   * Debugging on?
+   *
+   * @var bool
+   */
+  protected $debug_ = false;
+
+  /**
+   * Debug handler
+   *
+   * @var mixed
+   */
+  protected $debugHandler_ = null;
+
+  /**
+   * Socket constructor
+   *
+   * @param string $host         Remote hostname
+   * @param int    $port         Remote port
+   * @param bool   $persist      Whether to use a persistent socket
+   * @param string $debugHandler Function to call for error logging
+   */
+  public function __construct($host='localhost',
+                              $port=9090,
+                              $persist=false,
+                              $debugHandler=null) {
+    $this->host_ = $host;
+    $this->port_ = $port;
+    $this->persist_ = $persist;
+    $this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log';
+  }
+
+  /**
+   * @param resource $handle
+   * @return void
+   */
+  public function setHandle($handle)
+  {
+    $this->handle_ = $handle;
+  }
+
+  /**
+   * Sets the send timeout.
+   *
+   * @param int $timeout  Timeout in milliseconds.
+   */
+  public function setSendTimeout($timeout)
+  {
+    $this->sendTimeoutSec_ = floor($timeout / 1000);
+    $this->sendTimeoutUsec_ =
+            ($timeout - ($this->sendTimeoutSec_ * 1000)) * 1000;
+  }
+
+  /**
+   * Sets the receive timeout.
+   *
+   * @param int $timeout  Timeout in milliseconds.
+   */
+  public function setRecvTimeout($timeout)
+  {
+    $this->recvTimeoutSec_ = floor($timeout / 1000);
+    $this->recvTimeoutUsec_ =
+            ($timeout - ($this->recvTimeoutSec_ * 1000)) * 1000;
+  }
+
+  /**
+   * Sets debugging output on or off
+   *
+   * @param bool $debug
+   */
+  public function setDebug($debug)
+  {
+    $this->debug_ = $debug;
+  }
+
+  /**
+   * Get the host that this socket is connected to
+   *
+   * @return string host
+   */
+  public function getHost()
+  {
+    return $this->host_;
+  }
+
+  /**
+   * Get the remote port that this socket is connected to
+   *
+   * @return int port
+   */
+  public function getPort()
+  {
+    return $this->port_;
+  }
+
+  /**
+   * Tests whether this is open
+   *
+   * @return bool true if the socket is open
+   */
+  public function isOpen()
+  {
+    return is_resource($this->handle_);
+  }
+
+  /**
+   * Connects the socket.
+   */
+  public function open()
+  {
+    if ($this->isOpen()) {
+      throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN);
+    }
+
+    if (empty($this->host_)) {
+      throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN);
+    }
+
+    if ($this->port_ <= 0) {
+      throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN);
+    }
+
+    if ($this->persist_) {
+      $this->handle_ = @pfsockopen($this->host_,
+                                   $this->port_,
+                                   $errno,
+                                   $errstr,
+                                   $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000));
+    } else {
+      $this->handle_ = @fsockopen($this->host_,
+                                  $this->port_,
+                                  $errno,
+                                  $errstr,
+                                  $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000));
+    }
+
+    // Connect failed?
+    if ($this->handle_ === FALSE) {
+      $error = 'TSocket: Could not connect to '.$this->host_.':'.$this->port_.' ('.$errstr.' ['.$errno.'])';
+      if ($this->debug_) {
+        call_user_func($this->debugHandler_, $error);
+      }
+      throw new TException($error);
+    }
+  }
+
+  /**
+   * Closes the socket.
+   */
+  public function close()
+  {
+    if (!$this->persist_) {
+      @fclose($this->handle_);
+      $this->handle_ = null;
+    }
+  }
+
+  /**
+   * Read from the socket at most $len bytes.
+   *
+   * This method will not wait for all the requested data, it will return as
+   * soon as any data is received.
+   *
+   * @param int $len Maximum number of bytes to read.
+   * @return string Binary data
+   */
+  public function read($len)
+  {
+    $null = null;
+    $read = array($this->handle_);
+    $readable = @stream_select($read, $null, $null, $this->recvTimeoutSec_, $this->recvTimeoutUsec_);
+
+    if ($readable > 0) {
+      $data = fread($this->handle_, $len);
+      if ($data === false) {
+          throw new TTransportException('TSocket: Could not read '.$len.' bytes from '.
+                               $this->host_.':'.$this->port_);
+      } elseif ($data == '' && feof($this->handle_)) {
+          throw new TTransportException('TSocket read 0 bytes');
+        }
+
+      return $data;
+    } elseif ($readable === 0) {
+        throw new TTransportException('TSocket: timed out reading '.$len.' bytes from '.
+                             $this->host_.':'.$this->port_);
+      } else {
+        throw new TTransportException('TSocket: Could not read '.$len.' bytes from '.
+                             $this->host_.':'.$this->port_);
+      }
+    }
+
+  /**
+   * Write to the socket.
+   *
+   * @param string $buf The data to write
+   */
+  public function write($buf)
+  {
+    $null = null;
+    $write = array($this->handle_);
+
+    // keep writing until all the data has been written
+    while (TStringFuncFactory::create()->strlen($buf) > 0) {
+      // wait for stream to become available for writing
+      $writable = @stream_select($null, $write, $null, $this->sendTimeoutSec_, $this->sendTimeoutUsec_);
+      if ($writable > 0) {
+        // write buffer to stream
+        $written = fwrite($this->handle_, $buf);
+        if ($written === -1 || $written === false) {
+          throw new TTransportException('TSocket: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes '.
+                                   $this->host_.':'.$this->port_);
+        }
+        // determine how much of the buffer is left to write
+        $buf = TStringFuncFactory::create()->substr($buf, $written);
+      } elseif ($writable === 0) {
+          throw new TTransportException('TSocket: timed out writing '.TStringFuncFactory::create()->strlen($buf).' bytes from '.
+                               $this->host_.':'.$this->port_);
+        } else {
+            throw new TTransportException('TSocket: Could not write '.TStringFuncFactory::create()->strlen($buf).' bytes '.
+                                 $this->host_.':'.$this->port_);
+        }
+      }
+    }
+
+  /**
+   * Flush output to the socket.
+   *
+   * Since read(), readAll() and write() operate on the sockets directly,
+   * this is a no-op
+   *
+   * If you wish to have flushable buffering behaviour, wrap this TSocket
+   * in a TBufferedTransport.
+   */
+  public function flush()
+  {
+    // no-op
+    }
+  }

+ 300 - 0
php/OpenSearch/Thrift/Transport/TSocketPool.php

@@ -0,0 +1,300 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Exception\TException;
+
+/**
+ * This library makes use of APC cache to make hosts as down in a web
+ * environment. If you are running from the CLI or on a system without APC
+ * installed, then these null functions will step in and act like cache
+ * misses.
+ */
+if (!function_exists('apc_fetch')) {
+  function apc_fetch($key) { return FALSE; }
+  function apc_store($key, $var, $ttl=0) { return FALSE; }
+}
+
+/**
+ * Sockets implementation of the TTransport interface that allows connection
+ * to a pool of servers.
+ *
+ * @package thrift.transport
+ */
+class TSocketPool extends TSocket
+{
+  /**
+   * Remote servers. Array of associative arrays with 'host' and 'port' keys
+   */
+  private $servers_ = array();
+
+  /**
+   * How many times to retry each host in connect
+   *
+   * @var int
+   */
+  private $numRetries_ = 1;
+
+  /**
+   * Retry interval in seconds, how long to not try a host if it has been
+   * marked as down.
+   *
+   * @var int
+   */
+  private $retryInterval_ = 60;
+
+  /**
+   * Max consecutive failures before marking a host down.
+   *
+   * @var int
+   */
+  private $maxConsecutiveFailures_ = 1;
+
+  /**
+   * Try hosts in order? or Randomized?
+   *
+   * @var bool
+   */
+  private $randomize_ = true;
+
+  /**
+   * Always try last host, even if marked down?
+   *
+   * @var bool
+   */
+  private $alwaysTryLast_ = true;
+
+  /**
+   * Socket pool constructor
+   *
+   * @param array  $hosts        List of remote hostnames
+   * @param mixed  $ports        Array of remote ports, or a single common port
+   * @param bool   $persist      Whether to use a persistent socket
+   * @param mixed  $debugHandler Function for error logging
+   */
+  public function __construct($hosts=array('localhost'),
+                              $ports=array(9090),
+                              $persist=false,
+                              $debugHandler=null) {
+    parent::__construct(null, 0, $persist, $debugHandler);
+
+    if (!is_array($ports)) {
+      $port = $ports;
+      $ports = array();
+      foreach ($hosts as $key => $val) {
+        $ports[$key] = $port;
+      }
+    }
+
+    foreach ($hosts as $key => $host) {
+      $this->servers_ []= array('host' => $host,
+                                'port' => $ports[$key]);
+    }
+  }
+
+  /**
+   * Add a server to the pool
+   *
+   * This function does not prevent you from adding a duplicate server entry.
+   *
+   * @param string $host hostname or IP
+   * @param int $port port
+   */
+  public function addServer($host, $port)
+  {
+    $this->servers_[] = array('host' => $host, 'port' => $port);
+  }
+
+  /**
+   * Sets how many time to keep retrying a host in the connect function.
+   *
+   * @param int $numRetries
+   */
+  public function setNumRetries($numRetries)
+  {
+    $this->numRetries_ = $numRetries;
+  }
+
+  /**
+   * Sets how long to wait until retrying a host if it was marked down
+   *
+   * @param int $numRetries
+   */
+  public function setRetryInterval($retryInterval)
+  {
+    $this->retryInterval_ = $retryInterval;
+  }
+
+  /**
+   * Sets how many time to keep retrying a host before marking it as down.
+   *
+   * @param int $numRetries
+   */
+  public function setMaxConsecutiveFailures($maxConsecutiveFailures)
+  {
+    $this->maxConsecutiveFailures_ = $maxConsecutiveFailures;
+  }
+
+  /**
+   * Turns randomization in connect order on or off.
+   *
+   * @param bool $randomize
+   */
+  public function setRandomize($randomize)
+  {
+    $this->randomize_ = $randomize;
+  }
+
+  /**
+   * Whether to always try the last server.
+   *
+   * @param bool $alwaysTryLast
+   */
+  public function setAlwaysTryLast($alwaysTryLast)
+  {
+    $this->alwaysTryLast_ = $alwaysTryLast;
+  }
+
+  /**
+   * Connects the socket by iterating through all the servers in the pool
+   * and trying to find one that works.
+   */
+  public function open()
+  {
+    // Check if we want order randomization
+    if ($this->randomize_) {
+      shuffle($this->servers_);
+    }
+
+    // Count servers to identify the "last" one
+    $numServers = count($this->servers_);
+
+    for ($i = 0; $i < $numServers; ++$i) {
+
+      // This extracts the $host and $port variables
+      extract($this->servers_[$i]);
+
+      // Check APC cache for a record of this server being down
+      $failtimeKey = 'thrift_failtime:'.$host.':'.$port.'~';
+
+      // Cache miss? Assume it's OK
+      $lastFailtime = apc_fetch($failtimeKey);
+      if ($lastFailtime === FALSE) {
+        $lastFailtime = 0;
+      }
+
+      $retryIntervalPassed = false;
+
+      // Cache hit...make sure enough the retry interval has elapsed
+      if ($lastFailtime > 0) {
+        $elapsed = time() - $lastFailtime;
+        if ($elapsed > $this->retryInterval_) {
+          $retryIntervalPassed = true;
+          if ($this->debug_) {
+            call_user_func($this->debugHandler_,
+                           'TSocketPool: retryInterval '.
+                           '('.$this->retryInterval_.') '.
+                           'has passed for host '.$host.':'.$port);
+          }
+        }
+      }
+
+      // Only connect if not in the middle of a fail interval, OR if this
+      // is the LAST server we are trying, just hammer away on it
+      $isLastServer = false;
+      if ($this->alwaysTryLast_) {
+        $isLastServer = ($i == ($numServers - 1));
+      }
+
+      if (($lastFailtime === 0) ||
+          ($isLastServer) ||
+          ($lastFailtime > 0 && $retryIntervalPassed)) {
+
+        // Set underlying TSocket params to this one
+        $this->host_ = $host;
+        $this->port_ = $port;
+
+        // Try up to numRetries_ connections per server
+        for ($attempt = 0; $attempt < $this->numRetries_; $attempt++) {
+          try {
+            // Use the underlying TSocket open function
+            parent::open();
+
+            // Only clear the failure counts if required to do so
+            if ($lastFailtime > 0) {
+              apc_store($failtimeKey, 0);
+            }
+
+            // Successful connection, return now
+            return;
+
+          } catch (TException $tx) {
+            // Connection failed
+          }
+        }
+
+        // Mark failure of this host in the cache
+        $consecfailsKey = 'thrift_consecfails:'.$host.':'.$port.'~';
+
+        // Ignore cache misses
+        $consecfails = apc_fetch($consecfailsKey);
+        if ($consecfails === FALSE) {
+          $consecfails = 0;
+        }
+
+        // Increment by one
+        $consecfails++;
+
+        // Log and cache this failure
+        if ($consecfails >= $this->maxConsecutiveFailures_) {
+          if ($this->debug_) {
+            call_user_func($this->debugHandler_,
+                           'TSocketPool: marking '.$host.':'.$port.
+                           ' as down for '.$this->retryInterval_.' secs '.
+                           'after '.$consecfails.' failed attempts.');
+          }
+          // Store the failure time
+          apc_store($failtimeKey, time());
+
+          // Clear the count of consecutive failures
+          apc_store($consecfailsKey, 0);
+        } else {
+          apc_store($consecfailsKey, $consecfails);
+        }
+      }
+    }
+
+    // Oh no; we failed them all. The system is totally ill!
+    $error = 'TSocketPool: All hosts in pool are down. ';
+    $hosts = array();
+    foreach ($this->servers_ as $server) {
+      $hosts []= $server['host'].':'.$server['port'];
+    }
+    $hostlist = implode(',', $hosts);
+    $error .= '('.$hostlist.')';
+    if ($this->debug_) {
+      call_user_func($this->debugHandler_, $error);
+    }
+    throw new TException($error);
+  }
+}

+ 95 - 0
php/OpenSearch/Thrift/Transport/TTransport.php

@@ -0,0 +1,95 @@
+<?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.transport
+ */
+
+namespace Thrift\Transport;
+
+use Thrift\Factory\TStringFuncFactory;
+
+/**
+ * Base interface for a transport agent.
+ *
+ * @package thrift.transport
+ */
+abstract class TTransport
+{
+  /**
+   * Whether this transport is open.
+   *
+   * @return boolean true if open
+   */
+  abstract public function isOpen();
+
+  /**
+   * Open the transport for reading/writing
+   *
+   * @throws TTransportException if cannot open
+   */
+  abstract public function open();
+
+  /**
+   * Close the transport.
+   */
+  abstract public function close();
+
+  /**
+   * Read some data into the array.
+   *
+   * @param int    $len How much to read
+   * @return string The data that has been read
+   * @throws TTransportException if cannot read any more data
+   */
+  abstract public function read($len);
+
+  /**
+   * Guarantees that the full amount of data is read.
+   *
+   * @return string The data, of exact length
+   * @throws TTransportException if cannot read data
+   */
+  public function readAll($len)
+  {
+    // return $this->read($len);
+
+    $data = '';
+    $got = 0;
+    while (($got = TStringFuncFactory::create()->strlen($data)) < $len) {
+      $data .= $this->read($len - $got);
+    }
+
+    return $data;
+  }
+
+  /**
+   * Writes the given data out.
+   *
+   * @param string $buf  The data to write
+   * @throws TTransportException if writing fails
+   */
+  abstract public function write($buf);
+
+  /**
+   * Flushes any pending data out of a buffer
+   *
+   * @throws TTransportException if a writing error occurs
+   */
+  public function flush() {}
+}

+ 50 - 0
php/OpenSearch/Thrift/Type/TConstant.php

@@ -0,0 +1,50 @@
+<?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
+ */
+
+namespace Thrift\Type;
+
+/**
+ * Base class for constant Management
+ */
+abstract class TConstant
+{
+    /**
+     * Don't instanciate this class
+     */
+    protected function __construct() {}
+
+    /**
+     * Get a constant value
+     * @param  string $constant
+     * @return mixed
+     */
+    public static function get($constant)
+    {
+        if (is_null(static::$$constant)) {
+            static::$$constant = call_user_func(
+                    sprintf('static::init_%s', $constant)
+                );
+        }
+
+        return static::$$constant;
+    }
+}

+ 34 - 0
php/OpenSearch/Thrift/Type/TMessageType.php

@@ -0,0 +1,34 @@
+<?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
+ */
+
+namespace Thrift\Type;
+
+/**
+ * Message types for RPC
+ */
+class TMessageType
+{
+  const CALL  = 1;
+  const REPLY = 2;
+  const EXCEPTION = 3;
+  const ONEWAY = 4;
+}

+ 47 - 0
php/OpenSearch/Thrift/Type/TType.php

@@ -0,0 +1,47 @@
+<?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
+ */
+
+namespace Thrift\Type;
+
+/**
+ * Data types that can be sent via Thrift
+ */
+class TType
+{
+  const STOP   = 0;
+  const VOID   = 1;
+  const BOOL   = 2;
+  const BYTE   = 3;
+  const I08    = 3;
+  const DOUBLE = 4;
+  const I16    = 6;
+  const I32    = 8;
+  const I64    = 10;
+  const STRING = 11;
+  const UTF7   = 11;
+  const STRUCT = 12;
+  const MAP    = 13;
+  const SET    = 14;
+  const LST    = 15;    // N.B. cannot use LIST keyword in PHP!
+  const UTF8   = 16;
+  const UTF16  = 17;
+}

+ 222 - 0
php/OpenSearch/Util/ClauseParamsBuilder.php

@@ -0,0 +1,222 @@
+<?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.
+ */
+
+namespace OpenSearch\Util;
+
+use OpenSearch\Generated\Search\Constant;
+use OpenSearch\Generated\Search\Order;
+use OpenSearch\Generated\Search\searchFormat;
+
+class ClauseParamsBuilder {
+    const CONFIG_KEY = 'config';
+    const QUERY_KEY = 'query';
+    const SORT_KEY = 'sort';
+    const DISTINCT_KEY = 'distinct';
+    const AGGREGATE_KEY = 'aggregate';
+    const FILTER_KEY = 'filter';
+    const KVPAIRS = 'kvpairs';
+
+    const CLAUSE_SEPARATOR = '&&';
+    const KV_SEPARATOR = '=';
+    const CLAUSE_CONFIG_SEPARATOR = ',';
+    const CLAUSE_CONFIG_KV_SEPARATOR = ':';
+
+    const CLAUSE_SORT_SEPARATOR = ';';
+
+    const CLAUSE_DISTINCT_KV_SEPARATOR = ':';
+    const CLAUSE_DISTINCT_SEPARATOR = ';';
+    const CLAUSE_DISTINCT_SUB_SEPARATOR = ',';
+
+    const CLAUSE_AGGREGATE_KV_SEPARATOR = ':';
+    const CLAUSE_AGGREGATE_SEPARATOR = ';';
+    const CLAUSE_AGGREGATE_SUB_SEPARATOR = ',';
+
+    const CONFIG_CLAUSE_START = 'CONFIG_CLAUSE_START';
+    const CONFIG_CLAUSE_HIT = 'CONFIG_CLAUSE_HIT';
+    const CONFIG_CLAUSE_RERANK_SIZE = 'CONFIG_CLAUSE_RERANK_SIZE';
+    const CONFIG_CLAUSE_FORMAT = 'CONFIG_CLAUSE_FORMAT';
+
+    const DISTINCT_CLAUSE_DIST_KEY = 'DISTINCT_CLAUSE_DIST_KEY';
+    const DISTINCT_CLAUSE_DIST_COUNT = 'DISTINCT_CLAUSE_DIST_COUNT';
+    const DISTINCT_CLAUSE_DIST_TIMES = 'DISTINCT_CLAUSE_DIST_TIMES';
+    const DISTINCT_CLAUSE_RESERVED = 'DISTINCT_CLAUSE_RESERVED';
+    const DISTINCT_CLAUSE_DIST_FILTER = 'DISTINCT_CLAUSE_DIST_FILTER';
+    const DISTINCT_CLAUSE_UPDATE_TOTAL_HIT = 'DISTINCT_CLAUSE_UPDATE_TOTAL_HIT';
+    const DISTINCT_CLAUSE_GRADE = 'DISTINCT_CLAUSE_GRADE';
+
+    const AGGREGATE_CLAUSE_GROUP_KEY = 'AGGREGATE_CLAUSE_GROUP_KEY';
+    const AGGREGATE_CLAUSE_AGG_FUN = 'AGGREGATE_CLAUSE_AGG_FUN';
+    const AGGREGATE_CLAUSE_RANGE = 'AGGREGATE_CLAUSE_RANGE';
+    const AGGREGATE_CLAUSE_MAX_GROUP = 'AGGREGATE_CLAUSE_MAX_GROUP';
+    const AGGREGATE_CLAUSE_AGG_FILTER = 'AGGREGATE_CLAUSE_AGG_FILTER';
+    const AGGREGATE_CLAUSE_AGG_SAMPLER_THRESHOLD = 'AGGREGATE_CLAUSE_AGG_SAMPLER_THRESHOLD';
+    const AGGREGATE_CLAUSE_AGG_SAMPLER_STEP = 'AGGREGATE_CLAUSE_AGG_SAMPLER_STEP';
+
+    private $params;
+
+    private $clauses = array();
+
+    public function __construct($params) {
+        $this->params = $params;
+    }
+
+    private function buildConfigClause() {
+        $config = array();
+        if (isset($this->params->config->start)) {
+            $config[] = Constant::get(self::CONFIG_CLAUSE_START) .
+                self::CLAUSE_CONFIG_KV_SEPARATOR . $this->params->config->start;
+        }
+
+        if (isset($this->params->config->hits)) {
+            $config[] = Constant::get(self::CONFIG_CLAUSE_HIT) .
+                self::CLAUSE_CONFIG_KV_SEPARATOR . $this->params->config->hits;
+        }
+
+        if (isset($this->params->config->searchFormat)) {
+            $format = $this->params->config->searchFormat;
+            $config[] = Constant::get(self::CONFIG_CLAUSE_FORMAT) .
+                self::CLAUSE_CONFIG_KV_SEPARATOR . strtolower(searchFormat::$__names[$format]);
+        }
+
+        if (isset($this->params->rank->reRankSize)) {
+            $config[] = Constant::get(self::CONFIG_CLAUSE_RERANK_SIZE) .
+                self::CLAUSE_CONFIG_KV_SEPARATOR . $this->params->rank->reRankSize;
+        }
+
+        if (isset($this->params->config->customConfig)) {
+            foreach ($this->params->config->customConfig as $k => $v) {
+                $config[] = $k . self::CLAUSE_CONFIG_KV_SEPARATOR . $v;
+            }
+        }
+
+        $this->clauses[self::CONFIG_KEY] = implode(self::CLAUSE_CONFIG_SEPARATOR, $config);
+    }
+
+    private function buildQueryClause() {
+        if ($this->params->query !== null) {
+            $this->clauses[self::QUERY_KEY] = $this->params->query;
+        }
+    }
+
+    private function buildSortClause() {
+        $sorts = array();
+        if (isset($this->params->sort->sortFields)) {
+            foreach ($this->params->sort->sortFields as $sortField) {
+                $order = $sortField->order;
+                $orderString = Order::$__names[$order];
+                $sorts[] = Constant::get('SORT_CLAUSE_' . $orderString) . $sortField->field;
+            }
+
+            $this->clauses[self::SORT_KEY] = implode(self::CLAUSE_SORT_SEPARATOR, $sorts);
+        }
+    }
+
+    private function buildFilterClause() {
+        if (isset($this->params->filter)) {
+            $this->clauses[self::FILTER_KEY] = $this->params->filter;
+        }
+    }
+
+    private function buildDistinctClause() {
+        $distincts = array();
+        if (isset($this->params->distincts)) {
+            $keys = array(
+                'key' => self::DISTINCT_CLAUSE_DIST_KEY,
+                'distCount' => self::DISTINCT_CLAUSE_DIST_COUNT,
+                'distTimes' => self::DISTINCT_CLAUSE_DIST_TIMES,
+                'reserved' => self::DISTINCT_CLAUSE_RESERVED,
+                'distFilter' => self::DISTINCT_CLAUSE_DIST_FILTER,
+                'updateTotalHit' => self::DISTINCT_CLAUSE_UPDATE_TOTAL_HIT,
+                'grade' => self::DISTINCT_CLAUSE_GRADE
+            );
+            foreach ($this->params->distincts as $distinct) {
+                if (!isset($distinct->key)) {
+                    continue;
+                }
+
+                $dist = array();
+                foreach ($keys as $k => $v) {
+                    if ($distinct->$k) {
+                        $dist[] = Constant::get($v) . self::CLAUSE_AGGREGATE_KV_SEPARATOR . $distinct->$k;
+                    }
+                }
+
+                $distincts[] = implode(self::CLAUSE_DISTINCT_SUB_SEPARATOR, $dist);
+            }
+
+            $this->clauses[self::DISTINCT_KEY] = implode(self::CLAUSE_DISTINCT_SEPARATOR, $distincts);
+        }
+    }
+
+    private function buildAggregateClause() {
+        $aggregates = array();
+        if (isset($this->params->aggregates)) {
+            $keys = array(
+                'groupKey' => self::AGGREGATE_CLAUSE_GROUP_KEY,
+                'aggFun' => self::AGGREGATE_CLAUSE_AGG_FUN,
+                'range' => self::AGGREGATE_CLAUSE_RANGE,
+                'maxGroup' => self::AGGREGATE_CLAUSE_MAX_GROUP,
+                'aggFilter' => self::AGGREGATE_CLAUSE_AGG_FILTER,
+                'aggSamplerThresHold' => self::AGGREGATE_CLAUSE_AGG_SAMPLER_THRESHOLD,
+                'aggSamplerStep' => self::AGGREGATE_CLAUSE_AGG_SAMPLER_STEP
+            );
+
+            foreach ($this->params->aggregates as $aggregate) {
+                if (!isset($aggregate->groupKey) || !isset($aggregate->aggFun)) {
+                    continue;
+                }
+
+                $agg = array();
+                foreach ($keys as $k => $v) {
+                    if (isset($aggregate->$k)) {
+                        $agg[] = Constant::get($v) . self::CLAUSE_AGGREGATE_KV_SEPARATOR . $aggregate->$k;
+                    }
+                }
+
+                $aggregates[] = implode(self::CLAUSE_AGGREGATE_SUB_SEPARATOR, $agg);
+            }
+
+            $this->clauses[self::AGGREGATE_KEY] = implode(self::CLAUSE_AGGREGATE_SEPARATOR, $aggregates);
+        }
+    }
+
+    private function buildKVPairsClause() {
+        if (isset($this->params->config->kvpairs)) {
+            $this->clauses[self::KVPAIRS] = $this->params->config->kvpairs;
+        }
+    }
+
+    public function getClausesString() {
+        $this->buildConfigClause();
+        $this->buildQueryClause();
+        $this->buildSortClause();
+        $this->buildFilterClause();
+        $this->buildDistinctClause();
+        $this->buildAggregateClause();
+        $this->buildKVPairsClause();
+
+        $clauses = array();
+        foreach ($this->clauses as $clauseKey => $value) {
+            $clauses[] = $clauseKey . self::KV_SEPARATOR . $value;
+        }
+
+        return implode(self::CLAUSE_SEPARATOR, $clauses);
+    }
+}

+ 506 - 0
php/OpenSearch/Util/SearchParamsBuilder.php

@@ -0,0 +1,506 @@
+<?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.
+ */
+
+namespace OpenSearch\Util;
+
+use OpenSearch\Generated\Search\Aggregate;
+use OpenSearch\Generated\Search\Distinct;
+use OpenSearch\Generated\Search\Config;
+use OpenSearch\Generated\Search\Constant;
+use OpenSearch\Generated\Search\Order;
+use OpenSearch\Generated\Search\Rank;
+use OpenSearch\Generated\Search\SearchFormat;
+use OpenSearch\Generated\Search\SearchParams;
+use OpenSearch\Generated\Search\Sort;
+use OpenSearch\Generated\Search\SortField;
+use OpenSearch\Generated\Search\Summary;
+use OpenSearch\Generated\Search\DeepPaging;
+use OpenSearch\Generated\Search\Abtest;
+
+/**
+ * 搜索配置项。
+ */
+class SearchParamsBuilder {
+
+    const SORT_INCREASE = 1;
+    const SORT_DECREASE = 0;
+
+    private $searchParams;
+
+    public function __construct($opts = array()) {
+
+        $config = new Config();
+        $this->searchParams = new SearchParams(array('config' => $config));
+
+        if (isset($opts['start'])) {
+            $this->setStart($opts['start']);
+        }
+
+        if (isset($opts['hits'])) {
+            $this->setHits($opts['hits']);
+        }
+
+        if (isset($opts['format'])) {
+            $this->setFormat($opts['format']);
+        }
+
+        if (isset($opts['appName'])) {
+            $this->setAppName($opts['appName']);
+        }
+
+        if (isset($opts['query'])) {
+            $this->setQuery($opts['query']);
+        }
+
+        if (isset($opts['kvpairs'])) {
+            $this->setKvPairs($opts['kvpairs']);
+        }
+
+        if (isset($opts['fetchFields'])) {
+            $this->setFetchFields($opts['fetchFields']);
+        }
+
+        if (isset($opts['routeValue'])) {
+            $this->setRouteValue($opts['routeValue']);
+        }
+
+        if (isset($opts['customConfig']) && is_array($opts['customConfig'])) {
+            foreach ($opts['customConfig'] as $k => $v) {
+                $this->setCustomConfig($k, $v);
+            }
+        }
+
+        if (isset($opts['filter'])) {
+            $this->setFilter($opts['filter']);
+        }
+
+        if (isset($opts['sort']) && is_array($opts['sort'])) {
+            foreach ($opts['sort'] as $sort) {
+                if (!isset($sort['order'])) {
+                    $sort['order'] = SELF::SORT_DECREASE;
+                }
+                $this->addSort($sort['field'], $sort['order']);
+            }
+        }
+
+        if (isset($opts['firstRankName'])) {
+            $this->setFirstRankName($opts['firstRankName']);
+        }
+
+        if (isset($opts['secondRankName'])) {
+            $this->setSecondRankName($opts['secondRankName']);
+        }
+
+        if (isset($opts['aggregate']) && isset($opts['aggregate']['groupKey'])) {
+            $this->addAggregate($opts['aggregate']);
+        } else if (isset($opts['aggregate']) && isset($opts['aggregate'][0])) {
+            foreach ($opts['aggregate'] as $aggregate) {
+                $this->addAggregate($aggregate);
+            }
+        }
+
+        if (isset($opts['distinct']) && isset($opts['distinct'][0])) {
+            foreach ($opts['distinct'] as $distinct) {
+                $this->addDistinct($distinct);
+            }
+        } else if (isset($opts['distinct']) && isset($opts['distinct']['key'])) {
+            $this->addDistinct($opts['distinct']);
+        }
+
+        if (isset($opts['summaries'])) {
+            foreach ($opts['summaries'] as $summary) {
+                $this->addSummary($summary);
+            }
+        }
+
+        if (isset($opts['qp'])) {
+            if (!is_array($opts['qp'])) {
+                $opts['qp'] = array($opts['qp']);
+            }
+            foreach ($opts['qp'] as $qp) {
+                $this->addQueryProcessor($qp);
+            }
+        }
+
+        if (isset($opts['disableFunctions']) && is_array($opts['disableFunctions'])) {
+            foreach ($opts['disableFunctions'] as $fun) {
+                $this->addDisableFunctions($fun);
+            }
+        } else if (isset($opts['disableFunctions'])) {
+            $this->addDisableFunctions($opts['disableFunctions']);
+        }
+
+        if (isset($opts['customParams'])) {
+            foreach ($opts['customParams'] as $key => $value) {
+                $this->setCustomParam($key, $value);
+            }
+        }
+
+        if (isset($opts['reRankSize'])) {
+            $this->setReRankSize($opts['reRankSize']);
+        }
+    }
+
+    /**
+     * 设置返回结果的偏移量。
+     *
+     * @param int $start 偏移量,范围[0,5000]。
+     * @return void
+     */
+    public function setStart($start) {
+        $this->searchParams->config->start = (int) $start;
+    }
+
+    /**
+     * 设置返回结果的条数。
+     *
+     * @param int $hits 返回结果的条数,范围[0,500]。
+     * @return void
+     */
+    public function setHits($hits) {
+        $this->searchParams->config->hits = $hits;
+    }
+
+    /**
+     * 设置返回结果的格式。
+     *
+     * @param String $format 返回结果的格式,有json、fulljson和xml格式。
+     * @return void
+     */
+    public function setFormat($format) {
+        $upperFormat = strtoupper($format);
+        $this->searchParams->config->searchFormat = array_search($upperFormat, SearchFormat::$__names);
+    }
+
+    /**
+     * 设置要搜索的应用名称或ID。
+     *
+     * @param String $appName 指定要搜索的应用名称或ID。
+     * @return void
+     */
+    public function setAppName($appNames) {
+        $this->searchParams->config->appNames = is_array($appNames) ? $appNames : array($appNames);
+    }
+
+    /**
+     * 设置搜索关键词。
+     *
+     * @param String $query 设置的搜索关键词,格式为:索引名:'关键词' [AND|OR ...]
+     * @return void
+     */
+    public function setQuery($query) {
+        $this->searchParams->query = $query;
+    }
+
+    /**
+     * 设置KVpairs。
+     *
+     * @param String $kvPairs 设置kvpairs。
+     * @return void
+     */
+    public function setKvPairs($kvPairs) {
+        $this->searchParams->config->kvpairs = $kvPairs;
+    }
+
+    /**
+     * 设置结果集的返回字段。
+     *
+     * @param array $fetchFields 指定的返回字段的列表,例如array('a', 'b')
+     * @return void
+     */
+    public function setFetchFields($fetchFields) {
+        $this->searchParams->config->fetchFields = $fetchFields;
+    }
+
+    /**
+     * 如果分组查询时,指定分组的值。
+     *
+     * @param Mixed $routeValue 分组字段值。
+     * @return void
+     */
+    public function setRouteValue($routeValue) {
+        $this->searchParams->config->routeValue = $routeValue;
+    }
+
+    /**
+     * 设置参与精排个数。
+     *
+     * @param int $reRankSize 参与精排个数,范围[0,2000]。
+     * @return void
+     */
+    public function setReRankSize($reRankSize) {
+        $this->searchParams->rank->reRankSize = $reRankSize;
+    }
+
+    /**
+     * 在Config字句中增加自定义的参数。
+     *
+     * @param String $key 设定自定义参数名。
+     * @param Mixed $value 设定自定义参数值。
+     * @return void
+     */
+    public function setCustomConfig($key, $value) {
+        if ($this->searchParams->config->customConfig == null) {
+            $this->searchParams->config->customConfig = array();
+        }
+
+        $this->searchParams->config->customConfig[$key] = $value;
+    }
+
+    /**
+     * 添加过滤条件。
+     *
+     * @param String $filter 过滤,例如a>1。
+     * @param String $condition 两个过滤条件的连接符, 例如AND OR等。
+     * @return void
+     */
+    public function addFilter($filter, $condition = 'AND') {
+        if ($this->searchParams->filter == null) {
+            $this->searchParams->filter = $filter;
+        } else {
+            $this->searchParams->filter .= " {$condition} $filter";
+        }
+    }
+
+    /**
+     * 设置过滤条件。
+     *
+     * @param String $filterSting 过滤,例如a>1 OR b<2。
+     * @return void
+     */
+    public function setFilter($filterString) {
+        $this->searchParams->filter = $filterString;
+    }
+
+    /**
+     * 添加排序规则。
+     *
+     * @param String $field 排序字段。
+     * @param int $sort 排序策略,有降序0或者升序1,默认降序。
+     * @return void
+     */
+    public function addSort($field, $order = self::SORT_DECREASE) {
+        if ($this->searchParams->sort == null) {
+            $this->searchParams->sort = new Sort();
+            $this->searchParams->sort->sortFields = array();
+        }
+        $sortField = new SortField(array('field' => $field, 'order' => $order));
+        $this->searchParams->sort->sortFields[] = $sortField;
+    }
+
+    /**
+     * 设置粗排表达式名称。
+     *
+     * @param String $firstRankName 指定的粗排表达式名称。
+     * @return void
+     */
+    public function setFirstRankName($firstRankName) {
+        $this->searchParams->rank->firstRankName = $firstRankName;
+    }
+
+    /**
+     * 设置精排表达式名称。
+     *
+     * @param String $secondRankName 指定的精排表达式名称。
+     * @return void
+     */
+    public function setSecondRankName($secondRankName) {
+        $this->searchParams->rank->secondRankName = $secondRankName;
+    }
+
+    /**
+     * 设置聚合配置。
+     *
+     * @param array $agg 指定的聚合配置。
+     * @return void
+     */
+    public function addAggregate($agg) {
+        $aggregate = new Aggregate($agg);
+        if ($this->searchParams->aggregates == null) {
+            $this->searchParams->aggregates = array();
+        }
+        $this->searchParams->aggregates[] = $aggregate;
+    }
+
+    /**
+     * 设置去重配置。
+     *
+     * @param array $dist 指定的去重配置。
+     * @return void
+     */
+    public function addDistinct($dist) {
+        $distinct = new Distinct($dist);
+        if ($this->searchParams->distincts == null) {
+            $this->searchParams->distincts = array();
+        }
+        $this->searchParams->distincts[] = $distinct;
+    }
+
+    /**
+     * 设置搜索结果摘要配置。
+     *
+     * @param array $summaryMeta 指定的摘要字段配置。
+     * @return void
+     */
+    public function addSummary($summaryMeta) {
+        $summary = new Summary($summaryMeta);
+        if ($this->searchParams->summaries == null) {
+            $this->searchParams->summaries = array();
+        }
+
+        $this->searchParams->summaries[] = $summary;
+    }
+
+    /**
+     * 添加查询分析配置。
+     *
+     * @param array $qpName 指定的QP名称。
+     * @return void
+     */
+    public function addQueryProcessor($qpName) {
+        if ($this->searchParams->queryProcessorNames == null) {
+            $this->searchParams->queryProcessorNames = array();
+        }
+
+        $this->searchParams->queryProcessorNames[] = $qpName;
+    }
+
+    /**
+     * 添加要关闭的function。
+     *
+     * @param String $disabledFunction 指定的要关闭的方法名称。
+     * @return void
+     */
+    public function addDisableFunctions($disabledFunction) {
+        if ($this->searchParams->disableFunctions == null) {
+            $this->searchParams->disableFunctions = array();
+        }
+
+        $this->searchParams->disableFunctions[] = $disabledFunction;
+    }
+
+    /**
+     * 设置自定义参数。
+     *
+     * @param String $key 自定义参数的参数名。
+     * @param String $value 自定义参数的参数值。
+     * @return void
+     */
+    public function setCustomParam($key, $value) {
+        if ($this->searchParams->customParam == null) {
+            $this->searchParams->customParam = array();
+        }
+
+        $this->searchParams->customParam[$key] = $value;
+    }
+
+    /**
+     * 设置扫描数据的过期时间。
+     *
+     * @param String $expireTime 设定scroll的过期时间。
+     * @return void
+     */
+    public function setScrollExpire($expiredTime) {
+        if ($this->searchParams->deepPaging == null) {
+            $this->searchParams->deepPaging = new DeepPaging();
+        }
+
+        $this->searchParams->deepPaging->scrollExpire = $expiredTime;
+    }
+
+    /**
+     * 设置扫描数据的scrollId。
+     *
+     * ScrollId 为上一次扫描时返回的信息。
+     *
+     * @param String $scrollId 设定scroll的scrollId。
+     * @return void
+     */
+    public function setScrollId($scrollId) {
+        if ($this->searchParams->deepPaging == null) {
+            $this->searchParams->deepPaging = new DeepPaging();
+        }
+
+        $this->searchParams->deepPaging->scrollId = $scrollId;
+    }
+
+    /**
+     * 设置abtest数据的sceneTag。
+     *
+     * SceneTag 为场景标签。
+     *
+     * @param String $sceneTag 设定abtest的sceneTag。
+     * @return void
+     */
+    public function setSceneTag($sceneTag) {
+        if ($this->searchParams->abtest == null) {
+            $this->searchParams->abtest = new Abtest();
+        }
+
+        $this->searchParams->abtest->sceneTag = $sceneTag;
+    }
+
+    /**
+     * 设置abtest数据的flowDivider。
+     *
+     * FlowDivider 为流量分配标识。
+     *
+     * @param String $flowDivider 设定abtest的flowDivider。
+     * @return void
+     */
+    public function setFlowDivider($flowDivider) {
+        if ($this->searchParams->abtest == null) {
+            $this->searchParams->abtest = new Abtest();
+        }
+
+        $this->searchParams->abtest->flowDivider = $flowDivider;
+    }
+
+    /**
+     * 设置终端用户的id,用来统计uv信息。
+     *
+     * @param String $userId 设定终端用户的id。
+     * @return void
+     */
+    public function setUserId($userId) {
+        $this->searchParams->userId = $userId;
+    }
+
+    /**
+     * 设置终端用户输入的query。
+     *
+     * @param String $rawQuery 设定终端用户输入的query。
+     * @return void
+     */
+    public function setRawQuery($rawQuery) {
+        $this->searchParams->rawQuery = $rawQuery;
+    }
+
+    /**
+     * 获取SearchParams对象。
+     *
+     * @return SearchParams
+     */
+    public function build() {
+        return $this->searchParams;
+    }
+}
+
+

+ 61 - 0
php/OpenSearch/Util/SuggestParamsBuilder.php

@@ -0,0 +1,61 @@
+<?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.
+ */
+
+namespace OpenSearch\Util;
+
+use OpenSearch\Generated\Search\SearchParams;
+use OpenSearch\Generated\Search\Config;
+use OpenSearch\Generated\Search\Suggest;
+
+class SuggestParamsBuilder {
+
+    public function __construct() {}
+
+    /**
+     * 创建一个下拉提示的搜索请求。
+     *
+     * @param string $appName 指定应用的名称。
+     * @param string $suggestName 指定下拉提示的名称。
+     * @param string $query 指定要搜索的关键词。
+     * @param int $hits 指定要返回的词条个数。
+     *
+     * @return \OpenSearch\Generated\Search\SearchParams
+     */
+    public static function build($appName, $suggestName, $query, $hits) {
+        $config = new Config(array('hits' => (int) $hits, 'appNames' => array($appName)));
+        $suggest = new Suggest(array('suggestName' => $suggestName));
+
+        return new SearchParams(array("config" => $config, 'query' => $query, 'suggest' => $suggest));
+    }
+
+    /**
+     * 根据SearchParams生成下拉提示搜索的参数。
+     *
+     * @param \OpenSearch\Generated\Search\SearchParams $searchParams searchParams
+     *
+     * @return array
+     */
+    public static function getQueryParams($searchParams) {
+        $query = $searchParams->query;
+        $hits = $searchParams->config->hits;
+
+        return array('query' => $query, 'hit' => $hits);
+    }
+}

+ 183 - 0
php/OpenSearch/Util/UrlParamsBuilder.php

@@ -0,0 +1,183 @@
+<?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.
+ */
+
+namespace OpenSearch\Util;
+
+use OpenSearch\Generated\Search\Constant;
+use OpenSearch\Generated\Search\DeepPaging;
+use OpenSearch\Generated\Search\SearchType;
+
+class UrlParamsBuilder {
+
+    const QUERY = 'query';
+    const FORMAT = 'format';
+    const FIRST_RANK_NAME = 'first_rank_name';
+    const SECOND_RANK_NAME = 'second_rank_name';
+    const SUMMARY = 'summary';
+    const FETCH_FIELDS = 'fetch_fields';
+    const QP = 'qp';
+    const DISABLE = 'disable';
+    const ROUTE_VALUE = 'route_value';
+    const SCROLL_EXPIRE = 'scroll';
+    const SCROLL_ID = 'scroll_id';
+    const SEARCH_TYPE = 'search_type';
+
+    const FETCH_FIELDS_SEPARATOR = ';';
+    const QP_SEPARATOR = ',';
+    const DISABLE_FUNCTIONS_SEPARATOR = ';';
+
+    const SUMMARY_SEPARATOR = ';';
+    const SUMMARY_SUB_SEPARATOR = ',';
+    const SUMMARY_KV_SEPARATOR = ':';
+
+    const SEARCH_TYPE_SCAN = 'scan';
+
+    const ABTEST = "abtest";
+
+    private static $summaryKeys = array(
+        'summary_field' => 'SUMMARY_PARAM_SUMMARY_FIELD',
+        'summary_len' => 'SUMMARY_PARAM_SUMMARY_LEN',
+        'summary_ellipsis' => 'SUMMARY_PARAM_SUMMARY_ELLIPSIS',
+        'summary_snippet' => 'SUMMARY_PARAM_SUMMARY_SNIPPET',
+        'summary_element' => 'SUMMARY_PARAM_SUMMARY_ELEMENT',
+        'summary_element_prefix' => 'SUMMARY_PARAM_SUMMARY_ELEMENT_PREFIX',
+        'summary_element_postfix' => 'SUMMARY_PARAM_SUMMARY_ELEMENT_POSTFIX'
+    );
+
+    private $params = array();
+
+    public function __construct($searchParams) {
+        $this->init($searchParams);
+    }
+
+    public function init($searchParams) {
+        $this->initQuery($searchParams);
+        $this->initScroll($searchParams);
+        $this->initRank($searchParams);
+        $this->initFetchFields($searchParams);
+        $this->initSummary($searchParams);
+        $this->initQueryProcessor($searchParams);
+        $this->initDisableFunctions($searchParams);
+        $this->initRouteValue($searchParams);
+        $this->initCustomParams($searchParams);
+        $this->initAbtest($searchParams);
+        $this->initUserId($searchParams);
+        $this->initRawQuery($searchParams);
+    }
+
+    public function initScroll($searchParams) {
+        if (isset($searchParams->deepPaging) && $searchParams->deepPaging instanceof DeepPaging) {
+            if ($searchParams->deepPaging->scrollId) {
+                $this->params[self::SCROLL_ID] = $searchParams->deepPaging->scrollId;
+            } else {
+                $this->params[self::SEARCH_TYPE] = self::SEARCH_TYPE_SCAN;
+            }
+            $this->params[self::SCROLL_EXPIRE] = $searchParams->deepPaging->scrollExpire;
+        }
+    }
+
+    public function initQuery($searchParams) {
+        $builder = new ClauseParamsBuilder($searchParams);
+        $this->params[self::QUERY] = $builder->getClausesString();
+    }
+
+    public function initRank($searchParams) {
+        if (isset($searchParams->rank->firstRankName)) {
+            $this->params[self::FIRST_RANK_NAME] = $searchParams->rank->firstRankName;
+        }
+
+        if (isset($searchParams->rank->secondRankName)) {
+            $this->params[self::SECOND_RANK_NAME] = $searchParams->rank->secondRankName;
+        }
+    }
+
+    public function initFetchFields($searchParams) {
+        if (isset($searchParams->config->fetchFields)) {
+            $this->params[self::FETCH_FIELDS] = implode(self::FETCH_FIELDS_SEPARATOR, $searchParams->config->fetchFields);
+        }
+    }
+
+    public function initSummary($searchParams) {
+        if (isset($searchParams->summaries)) {
+            $summaries = array();
+            foreach ($searchParams->summaries as $summary) {
+                if (!isset($summary->summary_field)) {
+                    continue;
+                }
+
+                $sum = array();
+                foreach (self::$summaryKeys as $k => $v) {
+                    if (isset($summary->$k)) {
+                        $sum[] = Constant::get($v) . self::SUMMARY_KV_SEPARATOR . $summary->$k;
+                    }
+                }
+
+                $summaries[] = implode(self::SUMMARY_SUB_SEPARATOR, $sum);
+            }
+            $this->params[self::SUMMARY] = implode(self::SUMMARY_SEPARATOR, $summaries);
+        }
+    }
+
+    public function initQueryProcessor($searchParams) {
+        if (isset($searchParams->queryProcessorNames)) {
+            $this->params[self::QP] = implode(self::QP_SEPARATOR, $searchParams->queryProcessorNames);
+        }
+    }
+
+    public function initDisableFunctions($searchParams) {
+        if (isset($searchParams->disableFunctions)) {
+            $this->params[self::DISABLE] = implode(self::DISABLE_FUNCTIONS_SEPARATOR, $searchParams->disableFunctions);
+        }
+    }
+
+    public function initRouteValue($searchParams) {
+        if (isset($searchParams->config->routeValue)) {
+            $this->params[self::ROUTE_VALUE] = $searchParams->config->routeValue;
+        }
+    }
+
+    public function initCustomParams($searchParams) {
+        if (isset($searchParams->customParam)) {
+            $this->params = array_merge($this->params, $searchParams->customParam);
+        }
+    }
+
+    public function initAbtest($searchParams) {
+        if (isset($searchParams->abtest) && isset($searchParams->abtest->sceneTag) && isset($searchParams->abtest->flowDivider)) {
+            $this->params[self::ABTEST] = sprintf("%s=%s,%s=%s", Constant::get('ABTEST_PARAM_SCENE_TAG'), $searchParams->abtest->sceneTag, Constant::get('ABTEST_PARAM_FLOW_DIVIDER'), $searchParams->abtest->flowDivider);
+        }
+    }
+
+    public function initUserId($searchParams) {
+        if (isset($searchParams->userId)) {
+            $this->params[Constant::get('USER_ID')] = $searchParams->userId;
+        }
+    }
+
+    public function initRawQuery($searchParams) {
+        if (isset($searchParams->rawQuery)) {
+            $this->params[Constant::get('RAW_QUERY')] = $searchParams->rawQuery;
+        }
+    }
+
+    public function getHttpParams() {
+        return $this->params;
+    }
+}

+ 14 - 0
php/demo/Config.inc.php

@@ -0,0 +1,14 @@
+<?php
+
+require_once("../OpenSearch/Autoloader/Autoloader.php");
+
+use OpenSearch\Client\OpenSearchClient;
+
+$accessKeyId = '<Your accessKeyId>';
+$secret = '<Your secret>';
+$endPoint = '<region endPoint>';
+$appName = '<app name>';
+$suggestName = '<suggest name>';
+$options = array('debug' => true);
+
+$client = new OpenSearchClient($accessKeyId, $secret, $endPoint, $options);

+ 11 - 0
php/demo/demo_app.php

@@ -0,0 +1,11 @@
+<?php
+require_once("Config.inc.php");
+
+use OpenSearch\Client\AppClient;
+use OpenSearch\Generated\Common\Pageable;
+
+$pageable = new Pageable(array('page' => 1, 'size' => 1));
+$appClient = new AppClient($client);
+$ret = $appClient->listAll($pageable);
+print_r($ret);
+//echo $ret->traceInfo->tracer;

Some files were not shown because too many files changed in this diff