From c6bb6ffad240f9012ad823498d3a1352a9e6eb52 Mon Sep 17 00:00:00 2001 From: WeijieSun Date: Sat, 10 Mar 2018 11:32:47 +0800 Subject: [PATCH] add java client source code Summary: Ref T9266 Test Plan: N/A Reviewers: qinzuoyan, cailiuyang, heyuchen, wutao1, laiyingchun Reviewed By: qinzuoyan Subscribers: #pegasus Maniphest Tasks: T9266 Differential Revision: https://phabricator.d.xiaomi.net/D86668 --- .arcconfig | 4 + .gitignore | 10 + LICENSE | 202 + README.md | 113 +- carrot | 313 + configuration/log4j.properties | 23 + configuration/pegasus.properties | 6 + idl/apache-licence-template | 3 + idl/base.thrift | 23 + idl/recompile_thrift.sh | 30 + idl/replication.thrift | 30 + idl/rrdb.thrift | 159 + pom.xml | 152 + scripts/PegasusCli | 4 + src/assembly/dep.xml | 38 + .../infra/pegasus/apps/count_response.java | 763 ++ .../infra/pegasus/apps/filter_type.java | 50 + .../pegasus/apps/get_scanner_request.java | 1335 +++ .../xiaomi/infra/pegasus/apps/key_value.java | 489 + .../com/xiaomi/infra/pegasus/apps/meta.java | 977 ++ .../infra/pegasus/apps/multi_get_request.java | 1469 +++ .../pegasus/apps/multi_get_response.java | 825 ++ .../infra/pegasus/apps/multi_put_request.java | 638 ++ .../pegasus/apps/multi_remove_request.java | 638 ++ .../pegasus/apps/multi_remove_response.java | 859 ++ .../infra/pegasus/apps/read_response.java | 776 ++ .../com/xiaomi/infra/pegasus/apps/rrdb.java | 9372 +++++++++++++++++ .../infra/pegasus/apps/scan_request.java | 371 + .../infra/pegasus/apps/scan_response.java | 921 ++ .../infra/pegasus/apps/ttl_response.java | 763 ++ .../infra/pegasus/apps/update_request.java | 589 ++ .../infra/pegasus/apps/update_response.java | 763 ++ .../com/xiaomi/infra/pegasus/base/blob.java | 203 + .../xiaomi/infra/pegasus/base/error_code.java | 286 + .../com/xiaomi/infra/pegasus/base/gpid.java | 229 + .../infra/pegasus/base/rpc_address.java | 244 + .../xiaomi/infra/pegasus/base/task_code.java | 196 + .../infra/pegasus/client/FilterType.java | 26 + .../infra/pegasus/client/HashKeyData.java | 36 + .../infra/pegasus/client/MultiGetOptions.java | 26 + .../infra/pegasus/client/PConfigUtil.java | 114 + .../infra/pegasus/client/PException.java | 29 + .../infra/pegasus/client/PegasusCli.java | 252 + .../infra/pegasus/client/PegasusClient.java | 414 + .../pegasus/client/PegasusClientFactory.java | 70 + .../client/PegasusClientInterface.java | 425 + .../infra/pegasus/client/PegasusScanner.java | 272 + .../client/PegasusScannerInterface.java | 36 + .../infra/pegasus/client/PegasusTable.java | 1166 ++ .../pegasus/client/PegasusTableInterface.java | 801 ++ .../infra/pegasus/client/ScanOptions.java | 37 + .../xiaomi/infra/pegasus/client/SetItem.java | 32 + .../infra/pegasus/metrics/MetricsManager.java | 63 + .../infra/pegasus/metrics/MetricsPool.java | 134 + .../pegasus/metrics/MetricsReporter.java | 178 + .../pegasus/operator/client_operator.java | 73 + .../pegasus/operator/query_cfg_operator.java | 44 + .../operator/rrdb_clear_scanner_operator.java | 35 + .../pegasus/operator/rrdb_get_operator.java | 43 + .../operator/rrdb_get_scanner_operator.java | 43 + .../operator/rrdb_multi_get_operator.java | 43 + .../operator/rrdb_multi_put_operator.java | 43 + .../operator/rrdb_multi_remove_operator.java | 45 + .../pegasus/operator/rrdb_put_operator.java | 43 + .../operator/rrdb_remove_operator.java | 43 + .../pegasus/operator/rrdb_scan_operator.java | 45 + .../operator/rrdb_sortkey_count_operator.java | 45 + .../pegasus/operator/rrdb_ttl_operator.java | 40 + .../replication/partition_configuration.java | 1097 ++ .../replication/query_cfg_request.java | 528 + .../replication/query_cfg_response.java | 830 ++ .../com/xiaomi/infra/pegasus/rpc/Cluster.java | 65 + .../xiaomi/infra/pegasus/rpc/KeyHasher.java | 20 + .../pegasus/rpc/ReplicationException.java | 35 + .../com/xiaomi/infra/pegasus/rpc/Table.java | 63 + .../infra/pegasus/rpc/ThriftHeader.java | 37 + .../pegasus/rpc/async/ClientRequestRound.java | 63 + .../pegasus/rpc/async/ClusterManager.java | 143 + .../infra/pegasus/rpc/async/MetaSession.java | 177 + .../pegasus/rpc/async/ReplicaSession.java | 282 + .../pegasus/rpc/async/TByteBufTransport.java | 50 + .../infra/pegasus/rpc/async/TableHandler.java | 371 + .../pegasus/rpc/async/ThriftFrameDecoder.java | 74 + .../pegasus/rpc/async/ThriftFrameEncoder.java | 42 + .../pegasus/thrift/AsyncProcessFunction.java | 56 + .../infra/pegasus/thrift/EncodingUtils.java | 148 + .../xiaomi/infra/pegasus/thrift/Option.java | 121 + .../infra/pegasus/thrift/ProcessFunction.java | 87 + .../infra/pegasus/thrift/ShortStack.java | 82 + .../pegasus/thrift/TApplicationException.java | 150 + .../infra/pegasus/thrift/TAsyncProcessor.java | 35 + .../xiaomi/infra/pegasus/thrift/TBase.java | 67 + .../pegasus/thrift/TBaseAsyncProcessor.java | 105 + .../infra/pegasus/thrift/TBaseHelper.java | 337 + .../infra/pegasus/thrift/TBaseProcessor.java | 42 + .../thrift/TByteArrayOutputStream.java | 56 + .../infra/pegasus/thrift/TDeserializer.java | 358 + .../xiaomi/infra/pegasus/thrift/TEnum.java | 24 + .../infra/pegasus/thrift/TEnumHelper.java | 57 + .../infra/pegasus/thrift/TException.java | 45 + .../infra/pegasus/thrift/TFieldIdEnum.java | 34 + .../pegasus/thrift/TFieldRequirementType.java | 30 + .../pegasus/thrift/TMultiplexedProcessor.java | 154 + .../thrift/TNonblockingMultiFetchClient.java | 399 + .../thrift/TNonblockingMultiFetchStats.java | 80 + .../infra/pegasus/thrift/TProcessor.java | 32 + .../pegasus/thrift/TProcessorFactory.java | 43 + .../infra/pegasus/thrift/TSerializable.java | 44 + .../infra/pegasus/thrift/TSerializer.java | 110 + .../infra/pegasus/thrift/TServiceClient.java | 91 + .../pegasus/thrift/TServiceClientFactory.java | 45 + .../xiaomi/infra/pegasus/thrift/TUnion.java | 279 + .../thrift/async/AsyncMethodCallback.java | 51 + .../pegasus/thrift/async/TAsyncClient.java | 102 + .../thrift/async/TAsyncClientFactory.java | 25 + .../thrift/async/TAsyncClientManager.java | 201 + .../thrift/async/TAsyncMethodCall.java | 284 + .../thrift/meta_data/EnumMetaData.java | 31 + .../thrift/meta_data/FieldMetaData.java | 70 + .../thrift/meta_data/FieldValueMetaData.java | 72 + .../thrift/meta_data/ListMetaData.java | 29 + .../pegasus/thrift/meta_data/MapMetaData.java | 31 + .../pegasus/thrift/meta_data/SetMetaData.java | 29 + .../thrift/meta_data/StructMetaData.java | 31 + .../pegasus/thrift/protocol/TBase64Utils.java | 127 + .../thrift/protocol/TBinaryProtocol.java | 427 + .../thrift/protocol/TCompactProtocol.java | 908 ++ .../infra/pegasus/thrift/protocol/TField.java | 66 + .../thrift/protocol/TJSONProtocol.java | 1007 ++ .../infra/pegasus/thrift/protocol/TList.java | 38 + .../infra/pegasus/thrift/protocol/TMap.java | 40 + .../pegasus/thrift/protocol/TMessage.java | 76 + .../pegasus/thrift/protocol/TMessageType.java | 31 + .../thrift/protocol/TMultiplexedProtocol.java | 93 + .../pegasus/thrift/protocol/TProtocol.java | 162 + .../thrift/protocol/TProtocolDecorator.java | 213 + .../thrift/protocol/TProtocolException.java | 82 + .../thrift/protocol/TProtocolFactory.java | 31 + .../thrift/protocol/TProtocolUtil.java | 221 + .../infra/pegasus/thrift/protocol/TSet.java | 42 + .../thrift/protocol/TSimpleJSONProtocol.java | 448 + .../pegasus/thrift/protocol/TStruct.java | 36 + .../thrift/protocol/TTupleProtocol.java | 98 + .../infra/pegasus/thrift/protocol/TType.java | 40 + .../infra/pegasus/thrift/scheme/IScheme.java | 29 + .../pegasus/thrift/scheme/SchemeFactory.java | 25 + .../pegasus/thrift/scheme/StandardScheme.java | 25 + .../pegasus/thrift/scheme/TupleScheme.java | 25 + .../server/AbstractNonblockingServer.java | 612 ++ .../pegasus/thrift/server/Invocation.java | 20 + .../pegasus/thrift/server/ServerContext.java | 26 + .../thrift/server/TExtensibleServlet.java | 171 + .../pegasus/thrift/server/THsHaServer.java | 204 + .../thrift/server/TNonblockingServer.java | 248 + .../infra/pegasus/thrift/server/TServer.java | 177 + .../thrift/server/TServerEventHandler.java | 59 + .../infra/pegasus/thrift/server/TServlet.java | 119 + .../pegasus/thrift/server/TSimpleServer.java | 117 + .../thrift/server/TThreadPoolServer.java | 319 + .../server/TThreadedSelectorServer.java | 744 ++ .../thrift/transport/AutoExpandingBuffer.java | 52 + .../AutoExpandingBufferReadTransport.java | 84 + .../AutoExpandingBufferWriteTransport.java | 66 + .../pegasus/thrift/transport/TByteBuffer.java | 87 + .../transport/TFastFramedTransport.java | 197 + .../thrift/transport/TFileProcessor.java | 118 + .../thrift/transport/TFileTransport.java | 621 ++ .../thrift/transport/TFramedTransport.java | 181 + .../pegasus/thrift/transport/THttpClient.java | 362 + .../thrift/transport/TIOStreamTransport.java | 164 + .../thrift/transport/TMemoryBuffer.java | 102 + .../transport/TMemoryInputTransport.java | 96 + .../transport/TNonblockingServerSocket.java | 163 + .../TNonblockingServerTransport.java | 31 + .../thrift/transport/TNonblockingSocket.java | 210 + .../transport/TNonblockingTransport.java | 47 + .../transport/TSSLTransportFactory.java | 385 + .../transport/TSaslClientTransport.java | 113 + .../transport/TSaslServerTransport.java | 236 + .../thrift/transport/TSaslTransport.java | 578 + .../transport/TSaslTransportException.java | 43 + .../thrift/transport/TSeekableFile.java | 33 + .../thrift/transport/TServerSocket.java | 158 + .../thrift/transport/TServerTransport.java | 80 + .../transport/TSimpleFileTransport.java | 216 + .../pegasus/thrift/transport/TSocket.java | 248 + .../thrift/transport/TStandardFile.java | 60 + .../pegasus/thrift/transport/TTransport.java | 163 + .../thrift/transport/TTransportException.java | 81 + .../thrift/transport/TTransportFactory.java | 41 + .../thrift/transport/TZlibTransport.java | 148 + .../infra/pegasus/tools/FlowController.java | 91 + .../com/xiaomi/infra/pegasus/tools/tools.java | 169 + .../infra/pegasus/client/TestBasic.java | 1326 +++ .../infra/pegasus/client/TestBench.java | 123 + .../infra/pegasus/client/TestMultiThread.java | 172 + .../infra/pegasus/client/TestNoOperate.java | 35 + .../xiaomi/infra/pegasus/client/TestPing.java | 115 + .../infra/pegasus/client/TestPingZK.java | 76 + .../xiaomi/infra/pegasus/client/TestScan.java | 425 + .../infra/pegasus/client/TestTimeout.java | 41 + .../pegasus/metrics/MetricsPoolTest.java | 143 + .../pegasus/rpc/async/ClusterManagerTest.java | 89 + .../pegasus/rpc/async/MetaSessionTest.java | 98 + .../pegasus/rpc/async/ReplicaSessionTest.java | 149 + .../pegasus/rpc/async/TableHandlerTest.java | 190 + .../pegasus/rpc/async/TimeoutBenchmark.java | 85 + .../xiaomi/infra/pegasus/tools/Toollet.java | 172 + 208 files changed, 52274 insertions(+), 1 deletion(-) create mode 100644 .arcconfig create mode 100644 .gitignore create mode 100644 LICENSE create mode 100755 carrot create mode 100644 configuration/log4j.properties create mode 100644 configuration/pegasus.properties create mode 100644 idl/apache-licence-template create mode 100644 idl/base.thrift create mode 100755 idl/recompile_thrift.sh create mode 100644 idl/replication.thrift create mode 100644 idl/rrdb.thrift create mode 100755 pom.xml create mode 100755 scripts/PegasusCli create mode 100644 src/assembly/dep.xml create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/count_response.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/filter_type.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/get_scanner_request.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/key_value.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/meta.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/multi_get_request.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/multi_get_response.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/multi_put_request.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/multi_remove_request.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/multi_remove_response.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/read_response.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/rrdb.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/scan_request.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/scan_response.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/ttl_response.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/update_request.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/apps/update_response.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/base/blob.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/base/error_code.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/base/gpid.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/base/rpc_address.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/base/task_code.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/FilterType.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/HashKeyData.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/MultiGetOptions.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/PConfigUtil.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/PException.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/PegasusCli.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/PegasusClient.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/PegasusClientFactory.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/PegasusClientInterface.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/PegasusScanner.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/PegasusScannerInterface.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/PegasusTable.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/PegasusTableInterface.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/ScanOptions.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/client/SetItem.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsManager.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsPool.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsReporter.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/client_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/query_cfg_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_clear_scanner_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_get_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_get_scanner_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_get_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_put_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_remove_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_put_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_remove_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_scan_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_sortkey_count_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_ttl_operator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/replication/partition_configuration.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/replication/query_cfg_request.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/replication/query_cfg_response.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/Cluster.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/KeyHasher.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/ReplicationException.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/Table.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/ThriftHeader.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/async/ClientRequestRound.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/async/ClusterManager.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/async/MetaSession.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/async/ReplicaSession.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/async/TByteBufTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/async/TableHandler.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/async/ThriftFrameDecoder.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/rpc/async/ThriftFrameEncoder.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/AsyncProcessFunction.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/EncodingUtils.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/Option.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/ProcessFunction.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/ShortStack.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TApplicationException.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TAsyncProcessor.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TBase.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseAsyncProcessor.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseHelper.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseProcessor.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TByteArrayOutputStream.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TDeserializer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TEnum.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TEnumHelper.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TException.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TFieldIdEnum.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TFieldRequirementType.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TMultiplexedProcessor.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TNonblockingMultiFetchClient.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TNonblockingMultiFetchStats.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TProcessor.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TProcessorFactory.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TSerializable.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TSerializer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TServiceClient.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TServiceClientFactory.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/TUnion.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/async/AsyncMethodCallback.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClient.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClientFactory.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClientManager.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncMethodCall.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/EnumMetaData.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/FieldMetaData.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/FieldValueMetaData.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/ListMetaData.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/MapMetaData.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/SetMetaData.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/StructMetaData.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TBase64Utils.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TBinaryProtocol.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TCompactProtocol.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TField.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TJSONProtocol.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TList.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMap.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMessage.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMessageType.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMultiplexedProtocol.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocol.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolDecorator.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolException.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolFactory.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolUtil.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TSet.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TSimpleJSONProtocol.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TStruct.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TTupleProtocol.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TType.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/IScheme.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/SchemeFactory.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/StandardScheme.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/TupleScheme.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/AbstractNonblockingServer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/Invocation.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/ServerContext.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/TExtensibleServlet.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/THsHaServer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/TNonblockingServer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServerEventHandler.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServlet.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/TSimpleServer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/TThreadPoolServer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/server/TThreadedSelectorServer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBuffer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBufferReadTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBufferWriteTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TByteBuffer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFastFramedTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFileProcessor.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFileTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFramedTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/THttpClient.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TIOStreamTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TMemoryBuffer.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TMemoryInputTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingServerSocket.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingServerTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingSocket.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSSLTransportFactory.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslClientTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslServerTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslTransportException.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSeekableFile.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TServerSocket.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TServerTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSimpleFileTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSocket.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TStandardFile.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransportException.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransportFactory.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TZlibTransport.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/tools/FlowController.java create mode 100644 src/main/java/com/xiaomi/infra/pegasus/tools/tools.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/client/TestBasic.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/client/TestBench.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/client/TestMultiThread.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/client/TestNoOperate.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/client/TestPing.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/client/TestPingZK.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/client/TestScan.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/client/TestTimeout.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/metrics/MetricsPoolTest.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/rpc/async/ClusterManagerTest.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/rpc/async/MetaSessionTest.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/rpc/async/ReplicaSessionTest.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/rpc/async/TableHandlerTest.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/rpc/async/TimeoutBenchmark.java create mode 100644 src/test/java/com/xiaomi/infra/pegasus/tools/Toollet.java diff --git a/.arcconfig b/.arcconfig new file mode 100644 index 00000000..52351a40 --- /dev/null +++ b/.arcconfig @@ -0,0 +1,4 @@ +{ + "project_id" : "Pegasus", + "conduit_uri" : "https://phabricator.d.xiaomi.net/" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2d28d1e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +bin/ +release/ +target/ +.settings +.project +.classpath +.idea +pegasus-client.iml +log.txt +rolling_log/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..6efe7f33 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/README.md b/README.md index 642ebe88..f836a3ba 100644 --- a/README.md +++ b/README.md @@ -1 +1,112 @@ -## Pegasus Java Client +# Pegasus Java Client + +## Build + +``` +mvn clean package -DskipTests +``` + +## Install + +``` +mvn clean install -DskipTests +``` + +## Test + +To run test, you should start pegasus onebox firstly, and run test as: + +``` +mvn clean package +``` + +or specify one test: + +``` +mvn clean package -Dtest=TestPing +``` + +## PegasusCli + +PegasusCli is a tool to set/get/del data from pegasus. + +This tool is also deployed to Nexus, from which you can download it. + +Or you can build it from source as following: + +``` +mvn clean package -DskipTests +cd target/ +tar xfz pegasus-client-${VERSION}-thrift-0.11.0-inlined-bin.tar.gz +cd pegasus-client-${VERSION}-thrift-0.11.0-inlined +./PegasusCli +``` + +## Configuration + +Configure client by "pegasus.properties", for example: + +``` +meta_servers = 127.0.0.1:34601,127.0.0.1:34602,127.0.0.1:34603 +operation_timeout = 1000 +async_workers = 4 +enable_perf_counter = true +perf_counter_tags = k1=v1,k2=v2,k3=v3 +push_counter_interval_secs = 10 +``` + +You can provide a parameter of 'configPath' when creating a client instance. + +The format of 'configPath' should be one of these: +* zk path: zk://host1:port1,host2:port2,host3:port3/path/to/config +* local file path: file:///path/to/config +* resource path: resource:///path/to/config + +## PerfCounter(Metrics) + +Pegasus Java Client supports QPS and latency statistics of requests. + +The related configurations are: + +``` +enable_perf_counter = true +perf_counter_tags = k1=v1,k2=v2,k3=v3 +push_counter_interval_secs = 10 +``` + +For each type of request(get, set, multiset, etc.), we collect 8 metrics: +1. cps-1sec: the request's qps +2. cps-1min: the request's queries per 1 minute +3. cps-5min: the request's queries per 5 minutes +4. cps-15min: the request's queries per 15 minutes +5. latency-p50: the moving median of request's queries +6. latency-p99: the moving p99 of request's queries +7. lantecy-p999: the moving p999 of request's queries +8: latency-max: the moving max of request's queries + +We use io.dropwizard.metrics library to calculate the request count. + +Currently, metrics are integrated with open-falcon(http://open-falcon.com/), +which push counters to local http agent http://127.0.0.1:1988/push/v1. + +If you'd like to integrate pegasus client with other monitor system, please let us know ASAP. + +## Document + +For Pegasus Java API document, please refer to: https://github.com/XiaoMi/pegasus/wiki/Java%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%96%87%E6%A1%A3 + +## About thrift + +In order to prevent the conflict of different thrift version, we copy the thrift source into our project. Currently we use +the version of 0.11.0. + +If you'd like to use another version of thrift, please copy whole directory +"${YOUR\_THRIFT\_SRC\_ROOT}/lib/java/src/org/apache/thrift" into "src/main/java/com/xiaomi/infra/pegasus", and modify the package name by + +` +find src/main/java/com/xiaomi/infra -name "*.java" | xargs sed -i -e 's/org.apache.thrift/com.xiaomi.infra.pegasus.thrift/g' +` + +After the modification, compilation of the project may fail due to missing of dependencies. +You should find related dependencies and modify the pom.xml + diff --git a/carrot b/carrot new file mode 100755 index 00000000..53438ee2 --- /dev/null +++ b/carrot @@ -0,0 +1,313 @@ +#!/bin/bash + +# Carrot: A Release veRsiOn Tool for java client +# By WeijieSun (sunweijie@xiaomi.com) + +staging_branch="thrift-0.11.0-inlined" +project_name="pegasus-java-client" +command_decorator="verify" + +function git_current_branch() +{ + echo `git branch | fgrep "*" | cut -d " " -f 2` +} + +function java_client_get_current_version() +{ + pomfile_version=`grep version pom.xml | grep $staging_branch | tr -d '[:space:]'` + prefix="" + postfix="" + pomfile_version=${pomfile_version#$prefix} + pomfile_version=${pomfile_version%$postfix} + version_id=`echo $pomfile_version | cut -d - -f 1 | sed -e 's/\./ /g'` + + versions=($version_id) + + case $1 in + major) + echo ${versions[0]}-$staging_branch + ;; + minor) + echo ${versions[0]}.${versions[1]}-$staging_branch + ;; + patch) + echo $version_id-$staging_branch + ;; + *) + echo "Invalid current version type" + exit -1 + ;; + esac +} + +function java_client_get_next_version() +{ + pomfile_version=`grep version pom.xml | grep $staging_branch | tr -d '[:space:]'` + prefix="" + postfix="" + pomfile_version=${pomfile_version#$prefix} + pomfile_version=${pomfile_version%$postfix} + + version_id=`echo $pomfile_version | cut -d - -f 1 | sed -e 's/\./ /g'` + + versions=($version_id) + case $1 in + major) + versions[0]=$[ ${versions[0]} + 1 ] + ;; + minor) + versions[1]=$[ ${versions[1]} + 1 ] + ;; + patch) + if [ ${versions[2]} == "SNAPSHOT" ]; then + versions[2]="0" + else + versions[2]=$[ ${versions[2]} + 1 ] + fi + ;; + *) + echo "Invalid next version type" + exit -1 + ;; + esac + + if [ ${versions[2]} == "SNAPSHOT" ]; then + echo ${versions[0]}.${versions[1]}.SNAPSHOT-$staging_branch + else + echo ${versions[0]}.${versions[1]}.${versions[2]}-$staging_branch + fi +} + +function get_branch_type() +{ + if [ $1 = $staging_branch ]; then + echo "staging" + else + echo "release" + fi +} + +function verify_command() +{ + answer="" + echo -n -e "\033[31mExecuting command: $@, y/N?\033[0m" + read answer + if [ -z $answer ] || [ $answer = "y" ]; then + eval "$@" + else + return -1 + fi + return $? +} + +function verbose_command() +{ + echo -e "\033[31mExec Command: $@ \033[0m" + eval "$@" + return $? +} + +function carrot_execute() +{ + case $command_decorator in + silence) + eval $1 + ;; + verbose) + verbose_command $1 + ;; + verify) + verify_command $1 + ;; + simulate) + echo -e "\033[32m$1\033[0m" + ;; + *) + echo "invalid command decorator" + exit -1 + ;; + esac + if [ $? -ne 0 ]; then + echo "error in execute command $1, simulate the remaining commands" + command_decorator="simulate" + fi +} + +# +# patch -b|--branch branch_name -p|--commit_point commit_point -s|--start_from_this -d|--decorate decorate_type +# +function usage_patch +{ + echo "carrot patch -- apply patch to specific branch, and release a new patch version" + echo " -h|--help, print this help" + echo " -b|--branch BRANCH_NAME, the target branch. For current branch if not set" + echo " -p|--commit_point GIT_COMMIT_ID, cherry-pick this to the target" + echo " -s|--start_from_this. If set, cherry-pick from [GIT_COMMIT_ID, HEAD] to the target" + echo " -d|--decorate TYPE. [silence|verbose|verify|simulate], default is verify" +} + +function make_patch +{ + branch_name="" + commit_point="" + recent_commit="" + starting_flag="false" + + while [[ $# > 0 ]]; do + key="$1" + case $key in + -h|--help) + usage_patch + exit 0 + ;; + -b|--branch) + branch_name=$2 + shift + ;; + -p|--commit_point) + commit_point=$2 + shift;; + -s|--start_from_this) + starting_flag="true" + ;; + -d|--decorate) + command_decorator=$2 + shift + ;; + *) + usage_patch + exit -1 + ;; + esac + shift + done + + old_branch=`git_current_branch` + old_branch_type=`get_branch_type $old_branch` + + # only in staging branch, we try to calcuate the -s flag, AND + # only in staging branch, we try to get the recent commit point in log + if [ $old_branch_type == "staging" ]; then + if [ ! -z $commit_point ]; then + if [ $starting_flag == "true" ]; then + recent_commit=`git log | sed -n "1p" | cut -d" " -f 2` + fi + else + commit_point=`git log | sed -n "1p" | cut -d" " -f 2` + fi + fi + + current_branch=$old_branch + # we don't apply the patch unless we are in a release tag + if [ ! -z $branch_name ]; then + carrot_execute "git checkout $branch_name" + current_branch=$branch_name + if [ ! -z $recent_commit ]; then + carrot_execute "git cherry-pick $commit_point^..$recent_commit" + elif [ -n $commit_point ]; then + carrot_execute "git cherry-pick $commit_point" + fi + elif [ $old_branch_type == "staging" ]; then + echo "Please checkout to a release branch, or give a release branch name by -b" + exit -1 + fi + + new_version=`java_client_get_next_version patch` + carrot_execute "mvn versions:set -DnewVersion=$new_version" + carrot_execute "mvn versions:commit" + carrot_execute "git commit -am \"Release $project_name $new_version\"" + carrot_execute "git tag -a $new_version-release -m \"Release $project_name $new_version\"" + carrot_execute "git push -u origin $current_branch" + carrot_execute "git push --tags" + + if [ $current_branch != $old_branch ]; then + carrot_execute "git checkout $old_branch" + fi +} + +# +# minor-release -d|--decorate decorate_type +# +function usage_release_minor +{ + echo "carrot minor-release" + echo " -h|--help, print this help " + echo " -d|--decorate TYPE. [silence|verbose|verify|simulate], default is verify" +} + +function release_minor +{ + while [[ $# > 0 ]]; do + key="$1" + case $key in + -h|--help) + usage_release_minor + exit 0 + ;; + -d|--decorate) + command_decorator=$2 + shift + ;; + esac + shift + done + + this_branch=`git_current_branch` + branch_type=`get_branch_type $this_branch` + + if [ $branch_type != "staging" ]; then + echo "when release minor, we need to be in staging branch, currently in a $branch_type branch $this_branch" + exit -1 + fi + + this_version=`java_client_get_current_version minor` + + # create new branch and push + carrot_execute "git checkout -b $this_version-release" + # from a.b.SNAPSHOT -> a.b.0 + new_version=`java_client_get_next_version patch` + # commit the release version + carrot_execute "mvn versions:set -DnewVersion=$new_version" + carrot_execute "mvn versions:commit" + carrot_execute "git commit -am \"Release $project_name $new_version\"" + carrot_execute "git push -u origin $this_version-release" + # then make tag + carrot_execute "git tag -a $new_version-release -m \"Release $project_name $new_version\"" + carrot_execute "git push --tags" + + # update the staging branch's version + carrot_execute "git checkout $this_branch" + # from a.b.SNAPSHOT -> a.b+1.SNAPSHOT + new_version=`java_client_get_next_version minor` + carrot_execute "mvn versions:set -DnewVersion=$new_version" + carrot_execute "mvn versions:commit" + carrot_execute "git commit -am \"Bump version to $new_version\"" + carrot_execute "git push -u origin $this_branch" +} + +function usage_carrot +{ + echo "carrot -- Carrot is A Release veRsiOn Tool" + echo " help print the help" + echo " patch Make patch" + echo " minor-release Release a minor version" +} + +action=$1 +case $action in + help) + usage_carrot ;; + patch) + shift + make_patch $* + ;; + minor-release) + shift + release_minor $* + ;; + *) + echo "ERROR: unknown command $cmd" + echo + usage_carrot + exit -1 +esac diff --git a/configuration/log4j.properties b/configuration/log4j.properties new file mode 100644 index 00000000..3edd2ba4 --- /dev/null +++ b/configuration/log4j.properties @@ -0,0 +1,23 @@ +log4j.rootLogger=DEBUG, rolling_file +log4j.logger.com.xiaomi.infra.pegasus = INFO + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n + +log4j.appender.file=org.apache.log4j.FileAppender +log4j.appender.file.File=log.txt +log4j.appender.file.ImmediateFlush=true +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n +log4j.appender.file.Append=true + +log4j.appender.rolling_file=org.apache.log4j.RollingFileAppender +log4j.appender.rolling_file.File=rolling_log/log.txt +log4j.appender.rolling_file.MaxFileSize=10MB +log4j.appender.rolling_file.MaxBackupIndex=10 +log4j.appender.rolling_file.ImmediateFlush=true +log4j.appender.rolling_file.layout=org.apache.log4j.PatternLayout +log4j.appender.rolling_file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n +log4j.appender.rolling_file.Append=true diff --git a/configuration/pegasus.properties b/configuration/pegasus.properties new file mode 100644 index 00000000..740bd353 --- /dev/null +++ b/configuration/pegasus.properties @@ -0,0 +1,6 @@ +meta_servers = 127.0.0.1:34601,127.0.0.1:34602,127.0.0.1:34603 +operation_timeout = 1000 +async_workers = 4 +enable_perf_counter = false +perf_counter_tags = cluster=onebox,app=unit_test +push_counter_interval_secs = 10 diff --git a/idl/apache-licence-template b/idl/apache-licence-template new file mode 100644 index 00000000..4c33088c --- /dev/null +++ b/idl/apache-licence-template @@ -0,0 +1,3 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. diff --git a/idl/base.thrift b/idl/base.thrift new file mode 100644 index 00000000..209b06d1 --- /dev/null +++ b/idl/base.thrift @@ -0,0 +1,23 @@ +namespace cpp dsn.base +namespace java com.xiaomi.infra.pegasus.base + +// place holder +struct blob +{ +} + +struct error_code +{ +} + +struct task_code +{ +} + +struct rpc_address +{ +} + +struct gpid +{ +} diff --git a/idl/recompile_thrift.sh b/idl/recompile_thrift.sh new file mode 100755 index 00000000..e457f997 --- /dev/null +++ b/idl/recompile_thrift.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# method to get thrift 0.11.0: +# 1. get the source code from http://mirrors.tuna.tsinghua.edu.cn/apache/thrift/0.11.0/thrift-0.11.0.tar.gz +# 2. tar xvf thrift-0.11.0.tar.gz & cd thrift-0.11.0 +# 3. ./configure --with-csharp=no --with-java=no --with-python=no --with-erlang=no --with-perl=no --with-php=no --with-ruby=no --with-haskell=no --with-php_extension=no --with-rs=no +# 4. make && sudo make install +# +# Note: by default the thrift will be installed in /usr/local. If you'd like to install it somewhere else, you'd better with --prefix=... in step 3 + +thrift=thrift + +TMP_DIR=./gen-java +rm -rf $TMP_DIR + +mkdir -p $TMP_DIR +$thrift --gen java rrdb.thrift +$thrift --gen java replication.thrift + +# as we pack the thrift source in our project, so we need to replace the package name +find $TMP_DIR -name "*.java" | xargs sed -i -e "s/org.apache.thrift/com.xiaomi.infra.pegasus.thrift/g" +for gen_file in `find $TMP_DIR -name "*.java"`; do + cat apache-licence-template $gen_file > $gen_file.tmp + mv $gen_file.tmp $gen_file +done + +cp -v -r $TMP_DIR/* ../src/main/java/ +rm -rf $TMP_DIR + +echo "done" diff --git a/idl/replication.thrift b/idl/replication.thrift new file mode 100644 index 00000000..dec354d4 --- /dev/null +++ b/idl/replication.thrift @@ -0,0 +1,30 @@ +include "base.thrift" + +namespace cpp dsn.replication +namespace java com.xiaomi.infra.pegasus.replication + +struct partition_configuration +{ + 1:base.gpid pid; + 2:i64 ballot; + 3:i32 max_replica_count; + 4:base.rpc_address primary; + 5:list secondaries; + 6:list last_drops; + 7:i64 last_committed_decree; +} + +struct query_cfg_request +{ + 1:string app_name; + 2:list partition_indices; +} + +struct query_cfg_response +{ + 1:base.error_code err; + 2:i32 app_id; + 3:i32 partition_count; + 4:bool is_stateful; + 5:list partitions; +} diff --git a/idl/rrdb.thrift b/idl/rrdb.thrift new file mode 100644 index 00000000..41884b66 --- /dev/null +++ b/idl/rrdb.thrift @@ -0,0 +1,159 @@ +include "base.thrift" +include "replication.thrift" + +namespace cpp dsn.apps +namespace java com.xiaomi.infra.pegasus.apps + +enum filter_type +{ + FT_NO_FILTER, + FT_MATCH_ANYWHERE, + FT_MATCH_PREFIX, + FT_MATCH_POSTFIX +} + +struct update_request +{ + 1:base.blob key; + 2:base.blob value; + 3:i32 expire_ts_seconds; +} + +struct update_response +{ + 1:i32 error; + 2:i32 app_id; + 3:i32 partition_index; + 4:i64 decree; + 5:string server; +} + +struct read_response +{ + 1:i32 error; + 2:base.blob value; + 3:i32 app_id; + 4:i32 partition_index; + 6:string server; +} + +struct ttl_response +{ + 1:i32 error; + 2:i32 ttl_seconds; + 3:i32 app_id; + 4:i32 partition_index; + 6:string server; +} + +struct count_response +{ + 1:i32 error; + 2:i64 count; + 3:i32 app_id; + 4:i32 partition_index; + 6:string server; +} + +struct key_value +{ + 1:base.blob key; + 2:base.blob value; +} + +struct multi_put_request +{ + 1:base.blob hash_key; + 2:list kvs; // sort_key => value + 3:i32 expire_ts_seconds; +} + +struct multi_remove_request +{ + 1:base.blob hash_key; + 2:list sork_keys; // empty means remove all sortkeys + 3:i64 max_count; // deprecated +} + +struct multi_remove_response +{ + 1:i32 error; + 2:i64 count; // deleted count + 3:i32 app_id; + 4:i32 partition_index; + 5:i64 decree; + 6:string server; +} + +struct multi_get_request +{ + 1:base.blob hash_key; + 2:list sork_keys; // not empty means only fetch specified sortkeys + 3:i32 max_kv_count; // <= 0 means no limit + 4:i32 max_kv_size; // <= 0 means no limit + 5:bool no_value; // not return value, only return sortkeys + 6:base.blob start_sortkey; + 7:base.blob stop_sortkey; // empty means fetch to the last sort key + 8:bool start_inclusive; + 9:bool stop_inclusive; + 10:filter_type sort_key_filter_type; + 11:base.blob sort_key_filter_pattern; +} + +struct multi_get_response +{ + 1:i32 error; + 2:list kvs; // sort_key => value + 3:i32 app_id; + 4:i32 partition_index; + 6:string server; +} + +struct get_scanner_request +{ + 1:base.blob start_key; + 2:base.blob stop_key; + 3:bool start_inclusive; + 4:bool stop_inclusive; + 5:i32 batch_size; + 6:bool no_value; // not return value, only return sortkeys + 7:filter_type hash_key_filter_type; + 8:base.blob hash_key_filter_pattern; + 9:filter_type sort_key_filter_type; + 10:base.blob sort_key_filter_pattern; +} + +struct scan_request +{ + 1:i64 context_id; +} + +struct scan_response +{ + 1:i32 error; + 2:list kvs; + 3:i64 context_id; + 4:i32 app_id; + 5:i32 partition_index; + 6:string server; +} + +service rrdb +{ + update_response put(1:update_request update); + update_response multi_put(1:multi_put_request request); + update_response remove(1:base.blob key); + multi_remove_response multi_remove(1:multi_remove_request request); + read_response get(1:base.blob key); + multi_get_response multi_get(1:multi_get_request request); + count_response sortkey_count(1:base.blob hash_key); + ttl_response ttl(1:base.blob key); + scan_response get_scanner(1:get_scanner_request request); + scan_response scan(1:scan_request request); + oneway void clear_scanner(1:i64 context_id); +} + +service meta +{ + replication.query_cfg_response query_cfg(1:replication.query_cfg_request query); +} diff --git a/pom.xml b/pom.xml new file mode 100755 index 00000000..63f1cb90 --- /dev/null +++ b/pom.xml @@ -0,0 +1,152 @@ + + 4.0.0 + com.xiaomi.infra + pegasus-client + jar + 1.8.SNAPSHOT-thrift-0.11.0-inlined + Pegasus Java Client + + + junit + junit + 4.8.1 + test + + + javax.servlet + javax.servlet-api + 4.0.0 + provided + + + org.apache.httpcomponents + httpclient + 4.5.5 + + + io.dropwizard.metrics + metrics-core + 3.1.2 + + + org.slf4j + slf4j-api + 1.7.2 + + + org.slf4j + slf4j-log4j12 + 1.7.2 + + + org.apache.commons + commons-lang3 + 3.1 + + + com.101tec + zkclient + 0.2 + + + io.netty + netty-all + 4.0.33.Final + + + org.json + json + 20160810 + + + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + + + + + ${project.basedir}/src/main/java + ${project.basedir}/src/test/java + ${project.basedir}/target + ${project.basedir}/target/classes + ${project.basedir}/target/test-classes + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.6 + 1.6 + true + true + UTF-8 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + ${skipTests} + + ${project.basedir}/configuration + + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.10 + + + copy-dependencies + package + + copy-dependencies + + + ${project.build.directory}/library + gossip + + + + + + maven-assembly-plugin + 2.5.3 + + src/assembly/dep.xml + + + + create-archive + package + + single + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + + diff --git a/scripts/PegasusCli b/scripts/PegasusCli new file mode 100755 index 00000000..70399a85 --- /dev/null +++ b/scripts/PegasusCli @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +java -classpath ./*:library/* -Dlog4j.configuration="file:log4j.properties" com.xiaomi.infra.pegasus.client.PegasusCli "$@" + diff --git a/src/assembly/dep.xml b/src/assembly/dep.xml new file mode 100644 index 00000000..1ca47ff4 --- /dev/null +++ b/src/assembly/dep.xml @@ -0,0 +1,38 @@ + + bin + + tar.gz + + + + ${project.basedir}/configuration + / + + * + + + + ${project.basedir}/scripts + / + + * + + + + ${project.build.directory} + / + + *.jar + + + + ${project.build.directory}/library + /library + + *.jar + + + + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/count_response.java b/src/main/java/com/xiaomi/infra/pegasus/apps/count_response.java new file mode 100644 index 00000000..6eecdfb8 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/count_response.java @@ -0,0 +1,763 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class count_response implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("count_response"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField ERROR_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("error", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField COUNT_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("count", com.xiaomi.infra.pegasus.thrift.protocol.TType.I64, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField APP_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("app_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PARTITION_INDEX_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("partition_index", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SERVER_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("server", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING, (short)6); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new count_responseStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new count_responseTupleSchemeFactory(); + + public int error; // required + public long count; // required + public int app_id; // required + public int partition_index; // required + public java.lang.String server; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + ERROR((short)1, "error"), + COUNT((short)2, "count"), + APP_ID((short)3, "app_id"), + PARTITION_INDEX((short)4, "partition_index"), + SERVER((short)6, "server"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // ERROR + return ERROR; + case 2: // COUNT + return COUNT; + case 3: // APP_ID + return APP_ID; + case 4: // PARTITION_INDEX + return PARTITION_INDEX; + case 6: // SERVER + return SERVER; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __ERROR_ISSET_ID = 0; + private static final int __COUNT_ISSET_ID = 1; + private static final int __APP_ID_ISSET_ID = 2; + private static final int __PARTITION_INDEX_ISSET_ID = 3; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.ERROR, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("error", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.COUNT, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("count", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I64))); + tmpMap.put(_Fields.APP_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("app_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.PARTITION_INDEX, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("partition_index", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.SERVER, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("server", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(count_response.class, metaDataMap); + } + + public count_response() { + } + + public count_response( + int error, + long count, + int app_id, + int partition_index, + java.lang.String server) + { + this(); + this.error = error; + setErrorIsSet(true); + this.count = count; + setCountIsSet(true); + this.app_id = app_id; + setApp_idIsSet(true); + this.partition_index = partition_index; + setPartition_indexIsSet(true); + this.server = server; + } + + /** + * Performs a deep copy on other. + */ + public count_response(count_response other) { + __isset_bitfield = other.__isset_bitfield; + this.error = other.error; + this.count = other.count; + this.app_id = other.app_id; + this.partition_index = other.partition_index; + if (other.isSetServer()) { + this.server = other.server; + } + } + + public count_response deepCopy() { + return new count_response(this); + } + + @Override + public void clear() { + setErrorIsSet(false); + this.error = 0; + setCountIsSet(false); + this.count = 0; + setApp_idIsSet(false); + this.app_id = 0; + setPartition_indexIsSet(false); + this.partition_index = 0; + this.server = null; + } + + public int getError() { + return this.error; + } + + public count_response setError(int error) { + this.error = error; + setErrorIsSet(true); + return this; + } + + public void unsetError() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + /** Returns true if field error is set (has been assigned a value) and false otherwise */ + public boolean isSetError() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + public void setErrorIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __ERROR_ISSET_ID, value); + } + + public long getCount() { + return this.count; + } + + public count_response setCount(long count) { + this.count = count; + setCountIsSet(true); + return this; + } + + public void unsetCount() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __COUNT_ISSET_ID); + } + + /** Returns true if field count is set (has been assigned a value) and false otherwise */ + public boolean isSetCount() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __COUNT_ISSET_ID); + } + + public void setCountIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __COUNT_ISSET_ID, value); + } + + public int getApp_id() { + return this.app_id; + } + + public count_response setApp_id(int app_id) { + this.app_id = app_id; + setApp_idIsSet(true); + return this; + } + + public void unsetApp_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + /** Returns true if field app_id is set (has been assigned a value) and false otherwise */ + public boolean isSetApp_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + public void setApp_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __APP_ID_ISSET_ID, value); + } + + public int getPartition_index() { + return this.partition_index; + } + + public count_response setPartition_index(int partition_index) { + this.partition_index = partition_index; + setPartition_indexIsSet(true); + return this; + } + + public void unsetPartition_index() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + /** Returns true if field partition_index is set (has been assigned a value) and false otherwise */ + public boolean isSetPartition_index() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + public void setPartition_indexIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID, value); + } + + public java.lang.String getServer() { + return this.server; + } + + public count_response setServer(java.lang.String server) { + this.server = server; + return this; + } + + public void unsetServer() { + this.server = null; + } + + /** Returns true if field server is set (has been assigned a value) and false otherwise */ + public boolean isSetServer() { + return this.server != null; + } + + public void setServerIsSet(boolean value) { + if (!value) { + this.server = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case ERROR: + if (value == null) { + unsetError(); + } else { + setError((java.lang.Integer)value); + } + break; + + case COUNT: + if (value == null) { + unsetCount(); + } else { + setCount((java.lang.Long)value); + } + break; + + case APP_ID: + if (value == null) { + unsetApp_id(); + } else { + setApp_id((java.lang.Integer)value); + } + break; + + case PARTITION_INDEX: + if (value == null) { + unsetPartition_index(); + } else { + setPartition_index((java.lang.Integer)value); + } + break; + + case SERVER: + if (value == null) { + unsetServer(); + } else { + setServer((java.lang.String)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case ERROR: + return getError(); + + case COUNT: + return getCount(); + + case APP_ID: + return getApp_id(); + + case PARTITION_INDEX: + return getPartition_index(); + + case SERVER: + return getServer(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case ERROR: + return isSetError(); + case COUNT: + return isSetCount(); + case APP_ID: + return isSetApp_id(); + case PARTITION_INDEX: + return isSetPartition_index(); + case SERVER: + return isSetServer(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof count_response) + return this.equals((count_response)that); + return false; + } + + public boolean equals(count_response that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_error = true; + boolean that_present_error = true; + if (this_present_error || that_present_error) { + if (!(this_present_error && that_present_error)) + return false; + if (this.error != that.error) + return false; + } + + boolean this_present_count = true; + boolean that_present_count = true; + if (this_present_count || that_present_count) { + if (!(this_present_count && that_present_count)) + return false; + if (this.count != that.count) + return false; + } + + boolean this_present_app_id = true; + boolean that_present_app_id = true; + if (this_present_app_id || that_present_app_id) { + if (!(this_present_app_id && that_present_app_id)) + return false; + if (this.app_id != that.app_id) + return false; + } + + boolean this_present_partition_index = true; + boolean that_present_partition_index = true; + if (this_present_partition_index || that_present_partition_index) { + if (!(this_present_partition_index && that_present_partition_index)) + return false; + if (this.partition_index != that.partition_index) + return false; + } + + boolean this_present_server = true && this.isSetServer(); + boolean that_present_server = true && that.isSetServer(); + if (this_present_server || that_present_server) { + if (!(this_present_server && that_present_server)) + return false; + if (!this.server.equals(that.server)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + error; + + hashCode = hashCode * 8191 + com.xiaomi.infra.pegasus.thrift.TBaseHelper.hashCode(count); + + hashCode = hashCode * 8191 + app_id; + + hashCode = hashCode * 8191 + partition_index; + + hashCode = hashCode * 8191 + ((isSetServer()) ? 131071 : 524287); + if (isSetServer()) + hashCode = hashCode * 8191 + server.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(count_response other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetError()).compareTo(other.isSetError()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetError()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.error, other.error); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetCount()).compareTo(other.isSetCount()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetCount()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.count, other.count); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetApp_id()).compareTo(other.isSetApp_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetApp_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.app_id, other.app_id); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPartition_index()).compareTo(other.isSetPartition_index()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPartition_index()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.partition_index, other.partition_index); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetServer()).compareTo(other.isSetServer()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetServer()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.server, other.server); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("count_response("); + boolean first = true; + + sb.append("error:"); + sb.append(this.error); + first = false; + if (!first) sb.append(", "); + sb.append("count:"); + sb.append(this.count); + first = false; + if (!first) sb.append(", "); + sb.append("app_id:"); + sb.append(this.app_id); + first = false; + if (!first) sb.append(", "); + sb.append("partition_index:"); + sb.append(this.partition_index); + first = false; + if (!first) sb.append(", "); + sb.append("server:"); + if (this.server == null) { + sb.append("null"); + } else { + sb.append(this.server); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class count_responseStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public count_responseStandardScheme getScheme() { + return new count_responseStandardScheme(); + } + } + + private static class count_responseStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, count_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // ERROR + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // COUNT + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I64) { + struct.count = iprot.readI64(); + struct.setCountIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // APP_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // PARTITION_INDEX + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 6: // SERVER + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, count_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldBegin(ERROR_FIELD_DESC); + oprot.writeI32(struct.error); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(COUNT_FIELD_DESC); + oprot.writeI64(struct.count); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(APP_ID_FIELD_DESC); + oprot.writeI32(struct.app_id); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(PARTITION_INDEX_FIELD_DESC); + oprot.writeI32(struct.partition_index); + oprot.writeFieldEnd(); + if (struct.server != null) { + oprot.writeFieldBegin(SERVER_FIELD_DESC); + oprot.writeString(struct.server); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class count_responseTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public count_responseTupleScheme getScheme() { + return new count_responseTupleScheme(); + } + } + + private static class count_responseTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, count_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetError()) { + optionals.set(0); + } + if (struct.isSetCount()) { + optionals.set(1); + } + if (struct.isSetApp_id()) { + optionals.set(2); + } + if (struct.isSetPartition_index()) { + optionals.set(3); + } + if (struct.isSetServer()) { + optionals.set(4); + } + oprot.writeBitSet(optionals, 5); + if (struct.isSetError()) { + oprot.writeI32(struct.error); + } + if (struct.isSetCount()) { + oprot.writeI64(struct.count); + } + if (struct.isSetApp_id()) { + oprot.writeI32(struct.app_id); + } + if (struct.isSetPartition_index()) { + oprot.writeI32(struct.partition_index); + } + if (struct.isSetServer()) { + oprot.writeString(struct.server); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, count_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(5); + if (incoming.get(0)) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } + if (incoming.get(1)) { + struct.count = iprot.readI64(); + struct.setCountIsSet(true); + } + if (incoming.get(2)) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } + if (incoming.get(3)) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } + if (incoming.get(4)) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/filter_type.java b/src/main/java/com/xiaomi/infra/pegasus/apps/filter_type.java new file mode 100644 index 00000000..489ab57d --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/filter_type.java @@ -0,0 +1,50 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + + +public enum filter_type implements com.xiaomi.infra.pegasus.thrift.TEnum { + FT_NO_FILTER(0), + FT_MATCH_ANYWHERE(1), + FT_MATCH_PREFIX(2), + FT_MATCH_POSTFIX(3); + + private final int value; + + private filter_type(int value) { + this.value = value; + } + + /** + * Get the integer value of this enum value, as defined in the Thrift IDL. + */ + public int getValue() { + return value; + } + + /** + * Find a the enum type by its integer value, as defined in the Thrift IDL. + * @return null if the value is not found. + */ + public static filter_type findByValue(int value) { + switch (value) { + case 0: + return FT_NO_FILTER; + case 1: + return FT_MATCH_ANYWHERE; + case 2: + return FT_MATCH_PREFIX; + case 3: + return FT_MATCH_POSTFIX; + default: + return null; + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/get_scanner_request.java b/src/main/java/com/xiaomi/infra/pegasus/apps/get_scanner_request.java new file mode 100644 index 00000000..025ae737 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/get_scanner_request.java @@ -0,0 +1,1335 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class get_scanner_request implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("get_scanner_request"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField START_KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("start_key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField STOP_KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("stop_key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField START_INCLUSIVE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("start_inclusive", com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField STOP_INCLUSIVE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("stop_inclusive", com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField BATCH_SIZE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("batch_size", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)5); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField NO_VALUE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("no_value", com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL, (short)6); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField HASH_KEY_FILTER_TYPE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("hash_key_filter_type", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)7); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField HASH_KEY_FILTER_PATTERN_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("hash_key_filter_pattern", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)8); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SORT_KEY_FILTER_TYPE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("sort_key_filter_type", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)9); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SORT_KEY_FILTER_PATTERN_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("sort_key_filter_pattern", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)10); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new get_scanner_requestStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new get_scanner_requestTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.blob start_key; // required + public com.xiaomi.infra.pegasus.base.blob stop_key; // required + public boolean start_inclusive; // required + public boolean stop_inclusive; // required + public int batch_size; // required + public boolean no_value; // required + /** + * + * @see filter_type + */ + public filter_type hash_key_filter_type; // required + public com.xiaomi.infra.pegasus.base.blob hash_key_filter_pattern; // required + /** + * + * @see filter_type + */ + public filter_type sort_key_filter_type; // required + public com.xiaomi.infra.pegasus.base.blob sort_key_filter_pattern; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + START_KEY((short)1, "start_key"), + STOP_KEY((short)2, "stop_key"), + START_INCLUSIVE((short)3, "start_inclusive"), + STOP_INCLUSIVE((short)4, "stop_inclusive"), + BATCH_SIZE((short)5, "batch_size"), + NO_VALUE((short)6, "no_value"), + /** + * + * @see filter_type + */ + HASH_KEY_FILTER_TYPE((short)7, "hash_key_filter_type"), + HASH_KEY_FILTER_PATTERN((short)8, "hash_key_filter_pattern"), + /** + * + * @see filter_type + */ + SORT_KEY_FILTER_TYPE((short)9, "sort_key_filter_type"), + SORT_KEY_FILTER_PATTERN((short)10, "sort_key_filter_pattern"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // START_KEY + return START_KEY; + case 2: // STOP_KEY + return STOP_KEY; + case 3: // START_INCLUSIVE + return START_INCLUSIVE; + case 4: // STOP_INCLUSIVE + return STOP_INCLUSIVE; + case 5: // BATCH_SIZE + return BATCH_SIZE; + case 6: // NO_VALUE + return NO_VALUE; + case 7: // HASH_KEY_FILTER_TYPE + return HASH_KEY_FILTER_TYPE; + case 8: // HASH_KEY_FILTER_PATTERN + return HASH_KEY_FILTER_PATTERN; + case 9: // SORT_KEY_FILTER_TYPE + return SORT_KEY_FILTER_TYPE; + case 10: // SORT_KEY_FILTER_PATTERN + return SORT_KEY_FILTER_PATTERN; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __START_INCLUSIVE_ISSET_ID = 0; + private static final int __STOP_INCLUSIVE_ISSET_ID = 1; + private static final int __BATCH_SIZE_ISSET_ID = 2; + private static final int __NO_VALUE_ISSET_ID = 3; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.START_KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("start_key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.STOP_KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("stop_key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.START_INCLUSIVE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("start_inclusive", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL))); + tmpMap.put(_Fields.STOP_INCLUSIVE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("stop_inclusive", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL))); + tmpMap.put(_Fields.BATCH_SIZE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("batch_size", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.NO_VALUE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("no_value", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL))); + tmpMap.put(_Fields.HASH_KEY_FILTER_TYPE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("hash_key_filter_type", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.EnumMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.ENUM, filter_type.class))); + tmpMap.put(_Fields.HASH_KEY_FILTER_PATTERN, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("hash_key_filter_pattern", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.SORT_KEY_FILTER_TYPE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("sort_key_filter_type", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.EnumMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.ENUM, filter_type.class))); + tmpMap.put(_Fields.SORT_KEY_FILTER_PATTERN, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("sort_key_filter_pattern", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(get_scanner_request.class, metaDataMap); + } + + public get_scanner_request() { + } + + public get_scanner_request( + com.xiaomi.infra.pegasus.base.blob start_key, + com.xiaomi.infra.pegasus.base.blob stop_key, + boolean start_inclusive, + boolean stop_inclusive, + int batch_size, + boolean no_value, + filter_type hash_key_filter_type, + com.xiaomi.infra.pegasus.base.blob hash_key_filter_pattern, + filter_type sort_key_filter_type, + com.xiaomi.infra.pegasus.base.blob sort_key_filter_pattern) + { + this(); + this.start_key = start_key; + this.stop_key = stop_key; + this.start_inclusive = start_inclusive; + setStart_inclusiveIsSet(true); + this.stop_inclusive = stop_inclusive; + setStop_inclusiveIsSet(true); + this.batch_size = batch_size; + setBatch_sizeIsSet(true); + this.no_value = no_value; + setNo_valueIsSet(true); + this.hash_key_filter_type = hash_key_filter_type; + this.hash_key_filter_pattern = hash_key_filter_pattern; + this.sort_key_filter_type = sort_key_filter_type; + this.sort_key_filter_pattern = sort_key_filter_pattern; + } + + /** + * Performs a deep copy on other. + */ + public get_scanner_request(get_scanner_request other) { + __isset_bitfield = other.__isset_bitfield; + if (other.isSetStart_key()) { + this.start_key = new com.xiaomi.infra.pegasus.base.blob(other.start_key); + } + if (other.isSetStop_key()) { + this.stop_key = new com.xiaomi.infra.pegasus.base.blob(other.stop_key); + } + this.start_inclusive = other.start_inclusive; + this.stop_inclusive = other.stop_inclusive; + this.batch_size = other.batch_size; + this.no_value = other.no_value; + if (other.isSetHash_key_filter_type()) { + this.hash_key_filter_type = other.hash_key_filter_type; + } + if (other.isSetHash_key_filter_pattern()) { + this.hash_key_filter_pattern = new com.xiaomi.infra.pegasus.base.blob(other.hash_key_filter_pattern); + } + if (other.isSetSort_key_filter_type()) { + this.sort_key_filter_type = other.sort_key_filter_type; + } + if (other.isSetSort_key_filter_pattern()) { + this.sort_key_filter_pattern = new com.xiaomi.infra.pegasus.base.blob(other.sort_key_filter_pattern); + } + } + + public get_scanner_request deepCopy() { + return new get_scanner_request(this); + } + + @Override + public void clear() { + this.start_key = null; + this.stop_key = null; + setStart_inclusiveIsSet(false); + this.start_inclusive = false; + setStop_inclusiveIsSet(false); + this.stop_inclusive = false; + setBatch_sizeIsSet(false); + this.batch_size = 0; + setNo_valueIsSet(false); + this.no_value = false; + this.hash_key_filter_type = null; + this.hash_key_filter_pattern = null; + this.sort_key_filter_type = null; + this.sort_key_filter_pattern = null; + } + + public com.xiaomi.infra.pegasus.base.blob getStart_key() { + return this.start_key; + } + + public get_scanner_request setStart_key(com.xiaomi.infra.pegasus.base.blob start_key) { + this.start_key = start_key; + return this; + } + + public void unsetStart_key() { + this.start_key = null; + } + + /** Returns true if field start_key is set (has been assigned a value) and false otherwise */ + public boolean isSetStart_key() { + return this.start_key != null; + } + + public void setStart_keyIsSet(boolean value) { + if (!value) { + this.start_key = null; + } + } + + public com.xiaomi.infra.pegasus.base.blob getStop_key() { + return this.stop_key; + } + + public get_scanner_request setStop_key(com.xiaomi.infra.pegasus.base.blob stop_key) { + this.stop_key = stop_key; + return this; + } + + public void unsetStop_key() { + this.stop_key = null; + } + + /** Returns true if field stop_key is set (has been assigned a value) and false otherwise */ + public boolean isSetStop_key() { + return this.stop_key != null; + } + + public void setStop_keyIsSet(boolean value) { + if (!value) { + this.stop_key = null; + } + } + + public boolean isStart_inclusive() { + return this.start_inclusive; + } + + public get_scanner_request setStart_inclusive(boolean start_inclusive) { + this.start_inclusive = start_inclusive; + setStart_inclusiveIsSet(true); + return this; + } + + public void unsetStart_inclusive() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __START_INCLUSIVE_ISSET_ID); + } + + /** Returns true if field start_inclusive is set (has been assigned a value) and false otherwise */ + public boolean isSetStart_inclusive() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __START_INCLUSIVE_ISSET_ID); + } + + public void setStart_inclusiveIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __START_INCLUSIVE_ISSET_ID, value); + } + + public boolean isStop_inclusive() { + return this.stop_inclusive; + } + + public get_scanner_request setStop_inclusive(boolean stop_inclusive) { + this.stop_inclusive = stop_inclusive; + setStop_inclusiveIsSet(true); + return this; + } + + public void unsetStop_inclusive() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __STOP_INCLUSIVE_ISSET_ID); + } + + /** Returns true if field stop_inclusive is set (has been assigned a value) and false otherwise */ + public boolean isSetStop_inclusive() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __STOP_INCLUSIVE_ISSET_ID); + } + + public void setStop_inclusiveIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __STOP_INCLUSIVE_ISSET_ID, value); + } + + public int getBatch_size() { + return this.batch_size; + } + + public get_scanner_request setBatch_size(int batch_size) { + this.batch_size = batch_size; + setBatch_sizeIsSet(true); + return this; + } + + public void unsetBatch_size() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __BATCH_SIZE_ISSET_ID); + } + + /** Returns true if field batch_size is set (has been assigned a value) and false otherwise */ + public boolean isSetBatch_size() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __BATCH_SIZE_ISSET_ID); + } + + public void setBatch_sizeIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __BATCH_SIZE_ISSET_ID, value); + } + + public boolean isNo_value() { + return this.no_value; + } + + public get_scanner_request setNo_value(boolean no_value) { + this.no_value = no_value; + setNo_valueIsSet(true); + return this; + } + + public void unsetNo_value() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __NO_VALUE_ISSET_ID); + } + + /** Returns true if field no_value is set (has been assigned a value) and false otherwise */ + public boolean isSetNo_value() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __NO_VALUE_ISSET_ID); + } + + public void setNo_valueIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __NO_VALUE_ISSET_ID, value); + } + + /** + * + * @see filter_type + */ + public filter_type getHash_key_filter_type() { + return this.hash_key_filter_type; + } + + /** + * + * @see filter_type + */ + public get_scanner_request setHash_key_filter_type(filter_type hash_key_filter_type) { + this.hash_key_filter_type = hash_key_filter_type; + return this; + } + + public void unsetHash_key_filter_type() { + this.hash_key_filter_type = null; + } + + /** Returns true if field hash_key_filter_type is set (has been assigned a value) and false otherwise */ + public boolean isSetHash_key_filter_type() { + return this.hash_key_filter_type != null; + } + + public void setHash_key_filter_typeIsSet(boolean value) { + if (!value) { + this.hash_key_filter_type = null; + } + } + + public com.xiaomi.infra.pegasus.base.blob getHash_key_filter_pattern() { + return this.hash_key_filter_pattern; + } + + public get_scanner_request setHash_key_filter_pattern(com.xiaomi.infra.pegasus.base.blob hash_key_filter_pattern) { + this.hash_key_filter_pattern = hash_key_filter_pattern; + return this; + } + + public void unsetHash_key_filter_pattern() { + this.hash_key_filter_pattern = null; + } + + /** Returns true if field hash_key_filter_pattern is set (has been assigned a value) and false otherwise */ + public boolean isSetHash_key_filter_pattern() { + return this.hash_key_filter_pattern != null; + } + + public void setHash_key_filter_patternIsSet(boolean value) { + if (!value) { + this.hash_key_filter_pattern = null; + } + } + + /** + * + * @see filter_type + */ + public filter_type getSort_key_filter_type() { + return this.sort_key_filter_type; + } + + /** + * + * @see filter_type + */ + public get_scanner_request setSort_key_filter_type(filter_type sort_key_filter_type) { + this.sort_key_filter_type = sort_key_filter_type; + return this; + } + + public void unsetSort_key_filter_type() { + this.sort_key_filter_type = null; + } + + /** Returns true if field sort_key_filter_type is set (has been assigned a value) and false otherwise */ + public boolean isSetSort_key_filter_type() { + return this.sort_key_filter_type != null; + } + + public void setSort_key_filter_typeIsSet(boolean value) { + if (!value) { + this.sort_key_filter_type = null; + } + } + + public com.xiaomi.infra.pegasus.base.blob getSort_key_filter_pattern() { + return this.sort_key_filter_pattern; + } + + public get_scanner_request setSort_key_filter_pattern(com.xiaomi.infra.pegasus.base.blob sort_key_filter_pattern) { + this.sort_key_filter_pattern = sort_key_filter_pattern; + return this; + } + + public void unsetSort_key_filter_pattern() { + this.sort_key_filter_pattern = null; + } + + /** Returns true if field sort_key_filter_pattern is set (has been assigned a value) and false otherwise */ + public boolean isSetSort_key_filter_pattern() { + return this.sort_key_filter_pattern != null; + } + + public void setSort_key_filter_patternIsSet(boolean value) { + if (!value) { + this.sort_key_filter_pattern = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case START_KEY: + if (value == null) { + unsetStart_key(); + } else { + setStart_key((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case STOP_KEY: + if (value == null) { + unsetStop_key(); + } else { + setStop_key((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case START_INCLUSIVE: + if (value == null) { + unsetStart_inclusive(); + } else { + setStart_inclusive((java.lang.Boolean)value); + } + break; + + case STOP_INCLUSIVE: + if (value == null) { + unsetStop_inclusive(); + } else { + setStop_inclusive((java.lang.Boolean)value); + } + break; + + case BATCH_SIZE: + if (value == null) { + unsetBatch_size(); + } else { + setBatch_size((java.lang.Integer)value); + } + break; + + case NO_VALUE: + if (value == null) { + unsetNo_value(); + } else { + setNo_value((java.lang.Boolean)value); + } + break; + + case HASH_KEY_FILTER_TYPE: + if (value == null) { + unsetHash_key_filter_type(); + } else { + setHash_key_filter_type((filter_type)value); + } + break; + + case HASH_KEY_FILTER_PATTERN: + if (value == null) { + unsetHash_key_filter_pattern(); + } else { + setHash_key_filter_pattern((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case SORT_KEY_FILTER_TYPE: + if (value == null) { + unsetSort_key_filter_type(); + } else { + setSort_key_filter_type((filter_type)value); + } + break; + + case SORT_KEY_FILTER_PATTERN: + if (value == null) { + unsetSort_key_filter_pattern(); + } else { + setSort_key_filter_pattern((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case START_KEY: + return getStart_key(); + + case STOP_KEY: + return getStop_key(); + + case START_INCLUSIVE: + return isStart_inclusive(); + + case STOP_INCLUSIVE: + return isStop_inclusive(); + + case BATCH_SIZE: + return getBatch_size(); + + case NO_VALUE: + return isNo_value(); + + case HASH_KEY_FILTER_TYPE: + return getHash_key_filter_type(); + + case HASH_KEY_FILTER_PATTERN: + return getHash_key_filter_pattern(); + + case SORT_KEY_FILTER_TYPE: + return getSort_key_filter_type(); + + case SORT_KEY_FILTER_PATTERN: + return getSort_key_filter_pattern(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case START_KEY: + return isSetStart_key(); + case STOP_KEY: + return isSetStop_key(); + case START_INCLUSIVE: + return isSetStart_inclusive(); + case STOP_INCLUSIVE: + return isSetStop_inclusive(); + case BATCH_SIZE: + return isSetBatch_size(); + case NO_VALUE: + return isSetNo_value(); + case HASH_KEY_FILTER_TYPE: + return isSetHash_key_filter_type(); + case HASH_KEY_FILTER_PATTERN: + return isSetHash_key_filter_pattern(); + case SORT_KEY_FILTER_TYPE: + return isSetSort_key_filter_type(); + case SORT_KEY_FILTER_PATTERN: + return isSetSort_key_filter_pattern(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof get_scanner_request) + return this.equals((get_scanner_request)that); + return false; + } + + public boolean equals(get_scanner_request that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_start_key = true && this.isSetStart_key(); + boolean that_present_start_key = true && that.isSetStart_key(); + if (this_present_start_key || that_present_start_key) { + if (!(this_present_start_key && that_present_start_key)) + return false; + if (!this.start_key.equals(that.start_key)) + return false; + } + + boolean this_present_stop_key = true && this.isSetStop_key(); + boolean that_present_stop_key = true && that.isSetStop_key(); + if (this_present_stop_key || that_present_stop_key) { + if (!(this_present_stop_key && that_present_stop_key)) + return false; + if (!this.stop_key.equals(that.stop_key)) + return false; + } + + boolean this_present_start_inclusive = true; + boolean that_present_start_inclusive = true; + if (this_present_start_inclusive || that_present_start_inclusive) { + if (!(this_present_start_inclusive && that_present_start_inclusive)) + return false; + if (this.start_inclusive != that.start_inclusive) + return false; + } + + boolean this_present_stop_inclusive = true; + boolean that_present_stop_inclusive = true; + if (this_present_stop_inclusive || that_present_stop_inclusive) { + if (!(this_present_stop_inclusive && that_present_stop_inclusive)) + return false; + if (this.stop_inclusive != that.stop_inclusive) + return false; + } + + boolean this_present_batch_size = true; + boolean that_present_batch_size = true; + if (this_present_batch_size || that_present_batch_size) { + if (!(this_present_batch_size && that_present_batch_size)) + return false; + if (this.batch_size != that.batch_size) + return false; + } + + boolean this_present_no_value = true; + boolean that_present_no_value = true; + if (this_present_no_value || that_present_no_value) { + if (!(this_present_no_value && that_present_no_value)) + return false; + if (this.no_value != that.no_value) + return false; + } + + boolean this_present_hash_key_filter_type = true && this.isSetHash_key_filter_type(); + boolean that_present_hash_key_filter_type = true && that.isSetHash_key_filter_type(); + if (this_present_hash_key_filter_type || that_present_hash_key_filter_type) { + if (!(this_present_hash_key_filter_type && that_present_hash_key_filter_type)) + return false; + if (!this.hash_key_filter_type.equals(that.hash_key_filter_type)) + return false; + } + + boolean this_present_hash_key_filter_pattern = true && this.isSetHash_key_filter_pattern(); + boolean that_present_hash_key_filter_pattern = true && that.isSetHash_key_filter_pattern(); + if (this_present_hash_key_filter_pattern || that_present_hash_key_filter_pattern) { + if (!(this_present_hash_key_filter_pattern && that_present_hash_key_filter_pattern)) + return false; + if (!this.hash_key_filter_pattern.equals(that.hash_key_filter_pattern)) + return false; + } + + boolean this_present_sort_key_filter_type = true && this.isSetSort_key_filter_type(); + boolean that_present_sort_key_filter_type = true && that.isSetSort_key_filter_type(); + if (this_present_sort_key_filter_type || that_present_sort_key_filter_type) { + if (!(this_present_sort_key_filter_type && that_present_sort_key_filter_type)) + return false; + if (!this.sort_key_filter_type.equals(that.sort_key_filter_type)) + return false; + } + + boolean this_present_sort_key_filter_pattern = true && this.isSetSort_key_filter_pattern(); + boolean that_present_sort_key_filter_pattern = true && that.isSetSort_key_filter_pattern(); + if (this_present_sort_key_filter_pattern || that_present_sort_key_filter_pattern) { + if (!(this_present_sort_key_filter_pattern && that_present_sort_key_filter_pattern)) + return false; + if (!this.sort_key_filter_pattern.equals(that.sort_key_filter_pattern)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetStart_key()) ? 131071 : 524287); + if (isSetStart_key()) + hashCode = hashCode * 8191 + start_key.hashCode(); + + hashCode = hashCode * 8191 + ((isSetStop_key()) ? 131071 : 524287); + if (isSetStop_key()) + hashCode = hashCode * 8191 + stop_key.hashCode(); + + hashCode = hashCode * 8191 + ((start_inclusive) ? 131071 : 524287); + + hashCode = hashCode * 8191 + ((stop_inclusive) ? 131071 : 524287); + + hashCode = hashCode * 8191 + batch_size; + + hashCode = hashCode * 8191 + ((no_value) ? 131071 : 524287); + + hashCode = hashCode * 8191 + ((isSetHash_key_filter_type()) ? 131071 : 524287); + if (isSetHash_key_filter_type()) + hashCode = hashCode * 8191 + hash_key_filter_type.getValue(); + + hashCode = hashCode * 8191 + ((isSetHash_key_filter_pattern()) ? 131071 : 524287); + if (isSetHash_key_filter_pattern()) + hashCode = hashCode * 8191 + hash_key_filter_pattern.hashCode(); + + hashCode = hashCode * 8191 + ((isSetSort_key_filter_type()) ? 131071 : 524287); + if (isSetSort_key_filter_type()) + hashCode = hashCode * 8191 + sort_key_filter_type.getValue(); + + hashCode = hashCode * 8191 + ((isSetSort_key_filter_pattern()) ? 131071 : 524287); + if (isSetSort_key_filter_pattern()) + hashCode = hashCode * 8191 + sort_key_filter_pattern.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(get_scanner_request other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetStart_key()).compareTo(other.isSetStart_key()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetStart_key()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.start_key, other.start_key); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetStop_key()).compareTo(other.isSetStop_key()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetStop_key()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.stop_key, other.stop_key); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetStart_inclusive()).compareTo(other.isSetStart_inclusive()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetStart_inclusive()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.start_inclusive, other.start_inclusive); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetStop_inclusive()).compareTo(other.isSetStop_inclusive()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetStop_inclusive()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.stop_inclusive, other.stop_inclusive); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetBatch_size()).compareTo(other.isSetBatch_size()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetBatch_size()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.batch_size, other.batch_size); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetNo_value()).compareTo(other.isSetNo_value()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetNo_value()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.no_value, other.no_value); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetHash_key_filter_type()).compareTo(other.isSetHash_key_filter_type()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetHash_key_filter_type()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.hash_key_filter_type, other.hash_key_filter_type); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetHash_key_filter_pattern()).compareTo(other.isSetHash_key_filter_pattern()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetHash_key_filter_pattern()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.hash_key_filter_pattern, other.hash_key_filter_pattern); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetSort_key_filter_type()).compareTo(other.isSetSort_key_filter_type()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSort_key_filter_type()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.sort_key_filter_type, other.sort_key_filter_type); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetSort_key_filter_pattern()).compareTo(other.isSetSort_key_filter_pattern()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSort_key_filter_pattern()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.sort_key_filter_pattern, other.sort_key_filter_pattern); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("get_scanner_request("); + boolean first = true; + + sb.append("start_key:"); + if (this.start_key == null) { + sb.append("null"); + } else { + sb.append(this.start_key); + } + first = false; + if (!first) sb.append(", "); + sb.append("stop_key:"); + if (this.stop_key == null) { + sb.append("null"); + } else { + sb.append(this.stop_key); + } + first = false; + if (!first) sb.append(", "); + sb.append("start_inclusive:"); + sb.append(this.start_inclusive); + first = false; + if (!first) sb.append(", "); + sb.append("stop_inclusive:"); + sb.append(this.stop_inclusive); + first = false; + if (!first) sb.append(", "); + sb.append("batch_size:"); + sb.append(this.batch_size); + first = false; + if (!first) sb.append(", "); + sb.append("no_value:"); + sb.append(this.no_value); + first = false; + if (!first) sb.append(", "); + sb.append("hash_key_filter_type:"); + if (this.hash_key_filter_type == null) { + sb.append("null"); + } else { + sb.append(this.hash_key_filter_type); + } + first = false; + if (!first) sb.append(", "); + sb.append("hash_key_filter_pattern:"); + if (this.hash_key_filter_pattern == null) { + sb.append("null"); + } else { + sb.append(this.hash_key_filter_pattern); + } + first = false; + if (!first) sb.append(", "); + sb.append("sort_key_filter_type:"); + if (this.sort_key_filter_type == null) { + sb.append("null"); + } else { + sb.append(this.sort_key_filter_type); + } + first = false; + if (!first) sb.append(", "); + sb.append("sort_key_filter_pattern:"); + if (this.sort_key_filter_pattern == null) { + sb.append("null"); + } else { + sb.append(this.sort_key_filter_pattern); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (start_key != null) { + start_key.validate(); + } + if (stop_key != null) { + stop_key.validate(); + } + if (hash_key_filter_pattern != null) { + hash_key_filter_pattern.validate(); + } + if (sort_key_filter_pattern != null) { + sort_key_filter_pattern.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class get_scanner_requestStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public get_scanner_requestStandardScheme getScheme() { + return new get_scanner_requestStandardScheme(); + } + } + + private static class get_scanner_requestStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, get_scanner_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // START_KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.start_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.start_key.read(iprot); + struct.setStart_keyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // STOP_KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.stop_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.stop_key.read(iprot); + struct.setStop_keyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // START_INCLUSIVE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL) { + struct.start_inclusive = iprot.readBool(); + struct.setStart_inclusiveIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // STOP_INCLUSIVE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL) { + struct.stop_inclusive = iprot.readBool(); + struct.setStop_inclusiveIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 5: // BATCH_SIZE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.batch_size = iprot.readI32(); + struct.setBatch_sizeIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 6: // NO_VALUE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL) { + struct.no_value = iprot.readBool(); + struct.setNo_valueIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 7: // HASH_KEY_FILTER_TYPE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.hash_key_filter_type = com.xiaomi.infra.pegasus.apps.filter_type.findByValue(iprot.readI32()); + struct.setHash_key_filter_typeIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 8: // HASH_KEY_FILTER_PATTERN + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.hash_key_filter_pattern = new com.xiaomi.infra.pegasus.base.blob(); + struct.hash_key_filter_pattern.read(iprot); + struct.setHash_key_filter_patternIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 9: // SORT_KEY_FILTER_TYPE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.sort_key_filter_type = com.xiaomi.infra.pegasus.apps.filter_type.findByValue(iprot.readI32()); + struct.setSort_key_filter_typeIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 10: // SORT_KEY_FILTER_PATTERN + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.sort_key_filter_pattern = new com.xiaomi.infra.pegasus.base.blob(); + struct.sort_key_filter_pattern.read(iprot); + struct.setSort_key_filter_patternIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, get_scanner_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.start_key != null) { + oprot.writeFieldBegin(START_KEY_FIELD_DESC); + struct.start_key.write(oprot); + oprot.writeFieldEnd(); + } + if (struct.stop_key != null) { + oprot.writeFieldBegin(STOP_KEY_FIELD_DESC); + struct.stop_key.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(START_INCLUSIVE_FIELD_DESC); + oprot.writeBool(struct.start_inclusive); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(STOP_INCLUSIVE_FIELD_DESC); + oprot.writeBool(struct.stop_inclusive); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(BATCH_SIZE_FIELD_DESC); + oprot.writeI32(struct.batch_size); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(NO_VALUE_FIELD_DESC); + oprot.writeBool(struct.no_value); + oprot.writeFieldEnd(); + if (struct.hash_key_filter_type != null) { + oprot.writeFieldBegin(HASH_KEY_FILTER_TYPE_FIELD_DESC); + oprot.writeI32(struct.hash_key_filter_type.getValue()); + oprot.writeFieldEnd(); + } + if (struct.hash_key_filter_pattern != null) { + oprot.writeFieldBegin(HASH_KEY_FILTER_PATTERN_FIELD_DESC); + struct.hash_key_filter_pattern.write(oprot); + oprot.writeFieldEnd(); + } + if (struct.sort_key_filter_type != null) { + oprot.writeFieldBegin(SORT_KEY_FILTER_TYPE_FIELD_DESC); + oprot.writeI32(struct.sort_key_filter_type.getValue()); + oprot.writeFieldEnd(); + } + if (struct.sort_key_filter_pattern != null) { + oprot.writeFieldBegin(SORT_KEY_FILTER_PATTERN_FIELD_DESC); + struct.sort_key_filter_pattern.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class get_scanner_requestTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public get_scanner_requestTupleScheme getScheme() { + return new get_scanner_requestTupleScheme(); + } + } + + private static class get_scanner_requestTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, get_scanner_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetStart_key()) { + optionals.set(0); + } + if (struct.isSetStop_key()) { + optionals.set(1); + } + if (struct.isSetStart_inclusive()) { + optionals.set(2); + } + if (struct.isSetStop_inclusive()) { + optionals.set(3); + } + if (struct.isSetBatch_size()) { + optionals.set(4); + } + if (struct.isSetNo_value()) { + optionals.set(5); + } + if (struct.isSetHash_key_filter_type()) { + optionals.set(6); + } + if (struct.isSetHash_key_filter_pattern()) { + optionals.set(7); + } + if (struct.isSetSort_key_filter_type()) { + optionals.set(8); + } + if (struct.isSetSort_key_filter_pattern()) { + optionals.set(9); + } + oprot.writeBitSet(optionals, 10); + if (struct.isSetStart_key()) { + struct.start_key.write(oprot); + } + if (struct.isSetStop_key()) { + struct.stop_key.write(oprot); + } + if (struct.isSetStart_inclusive()) { + oprot.writeBool(struct.start_inclusive); + } + if (struct.isSetStop_inclusive()) { + oprot.writeBool(struct.stop_inclusive); + } + if (struct.isSetBatch_size()) { + oprot.writeI32(struct.batch_size); + } + if (struct.isSetNo_value()) { + oprot.writeBool(struct.no_value); + } + if (struct.isSetHash_key_filter_type()) { + oprot.writeI32(struct.hash_key_filter_type.getValue()); + } + if (struct.isSetHash_key_filter_pattern()) { + struct.hash_key_filter_pattern.write(oprot); + } + if (struct.isSetSort_key_filter_type()) { + oprot.writeI32(struct.sort_key_filter_type.getValue()); + } + if (struct.isSetSort_key_filter_pattern()) { + struct.sort_key_filter_pattern.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, get_scanner_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(10); + if (incoming.get(0)) { + struct.start_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.start_key.read(iprot); + struct.setStart_keyIsSet(true); + } + if (incoming.get(1)) { + struct.stop_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.stop_key.read(iprot); + struct.setStop_keyIsSet(true); + } + if (incoming.get(2)) { + struct.start_inclusive = iprot.readBool(); + struct.setStart_inclusiveIsSet(true); + } + if (incoming.get(3)) { + struct.stop_inclusive = iprot.readBool(); + struct.setStop_inclusiveIsSet(true); + } + if (incoming.get(4)) { + struct.batch_size = iprot.readI32(); + struct.setBatch_sizeIsSet(true); + } + if (incoming.get(5)) { + struct.no_value = iprot.readBool(); + struct.setNo_valueIsSet(true); + } + if (incoming.get(6)) { + struct.hash_key_filter_type = com.xiaomi.infra.pegasus.apps.filter_type.findByValue(iprot.readI32()); + struct.setHash_key_filter_typeIsSet(true); + } + if (incoming.get(7)) { + struct.hash_key_filter_pattern = new com.xiaomi.infra.pegasus.base.blob(); + struct.hash_key_filter_pattern.read(iprot); + struct.setHash_key_filter_patternIsSet(true); + } + if (incoming.get(8)) { + struct.sort_key_filter_type = com.xiaomi.infra.pegasus.apps.filter_type.findByValue(iprot.readI32()); + struct.setSort_key_filter_typeIsSet(true); + } + if (incoming.get(9)) { + struct.sort_key_filter_pattern = new com.xiaomi.infra.pegasus.base.blob(); + struct.sort_key_filter_pattern.read(iprot); + struct.setSort_key_filter_patternIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/key_value.java b/src/main/java/com/xiaomi/infra/pegasus/apps/key_value.java new file mode 100644 index 00000000..e1b3b836 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/key_value.java @@ -0,0 +1,489 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class key_value implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("key_value"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField VALUE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("value", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)2); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new key_valueStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new key_valueTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.blob key; // required + public com.xiaomi.infra.pegasus.base.blob value; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + KEY((short)1, "key"), + VALUE((short)2, "value"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // KEY + return KEY; + case 2: // VALUE + return VALUE; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.VALUE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("value", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(key_value.class, metaDataMap); + } + + public key_value() { + } + + public key_value( + com.xiaomi.infra.pegasus.base.blob key, + com.xiaomi.infra.pegasus.base.blob value) + { + this(); + this.key = key; + this.value = value; + } + + /** + * Performs a deep copy on other. + */ + public key_value(key_value other) { + if (other.isSetKey()) { + this.key = new com.xiaomi.infra.pegasus.base.blob(other.key); + } + if (other.isSetValue()) { + this.value = new com.xiaomi.infra.pegasus.base.blob(other.value); + } + } + + public key_value deepCopy() { + return new key_value(this); + } + + @Override + public void clear() { + this.key = null; + this.value = null; + } + + public com.xiaomi.infra.pegasus.base.blob getKey() { + return this.key; + } + + public key_value setKey(com.xiaomi.infra.pegasus.base.blob key) { + this.key = key; + return this; + } + + public void unsetKey() { + this.key = null; + } + + /** Returns true if field key is set (has been assigned a value) and false otherwise */ + public boolean isSetKey() { + return this.key != null; + } + + public void setKeyIsSet(boolean value) { + if (!value) { + this.key = null; + } + } + + public com.xiaomi.infra.pegasus.base.blob getValue() { + return this.value; + } + + public key_value setValue(com.xiaomi.infra.pegasus.base.blob value) { + this.value = value; + return this; + } + + public void unsetValue() { + this.value = null; + } + + /** Returns true if field value is set (has been assigned a value) and false otherwise */ + public boolean isSetValue() { + return this.value != null; + } + + public void setValueIsSet(boolean value) { + if (!value) { + this.value = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case KEY: + if (value == null) { + unsetKey(); + } else { + setKey((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case VALUE: + if (value == null) { + unsetValue(); + } else { + setValue((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case KEY: + return getKey(); + + case VALUE: + return getValue(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case KEY: + return isSetKey(); + case VALUE: + return isSetValue(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof key_value) + return this.equals((key_value)that); + return false; + } + + public boolean equals(key_value that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_key = true && this.isSetKey(); + boolean that_present_key = true && that.isSetKey(); + if (this_present_key || that_present_key) { + if (!(this_present_key && that_present_key)) + return false; + if (!this.key.equals(that.key)) + return false; + } + + boolean this_present_value = true && this.isSetValue(); + boolean that_present_value = true && that.isSetValue(); + if (this_present_value || that_present_value) { + if (!(this_present_value && that_present_value)) + return false; + if (!this.value.equals(that.value)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetKey()) ? 131071 : 524287); + if (isSetKey()) + hashCode = hashCode * 8191 + key.hashCode(); + + hashCode = hashCode * 8191 + ((isSetValue()) ? 131071 : 524287); + if (isSetValue()) + hashCode = hashCode * 8191 + value.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(key_value other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetKey()).compareTo(other.isSetKey()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetKey()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.key, other.key); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetValue()).compareTo(other.isSetValue()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetValue()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.value, other.value); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("key_value("); + boolean first = true; + + sb.append("key:"); + if (this.key == null) { + sb.append("null"); + } else { + sb.append(this.key); + } + first = false; + if (!first) sb.append(", "); + sb.append("value:"); + if (this.value == null) { + sb.append("null"); + } else { + sb.append(this.value); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (key != null) { + key.validate(); + } + if (value != null) { + value.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class key_valueStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public key_valueStandardScheme getScheme() { + return new key_valueStandardScheme(); + } + } + + private static class key_valueStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, key_value struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.key = new com.xiaomi.infra.pegasus.base.blob(); + struct.key.read(iprot); + struct.setKeyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // VALUE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.value = new com.xiaomi.infra.pegasus.base.blob(); + struct.value.read(iprot); + struct.setValueIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, key_value struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.key != null) { + oprot.writeFieldBegin(KEY_FIELD_DESC); + struct.key.write(oprot); + oprot.writeFieldEnd(); + } + if (struct.value != null) { + oprot.writeFieldBegin(VALUE_FIELD_DESC); + struct.value.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class key_valueTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public key_valueTupleScheme getScheme() { + return new key_valueTupleScheme(); + } + } + + private static class key_valueTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, key_value struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetKey()) { + optionals.set(0); + } + if (struct.isSetValue()) { + optionals.set(1); + } + oprot.writeBitSet(optionals, 2); + if (struct.isSetKey()) { + struct.key.write(oprot); + } + if (struct.isSetValue()) { + struct.value.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, key_value struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(2); + if (incoming.get(0)) { + struct.key = new com.xiaomi.infra.pegasus.base.blob(); + struct.key.read(iprot); + struct.setKeyIsSet(true); + } + if (incoming.get(1)) { + struct.value = new com.xiaomi.infra.pegasus.base.blob(); + struct.value.read(iprot); + struct.setValueIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/meta.java b/src/main/java/com/xiaomi/infra/pegasus/apps/meta.java new file mode 100644 index 00000000..cf835ce1 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/meta.java @@ -0,0 +1,977 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class meta { + + public interface Iface { + + public com.xiaomi.infra.pegasus.replication.query_cfg_response query_cfg(com.xiaomi.infra.pegasus.replication.query_cfg_request query) throws com.xiaomi.infra.pegasus.thrift.TException; + + } + + public interface AsyncIface { + + public void query_cfg(com.xiaomi.infra.pegasus.replication.query_cfg_request query, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + } + + public static class Client extends com.xiaomi.infra.pegasus.thrift.TServiceClient implements Iface { + public static class Factory implements com.xiaomi.infra.pegasus.thrift.TServiceClientFactory { + public Factory() {} + public Client getClient(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) { + return new Client(prot); + } + public Client getClient(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) { + return new Client(iprot, oprot); + } + } + + public Client(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) + { + super(prot, prot); + } + + public Client(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) { + super(iprot, oprot); + } + + public com.xiaomi.infra.pegasus.replication.query_cfg_response query_cfg(com.xiaomi.infra.pegasus.replication.query_cfg_request query) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_query_cfg(query); + return recv_query_cfg(); + } + + public void send_query_cfg(com.xiaomi.infra.pegasus.replication.query_cfg_request query) throws com.xiaomi.infra.pegasus.thrift.TException + { + query_cfg_args args = new query_cfg_args(); + args.setQuery(query); + sendBase("query_cfg", args); + } + + public com.xiaomi.infra.pegasus.replication.query_cfg_response recv_query_cfg() throws com.xiaomi.infra.pegasus.thrift.TException + { + query_cfg_result result = new query_cfg_result(); + receiveBase(result, "query_cfg"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "query_cfg failed: unknown result"); + } + + } + public static class AsyncClient extends com.xiaomi.infra.pegasus.thrift.async.TAsyncClient implements AsyncIface { + public static class Factory implements com.xiaomi.infra.pegasus.thrift.async.TAsyncClientFactory { + private com.xiaomi.infra.pegasus.thrift.async.TAsyncClientManager clientManager; + private com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory; + public Factory(com.xiaomi.infra.pegasus.thrift.async.TAsyncClientManager clientManager, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory) { + this.clientManager = clientManager; + this.protocolFactory = protocolFactory; + } + public AsyncClient getAsyncClient(com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) { + return new AsyncClient(protocolFactory, clientManager, transport); + } + } + + public AsyncClient(com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.async.TAsyncClientManager clientManager, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) { + super(protocolFactory, clientManager, transport); + } + + public void query_cfg(com.xiaomi.infra.pegasus.replication.query_cfg_request query, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + query_cfg_call method_call = new query_cfg_call(query, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class query_cfg_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private com.xiaomi.infra.pegasus.replication.query_cfg_request query; + public query_cfg_call(com.xiaomi.infra.pegasus.replication.query_cfg_request query, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.query = query; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("query_cfg", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + query_cfg_args args = new query_cfg_args(); + args.setQuery(query); + args.write(prot); + prot.writeMessageEnd(); + } + + public com.xiaomi.infra.pegasus.replication.query_cfg_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_query_cfg(); + } + } + + } + + public static class Processor extends com.xiaomi.infra.pegasus.thrift.TBaseProcessor implements com.xiaomi.infra.pegasus.thrift.TProcessor { + private static final org.slf4j.Logger _LOGGER = org.slf4j.LoggerFactory.getLogger(Processor.class.getName()); + public Processor(I iface) { + super(iface, getProcessMap(new java.util.HashMap>())); + } + + protected Processor(I iface, java.util.Map> processMap) { + super(iface, getProcessMap(processMap)); + } + + private static java.util.Map> getProcessMap(java.util.Map> processMap) { + processMap.put("query_cfg", new query_cfg()); + return processMap; + } + + public static class query_cfg extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public query_cfg() { + super("query_cfg"); + } + + public query_cfg_args getEmptyArgsInstance() { + return new query_cfg_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public query_cfg_result getResult(I iface, query_cfg_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + query_cfg_result result = new query_cfg_result(); + result.success = iface.query_cfg(args.query); + return result; + } + } + + } + + public static class AsyncProcessor extends com.xiaomi.infra.pegasus.thrift.TBaseAsyncProcessor { + private static final org.slf4j.Logger _LOGGER = org.slf4j.LoggerFactory.getLogger(AsyncProcessor.class.getName()); + public AsyncProcessor(I iface) { + super(iface, getProcessMap(new java.util.HashMap>())); + } + + protected AsyncProcessor(I iface, java.util.Map> processMap) { + super(iface, getProcessMap(processMap)); + } + + private static java.util.Map> getProcessMap(java.util.Map> processMap) { + processMap.put("query_cfg", new query_cfg()); + return processMap; + } + + public static class query_cfg extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public query_cfg() { + super("query_cfg"); + } + + public query_cfg_args getEmptyArgsInstance() { + return new query_cfg_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(com.xiaomi.infra.pegasus.replication.query_cfg_response o) { + query_cfg_result result = new query_cfg_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + query_cfg_result result = new query_cfg_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, query_cfg_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.query_cfg(args.query,resultHandler); + } + } + + } + + public static class query_cfg_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("query_cfg_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField QUERY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("query", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new query_cfg_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new query_cfg_argsTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.replication.query_cfg_request query; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + QUERY((short)1, "query"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // QUERY + return QUERY; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.QUERY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("query", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.replication.query_cfg_request.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(query_cfg_args.class, metaDataMap); + } + + public query_cfg_args() { + } + + public query_cfg_args( + com.xiaomi.infra.pegasus.replication.query_cfg_request query) + { + this(); + this.query = query; + } + + /** + * Performs a deep copy on other. + */ + public query_cfg_args(query_cfg_args other) { + if (other.isSetQuery()) { + this.query = new com.xiaomi.infra.pegasus.replication.query_cfg_request(other.query); + } + } + + public query_cfg_args deepCopy() { + return new query_cfg_args(this); + } + + @Override + public void clear() { + this.query = null; + } + + public com.xiaomi.infra.pegasus.replication.query_cfg_request getQuery() { + return this.query; + } + + public query_cfg_args setQuery(com.xiaomi.infra.pegasus.replication.query_cfg_request query) { + this.query = query; + return this; + } + + public void unsetQuery() { + this.query = null; + } + + /** Returns true if field query is set (has been assigned a value) and false otherwise */ + public boolean isSetQuery() { + return this.query != null; + } + + public void setQueryIsSet(boolean value) { + if (!value) { + this.query = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case QUERY: + if (value == null) { + unsetQuery(); + } else { + setQuery((com.xiaomi.infra.pegasus.replication.query_cfg_request)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case QUERY: + return getQuery(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case QUERY: + return isSetQuery(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof query_cfg_args) + return this.equals((query_cfg_args)that); + return false; + } + + public boolean equals(query_cfg_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_query = true && this.isSetQuery(); + boolean that_present_query = true && that.isSetQuery(); + if (this_present_query || that_present_query) { + if (!(this_present_query && that_present_query)) + return false; + if (!this.query.equals(that.query)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetQuery()) ? 131071 : 524287); + if (isSetQuery()) + hashCode = hashCode * 8191 + query.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(query_cfg_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetQuery()).compareTo(other.isSetQuery()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetQuery()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.query, other.query); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("query_cfg_args("); + boolean first = true; + + sb.append("query:"); + if (this.query == null) { + sb.append("null"); + } else { + sb.append(this.query); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (query != null) { + query.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class query_cfg_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public query_cfg_argsStandardScheme getScheme() { + return new query_cfg_argsStandardScheme(); + } + } + + private static class query_cfg_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, query_cfg_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // QUERY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.query = new com.xiaomi.infra.pegasus.replication.query_cfg_request(); + struct.query.read(iprot); + struct.setQueryIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, query_cfg_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.query != null) { + oprot.writeFieldBegin(QUERY_FIELD_DESC); + struct.query.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class query_cfg_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public query_cfg_argsTupleScheme getScheme() { + return new query_cfg_argsTupleScheme(); + } + } + + private static class query_cfg_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, query_cfg_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetQuery()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetQuery()) { + struct.query.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, query_cfg_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.query = new com.xiaomi.infra.pegasus.replication.query_cfg_request(); + struct.query.read(iprot); + struct.setQueryIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class query_cfg_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("query_cfg_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new query_cfg_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new query_cfg_resultTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.replication.query_cfg_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.replication.query_cfg_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(query_cfg_result.class, metaDataMap); + } + + public query_cfg_result() { + } + + public query_cfg_result( + com.xiaomi.infra.pegasus.replication.query_cfg_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public query_cfg_result(query_cfg_result other) { + if (other.isSetSuccess()) { + this.success = new com.xiaomi.infra.pegasus.replication.query_cfg_response(other.success); + } + } + + public query_cfg_result deepCopy() { + return new query_cfg_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public com.xiaomi.infra.pegasus.replication.query_cfg_response getSuccess() { + return this.success; + } + + public query_cfg_result setSuccess(com.xiaomi.infra.pegasus.replication.query_cfg_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((com.xiaomi.infra.pegasus.replication.query_cfg_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof query_cfg_result) + return this.equals((query_cfg_result)that); + return false; + } + + public boolean equals(query_cfg_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(query_cfg_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("query_cfg_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class query_cfg_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public query_cfg_resultStandardScheme getScheme() { + return new query_cfg_resultStandardScheme(); + } + } + + private static class query_cfg_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, query_cfg_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new com.xiaomi.infra.pegasus.replication.query_cfg_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, query_cfg_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class query_cfg_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public query_cfg_resultTupleScheme getScheme() { + return new query_cfg_resultTupleScheme(); + } + } + + private static class query_cfg_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, query_cfg_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, query_cfg_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new com.xiaomi.infra.pegasus.replication.query_cfg_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/multi_get_request.java b/src/main/java/com/xiaomi/infra/pegasus/apps/multi_get_request.java new file mode 100644 index 00000000..3d811db4 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/multi_get_request.java @@ -0,0 +1,1469 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class multi_get_request implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_get_request"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField HASH_KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("hash_key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SORK_KEYS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("sork_keys", com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField MAX_KV_COUNT_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("max_kv_count", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField MAX_KV_SIZE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("max_kv_size", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField NO_VALUE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("no_value", com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL, (short)5); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField START_SORTKEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("start_sortkey", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)6); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField STOP_SORTKEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("stop_sortkey", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)7); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField START_INCLUSIVE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("start_inclusive", com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL, (short)8); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField STOP_INCLUSIVE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("stop_inclusive", com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL, (short)9); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SORT_KEY_FILTER_TYPE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("sort_key_filter_type", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)10); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SORT_KEY_FILTER_PATTERN_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("sort_key_filter_pattern", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)11); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_get_requestStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_get_requestTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.blob hash_key; // required + public java.util.List sork_keys; // required + public int max_kv_count; // required + public int max_kv_size; // required + public boolean no_value; // required + public com.xiaomi.infra.pegasus.base.blob start_sortkey; // required + public com.xiaomi.infra.pegasus.base.blob stop_sortkey; // required + public boolean start_inclusive; // required + public boolean stop_inclusive; // required + /** + * + * @see filter_type + */ + public filter_type sort_key_filter_type; // required + public com.xiaomi.infra.pegasus.base.blob sort_key_filter_pattern; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + HASH_KEY((short)1, "hash_key"), + SORK_KEYS((short)2, "sork_keys"), + MAX_KV_COUNT((short)3, "max_kv_count"), + MAX_KV_SIZE((short)4, "max_kv_size"), + NO_VALUE((short)5, "no_value"), + START_SORTKEY((short)6, "start_sortkey"), + STOP_SORTKEY((short)7, "stop_sortkey"), + START_INCLUSIVE((short)8, "start_inclusive"), + STOP_INCLUSIVE((short)9, "stop_inclusive"), + /** + * + * @see filter_type + */ + SORT_KEY_FILTER_TYPE((short)10, "sort_key_filter_type"), + SORT_KEY_FILTER_PATTERN((short)11, "sort_key_filter_pattern"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // HASH_KEY + return HASH_KEY; + case 2: // SORK_KEYS + return SORK_KEYS; + case 3: // MAX_KV_COUNT + return MAX_KV_COUNT; + case 4: // MAX_KV_SIZE + return MAX_KV_SIZE; + case 5: // NO_VALUE + return NO_VALUE; + case 6: // START_SORTKEY + return START_SORTKEY; + case 7: // STOP_SORTKEY + return STOP_SORTKEY; + case 8: // START_INCLUSIVE + return START_INCLUSIVE; + case 9: // STOP_INCLUSIVE + return STOP_INCLUSIVE; + case 10: // SORT_KEY_FILTER_TYPE + return SORT_KEY_FILTER_TYPE; + case 11: // SORT_KEY_FILTER_PATTERN + return SORT_KEY_FILTER_PATTERN; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __MAX_KV_COUNT_ISSET_ID = 0; + private static final int __MAX_KV_SIZE_ISSET_ID = 1; + private static final int __NO_VALUE_ISSET_ID = 2; + private static final int __START_INCLUSIVE_ISSET_ID = 3; + private static final int __STOP_INCLUSIVE_ISSET_ID = 4; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.HASH_KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("hash_key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.SORK_KEYS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("sork_keys", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.ListMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class)))); + tmpMap.put(_Fields.MAX_KV_COUNT, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("max_kv_count", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.MAX_KV_SIZE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("max_kv_size", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.NO_VALUE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("no_value", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL))); + tmpMap.put(_Fields.START_SORTKEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("start_sortkey", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.STOP_SORTKEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("stop_sortkey", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.START_INCLUSIVE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("start_inclusive", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL))); + tmpMap.put(_Fields.STOP_INCLUSIVE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("stop_inclusive", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL))); + tmpMap.put(_Fields.SORT_KEY_FILTER_TYPE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("sort_key_filter_type", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.EnumMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.ENUM, filter_type.class))); + tmpMap.put(_Fields.SORT_KEY_FILTER_PATTERN, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("sort_key_filter_pattern", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_get_request.class, metaDataMap); + } + + public multi_get_request() { + } + + public multi_get_request( + com.xiaomi.infra.pegasus.base.blob hash_key, + java.util.List sork_keys, + int max_kv_count, + int max_kv_size, + boolean no_value, + com.xiaomi.infra.pegasus.base.blob start_sortkey, + com.xiaomi.infra.pegasus.base.blob stop_sortkey, + boolean start_inclusive, + boolean stop_inclusive, + filter_type sort_key_filter_type, + com.xiaomi.infra.pegasus.base.blob sort_key_filter_pattern) + { + this(); + this.hash_key = hash_key; + this.sork_keys = sork_keys; + this.max_kv_count = max_kv_count; + setMax_kv_countIsSet(true); + this.max_kv_size = max_kv_size; + setMax_kv_sizeIsSet(true); + this.no_value = no_value; + setNo_valueIsSet(true); + this.start_sortkey = start_sortkey; + this.stop_sortkey = stop_sortkey; + this.start_inclusive = start_inclusive; + setStart_inclusiveIsSet(true); + this.stop_inclusive = stop_inclusive; + setStop_inclusiveIsSet(true); + this.sort_key_filter_type = sort_key_filter_type; + this.sort_key_filter_pattern = sort_key_filter_pattern; + } + + /** + * Performs a deep copy on other. + */ + public multi_get_request(multi_get_request other) { + __isset_bitfield = other.__isset_bitfield; + if (other.isSetHash_key()) { + this.hash_key = new com.xiaomi.infra.pegasus.base.blob(other.hash_key); + } + if (other.isSetSork_keys()) { + java.util.List __this__sork_keys = new java.util.ArrayList(other.sork_keys.size()); + for (com.xiaomi.infra.pegasus.base.blob other_element : other.sork_keys) { + __this__sork_keys.add(new com.xiaomi.infra.pegasus.base.blob(other_element)); + } + this.sork_keys = __this__sork_keys; + } + this.max_kv_count = other.max_kv_count; + this.max_kv_size = other.max_kv_size; + this.no_value = other.no_value; + if (other.isSetStart_sortkey()) { + this.start_sortkey = new com.xiaomi.infra.pegasus.base.blob(other.start_sortkey); + } + if (other.isSetStop_sortkey()) { + this.stop_sortkey = new com.xiaomi.infra.pegasus.base.blob(other.stop_sortkey); + } + this.start_inclusive = other.start_inclusive; + this.stop_inclusive = other.stop_inclusive; + if (other.isSetSort_key_filter_type()) { + this.sort_key_filter_type = other.sort_key_filter_type; + } + if (other.isSetSort_key_filter_pattern()) { + this.sort_key_filter_pattern = new com.xiaomi.infra.pegasus.base.blob(other.sort_key_filter_pattern); + } + } + + public multi_get_request deepCopy() { + return new multi_get_request(this); + } + + @Override + public void clear() { + this.hash_key = null; + this.sork_keys = null; + setMax_kv_countIsSet(false); + this.max_kv_count = 0; + setMax_kv_sizeIsSet(false); + this.max_kv_size = 0; + setNo_valueIsSet(false); + this.no_value = false; + this.start_sortkey = null; + this.stop_sortkey = null; + setStart_inclusiveIsSet(false); + this.start_inclusive = false; + setStop_inclusiveIsSet(false); + this.stop_inclusive = false; + this.sort_key_filter_type = null; + this.sort_key_filter_pattern = null; + } + + public com.xiaomi.infra.pegasus.base.blob getHash_key() { + return this.hash_key; + } + + public multi_get_request setHash_key(com.xiaomi.infra.pegasus.base.blob hash_key) { + this.hash_key = hash_key; + return this; + } + + public void unsetHash_key() { + this.hash_key = null; + } + + /** Returns true if field hash_key is set (has been assigned a value) and false otherwise */ + public boolean isSetHash_key() { + return this.hash_key != null; + } + + public void setHash_keyIsSet(boolean value) { + if (!value) { + this.hash_key = null; + } + } + + public int getSork_keysSize() { + return (this.sork_keys == null) ? 0 : this.sork_keys.size(); + } + + public java.util.Iterator getSork_keysIterator() { + return (this.sork_keys == null) ? null : this.sork_keys.iterator(); + } + + public void addToSork_keys(com.xiaomi.infra.pegasus.base.blob elem) { + if (this.sork_keys == null) { + this.sork_keys = new java.util.ArrayList(); + } + this.sork_keys.add(elem); + } + + public java.util.List getSork_keys() { + return this.sork_keys; + } + + public multi_get_request setSork_keys(java.util.List sork_keys) { + this.sork_keys = sork_keys; + return this; + } + + public void unsetSork_keys() { + this.sork_keys = null; + } + + /** Returns true if field sork_keys is set (has been assigned a value) and false otherwise */ + public boolean isSetSork_keys() { + return this.sork_keys != null; + } + + public void setSork_keysIsSet(boolean value) { + if (!value) { + this.sork_keys = null; + } + } + + public int getMax_kv_count() { + return this.max_kv_count; + } + + public multi_get_request setMax_kv_count(int max_kv_count) { + this.max_kv_count = max_kv_count; + setMax_kv_countIsSet(true); + return this; + } + + public void unsetMax_kv_count() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __MAX_KV_COUNT_ISSET_ID); + } + + /** Returns true if field max_kv_count is set (has been assigned a value) and false otherwise */ + public boolean isSetMax_kv_count() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __MAX_KV_COUNT_ISSET_ID); + } + + public void setMax_kv_countIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __MAX_KV_COUNT_ISSET_ID, value); + } + + public int getMax_kv_size() { + return this.max_kv_size; + } + + public multi_get_request setMax_kv_size(int max_kv_size) { + this.max_kv_size = max_kv_size; + setMax_kv_sizeIsSet(true); + return this; + } + + public void unsetMax_kv_size() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __MAX_KV_SIZE_ISSET_ID); + } + + /** Returns true if field max_kv_size is set (has been assigned a value) and false otherwise */ + public boolean isSetMax_kv_size() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __MAX_KV_SIZE_ISSET_ID); + } + + public void setMax_kv_sizeIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __MAX_KV_SIZE_ISSET_ID, value); + } + + public boolean isNo_value() { + return this.no_value; + } + + public multi_get_request setNo_value(boolean no_value) { + this.no_value = no_value; + setNo_valueIsSet(true); + return this; + } + + public void unsetNo_value() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __NO_VALUE_ISSET_ID); + } + + /** Returns true if field no_value is set (has been assigned a value) and false otherwise */ + public boolean isSetNo_value() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __NO_VALUE_ISSET_ID); + } + + public void setNo_valueIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __NO_VALUE_ISSET_ID, value); + } + + public com.xiaomi.infra.pegasus.base.blob getStart_sortkey() { + return this.start_sortkey; + } + + public multi_get_request setStart_sortkey(com.xiaomi.infra.pegasus.base.blob start_sortkey) { + this.start_sortkey = start_sortkey; + return this; + } + + public void unsetStart_sortkey() { + this.start_sortkey = null; + } + + /** Returns true if field start_sortkey is set (has been assigned a value) and false otherwise */ + public boolean isSetStart_sortkey() { + return this.start_sortkey != null; + } + + public void setStart_sortkeyIsSet(boolean value) { + if (!value) { + this.start_sortkey = null; + } + } + + public com.xiaomi.infra.pegasus.base.blob getStop_sortkey() { + return this.stop_sortkey; + } + + public multi_get_request setStop_sortkey(com.xiaomi.infra.pegasus.base.blob stop_sortkey) { + this.stop_sortkey = stop_sortkey; + return this; + } + + public void unsetStop_sortkey() { + this.stop_sortkey = null; + } + + /** Returns true if field stop_sortkey is set (has been assigned a value) and false otherwise */ + public boolean isSetStop_sortkey() { + return this.stop_sortkey != null; + } + + public void setStop_sortkeyIsSet(boolean value) { + if (!value) { + this.stop_sortkey = null; + } + } + + public boolean isStart_inclusive() { + return this.start_inclusive; + } + + public multi_get_request setStart_inclusive(boolean start_inclusive) { + this.start_inclusive = start_inclusive; + setStart_inclusiveIsSet(true); + return this; + } + + public void unsetStart_inclusive() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __START_INCLUSIVE_ISSET_ID); + } + + /** Returns true if field start_inclusive is set (has been assigned a value) and false otherwise */ + public boolean isSetStart_inclusive() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __START_INCLUSIVE_ISSET_ID); + } + + public void setStart_inclusiveIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __START_INCLUSIVE_ISSET_ID, value); + } + + public boolean isStop_inclusive() { + return this.stop_inclusive; + } + + public multi_get_request setStop_inclusive(boolean stop_inclusive) { + this.stop_inclusive = stop_inclusive; + setStop_inclusiveIsSet(true); + return this; + } + + public void unsetStop_inclusive() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __STOP_INCLUSIVE_ISSET_ID); + } + + /** Returns true if field stop_inclusive is set (has been assigned a value) and false otherwise */ + public boolean isSetStop_inclusive() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __STOP_INCLUSIVE_ISSET_ID); + } + + public void setStop_inclusiveIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __STOP_INCLUSIVE_ISSET_ID, value); + } + + /** + * + * @see filter_type + */ + public filter_type getSort_key_filter_type() { + return this.sort_key_filter_type; + } + + /** + * + * @see filter_type + */ + public multi_get_request setSort_key_filter_type(filter_type sort_key_filter_type) { + this.sort_key_filter_type = sort_key_filter_type; + return this; + } + + public void unsetSort_key_filter_type() { + this.sort_key_filter_type = null; + } + + /** Returns true if field sort_key_filter_type is set (has been assigned a value) and false otherwise */ + public boolean isSetSort_key_filter_type() { + return this.sort_key_filter_type != null; + } + + public void setSort_key_filter_typeIsSet(boolean value) { + if (!value) { + this.sort_key_filter_type = null; + } + } + + public com.xiaomi.infra.pegasus.base.blob getSort_key_filter_pattern() { + return this.sort_key_filter_pattern; + } + + public multi_get_request setSort_key_filter_pattern(com.xiaomi.infra.pegasus.base.blob sort_key_filter_pattern) { + this.sort_key_filter_pattern = sort_key_filter_pattern; + return this; + } + + public void unsetSort_key_filter_pattern() { + this.sort_key_filter_pattern = null; + } + + /** Returns true if field sort_key_filter_pattern is set (has been assigned a value) and false otherwise */ + public boolean isSetSort_key_filter_pattern() { + return this.sort_key_filter_pattern != null; + } + + public void setSort_key_filter_patternIsSet(boolean value) { + if (!value) { + this.sort_key_filter_pattern = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case HASH_KEY: + if (value == null) { + unsetHash_key(); + } else { + setHash_key((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case SORK_KEYS: + if (value == null) { + unsetSork_keys(); + } else { + setSork_keys((java.util.List)value); + } + break; + + case MAX_KV_COUNT: + if (value == null) { + unsetMax_kv_count(); + } else { + setMax_kv_count((java.lang.Integer)value); + } + break; + + case MAX_KV_SIZE: + if (value == null) { + unsetMax_kv_size(); + } else { + setMax_kv_size((java.lang.Integer)value); + } + break; + + case NO_VALUE: + if (value == null) { + unsetNo_value(); + } else { + setNo_value((java.lang.Boolean)value); + } + break; + + case START_SORTKEY: + if (value == null) { + unsetStart_sortkey(); + } else { + setStart_sortkey((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case STOP_SORTKEY: + if (value == null) { + unsetStop_sortkey(); + } else { + setStop_sortkey((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case START_INCLUSIVE: + if (value == null) { + unsetStart_inclusive(); + } else { + setStart_inclusive((java.lang.Boolean)value); + } + break; + + case STOP_INCLUSIVE: + if (value == null) { + unsetStop_inclusive(); + } else { + setStop_inclusive((java.lang.Boolean)value); + } + break; + + case SORT_KEY_FILTER_TYPE: + if (value == null) { + unsetSort_key_filter_type(); + } else { + setSort_key_filter_type((filter_type)value); + } + break; + + case SORT_KEY_FILTER_PATTERN: + if (value == null) { + unsetSort_key_filter_pattern(); + } else { + setSort_key_filter_pattern((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case HASH_KEY: + return getHash_key(); + + case SORK_KEYS: + return getSork_keys(); + + case MAX_KV_COUNT: + return getMax_kv_count(); + + case MAX_KV_SIZE: + return getMax_kv_size(); + + case NO_VALUE: + return isNo_value(); + + case START_SORTKEY: + return getStart_sortkey(); + + case STOP_SORTKEY: + return getStop_sortkey(); + + case START_INCLUSIVE: + return isStart_inclusive(); + + case STOP_INCLUSIVE: + return isStop_inclusive(); + + case SORT_KEY_FILTER_TYPE: + return getSort_key_filter_type(); + + case SORT_KEY_FILTER_PATTERN: + return getSort_key_filter_pattern(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case HASH_KEY: + return isSetHash_key(); + case SORK_KEYS: + return isSetSork_keys(); + case MAX_KV_COUNT: + return isSetMax_kv_count(); + case MAX_KV_SIZE: + return isSetMax_kv_size(); + case NO_VALUE: + return isSetNo_value(); + case START_SORTKEY: + return isSetStart_sortkey(); + case STOP_SORTKEY: + return isSetStop_sortkey(); + case START_INCLUSIVE: + return isSetStart_inclusive(); + case STOP_INCLUSIVE: + return isSetStop_inclusive(); + case SORT_KEY_FILTER_TYPE: + return isSetSort_key_filter_type(); + case SORT_KEY_FILTER_PATTERN: + return isSetSort_key_filter_pattern(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_get_request) + return this.equals((multi_get_request)that); + return false; + } + + public boolean equals(multi_get_request that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_hash_key = true && this.isSetHash_key(); + boolean that_present_hash_key = true && that.isSetHash_key(); + if (this_present_hash_key || that_present_hash_key) { + if (!(this_present_hash_key && that_present_hash_key)) + return false; + if (!this.hash_key.equals(that.hash_key)) + return false; + } + + boolean this_present_sork_keys = true && this.isSetSork_keys(); + boolean that_present_sork_keys = true && that.isSetSork_keys(); + if (this_present_sork_keys || that_present_sork_keys) { + if (!(this_present_sork_keys && that_present_sork_keys)) + return false; + if (!this.sork_keys.equals(that.sork_keys)) + return false; + } + + boolean this_present_max_kv_count = true; + boolean that_present_max_kv_count = true; + if (this_present_max_kv_count || that_present_max_kv_count) { + if (!(this_present_max_kv_count && that_present_max_kv_count)) + return false; + if (this.max_kv_count != that.max_kv_count) + return false; + } + + boolean this_present_max_kv_size = true; + boolean that_present_max_kv_size = true; + if (this_present_max_kv_size || that_present_max_kv_size) { + if (!(this_present_max_kv_size && that_present_max_kv_size)) + return false; + if (this.max_kv_size != that.max_kv_size) + return false; + } + + boolean this_present_no_value = true; + boolean that_present_no_value = true; + if (this_present_no_value || that_present_no_value) { + if (!(this_present_no_value && that_present_no_value)) + return false; + if (this.no_value != that.no_value) + return false; + } + + boolean this_present_start_sortkey = true && this.isSetStart_sortkey(); + boolean that_present_start_sortkey = true && that.isSetStart_sortkey(); + if (this_present_start_sortkey || that_present_start_sortkey) { + if (!(this_present_start_sortkey && that_present_start_sortkey)) + return false; + if (!this.start_sortkey.equals(that.start_sortkey)) + return false; + } + + boolean this_present_stop_sortkey = true && this.isSetStop_sortkey(); + boolean that_present_stop_sortkey = true && that.isSetStop_sortkey(); + if (this_present_stop_sortkey || that_present_stop_sortkey) { + if (!(this_present_stop_sortkey && that_present_stop_sortkey)) + return false; + if (!this.stop_sortkey.equals(that.stop_sortkey)) + return false; + } + + boolean this_present_start_inclusive = true; + boolean that_present_start_inclusive = true; + if (this_present_start_inclusive || that_present_start_inclusive) { + if (!(this_present_start_inclusive && that_present_start_inclusive)) + return false; + if (this.start_inclusive != that.start_inclusive) + return false; + } + + boolean this_present_stop_inclusive = true; + boolean that_present_stop_inclusive = true; + if (this_present_stop_inclusive || that_present_stop_inclusive) { + if (!(this_present_stop_inclusive && that_present_stop_inclusive)) + return false; + if (this.stop_inclusive != that.stop_inclusive) + return false; + } + + boolean this_present_sort_key_filter_type = true && this.isSetSort_key_filter_type(); + boolean that_present_sort_key_filter_type = true && that.isSetSort_key_filter_type(); + if (this_present_sort_key_filter_type || that_present_sort_key_filter_type) { + if (!(this_present_sort_key_filter_type && that_present_sort_key_filter_type)) + return false; + if (!this.sort_key_filter_type.equals(that.sort_key_filter_type)) + return false; + } + + boolean this_present_sort_key_filter_pattern = true && this.isSetSort_key_filter_pattern(); + boolean that_present_sort_key_filter_pattern = true && that.isSetSort_key_filter_pattern(); + if (this_present_sort_key_filter_pattern || that_present_sort_key_filter_pattern) { + if (!(this_present_sort_key_filter_pattern && that_present_sort_key_filter_pattern)) + return false; + if (!this.sort_key_filter_pattern.equals(that.sort_key_filter_pattern)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetHash_key()) ? 131071 : 524287); + if (isSetHash_key()) + hashCode = hashCode * 8191 + hash_key.hashCode(); + + hashCode = hashCode * 8191 + ((isSetSork_keys()) ? 131071 : 524287); + if (isSetSork_keys()) + hashCode = hashCode * 8191 + sork_keys.hashCode(); + + hashCode = hashCode * 8191 + max_kv_count; + + hashCode = hashCode * 8191 + max_kv_size; + + hashCode = hashCode * 8191 + ((no_value) ? 131071 : 524287); + + hashCode = hashCode * 8191 + ((isSetStart_sortkey()) ? 131071 : 524287); + if (isSetStart_sortkey()) + hashCode = hashCode * 8191 + start_sortkey.hashCode(); + + hashCode = hashCode * 8191 + ((isSetStop_sortkey()) ? 131071 : 524287); + if (isSetStop_sortkey()) + hashCode = hashCode * 8191 + stop_sortkey.hashCode(); + + hashCode = hashCode * 8191 + ((start_inclusive) ? 131071 : 524287); + + hashCode = hashCode * 8191 + ((stop_inclusive) ? 131071 : 524287); + + hashCode = hashCode * 8191 + ((isSetSort_key_filter_type()) ? 131071 : 524287); + if (isSetSort_key_filter_type()) + hashCode = hashCode * 8191 + sort_key_filter_type.getValue(); + + hashCode = hashCode * 8191 + ((isSetSort_key_filter_pattern()) ? 131071 : 524287); + if (isSetSort_key_filter_pattern()) + hashCode = hashCode * 8191 + sort_key_filter_pattern.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(multi_get_request other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetHash_key()).compareTo(other.isSetHash_key()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetHash_key()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.hash_key, other.hash_key); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetSork_keys()).compareTo(other.isSetSork_keys()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSork_keys()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.sork_keys, other.sork_keys); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetMax_kv_count()).compareTo(other.isSetMax_kv_count()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetMax_kv_count()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.max_kv_count, other.max_kv_count); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetMax_kv_size()).compareTo(other.isSetMax_kv_size()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetMax_kv_size()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.max_kv_size, other.max_kv_size); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetNo_value()).compareTo(other.isSetNo_value()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetNo_value()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.no_value, other.no_value); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetStart_sortkey()).compareTo(other.isSetStart_sortkey()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetStart_sortkey()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.start_sortkey, other.start_sortkey); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetStop_sortkey()).compareTo(other.isSetStop_sortkey()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetStop_sortkey()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.stop_sortkey, other.stop_sortkey); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetStart_inclusive()).compareTo(other.isSetStart_inclusive()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetStart_inclusive()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.start_inclusive, other.start_inclusive); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetStop_inclusive()).compareTo(other.isSetStop_inclusive()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetStop_inclusive()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.stop_inclusive, other.stop_inclusive); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetSort_key_filter_type()).compareTo(other.isSetSort_key_filter_type()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSort_key_filter_type()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.sort_key_filter_type, other.sort_key_filter_type); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetSort_key_filter_pattern()).compareTo(other.isSetSort_key_filter_pattern()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSort_key_filter_pattern()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.sort_key_filter_pattern, other.sort_key_filter_pattern); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_get_request("); + boolean first = true; + + sb.append("hash_key:"); + if (this.hash_key == null) { + sb.append("null"); + } else { + sb.append(this.hash_key); + } + first = false; + if (!first) sb.append(", "); + sb.append("sork_keys:"); + if (this.sork_keys == null) { + sb.append("null"); + } else { + sb.append(this.sork_keys); + } + first = false; + if (!first) sb.append(", "); + sb.append("max_kv_count:"); + sb.append(this.max_kv_count); + first = false; + if (!first) sb.append(", "); + sb.append("max_kv_size:"); + sb.append(this.max_kv_size); + first = false; + if (!first) sb.append(", "); + sb.append("no_value:"); + sb.append(this.no_value); + first = false; + if (!first) sb.append(", "); + sb.append("start_sortkey:"); + if (this.start_sortkey == null) { + sb.append("null"); + } else { + sb.append(this.start_sortkey); + } + first = false; + if (!first) sb.append(", "); + sb.append("stop_sortkey:"); + if (this.stop_sortkey == null) { + sb.append("null"); + } else { + sb.append(this.stop_sortkey); + } + first = false; + if (!first) sb.append(", "); + sb.append("start_inclusive:"); + sb.append(this.start_inclusive); + first = false; + if (!first) sb.append(", "); + sb.append("stop_inclusive:"); + sb.append(this.stop_inclusive); + first = false; + if (!first) sb.append(", "); + sb.append("sort_key_filter_type:"); + if (this.sort_key_filter_type == null) { + sb.append("null"); + } else { + sb.append(this.sort_key_filter_type); + } + first = false; + if (!first) sb.append(", "); + sb.append("sort_key_filter_pattern:"); + if (this.sort_key_filter_pattern == null) { + sb.append("null"); + } else { + sb.append(this.sort_key_filter_pattern); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (hash_key != null) { + hash_key.validate(); + } + if (start_sortkey != null) { + start_sortkey.validate(); + } + if (stop_sortkey != null) { + stop_sortkey.validate(); + } + if (sort_key_filter_pattern != null) { + sort_key_filter_pattern.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_get_requestStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_get_requestStandardScheme getScheme() { + return new multi_get_requestStandardScheme(); + } + } + + private static class multi_get_requestStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_get_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // HASH_KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.hash_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.hash_key.read(iprot); + struct.setHash_keyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // SORK_KEYS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list16 = iprot.readListBegin(); + struct.sork_keys = new java.util.ArrayList(_list16.size); + com.xiaomi.infra.pegasus.base.blob _elem17; + for (int _i18 = 0; _i18 < _list16.size; ++_i18) + { + _elem17 = new com.xiaomi.infra.pegasus.base.blob(); + _elem17.read(iprot); + struct.sork_keys.add(_elem17); + } + iprot.readListEnd(); + } + struct.setSork_keysIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // MAX_KV_COUNT + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.max_kv_count = iprot.readI32(); + struct.setMax_kv_countIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // MAX_KV_SIZE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.max_kv_size = iprot.readI32(); + struct.setMax_kv_sizeIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 5: // NO_VALUE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL) { + struct.no_value = iprot.readBool(); + struct.setNo_valueIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 6: // START_SORTKEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.start_sortkey = new com.xiaomi.infra.pegasus.base.blob(); + struct.start_sortkey.read(iprot); + struct.setStart_sortkeyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 7: // STOP_SORTKEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.stop_sortkey = new com.xiaomi.infra.pegasus.base.blob(); + struct.stop_sortkey.read(iprot); + struct.setStop_sortkeyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 8: // START_INCLUSIVE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL) { + struct.start_inclusive = iprot.readBool(); + struct.setStart_inclusiveIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 9: // STOP_INCLUSIVE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL) { + struct.stop_inclusive = iprot.readBool(); + struct.setStop_inclusiveIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 10: // SORT_KEY_FILTER_TYPE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.sort_key_filter_type = com.xiaomi.infra.pegasus.apps.filter_type.findByValue(iprot.readI32()); + struct.setSort_key_filter_typeIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 11: // SORT_KEY_FILTER_PATTERN + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.sort_key_filter_pattern = new com.xiaomi.infra.pegasus.base.blob(); + struct.sort_key_filter_pattern.read(iprot); + struct.setSort_key_filter_patternIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_get_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.hash_key != null) { + oprot.writeFieldBegin(HASH_KEY_FIELD_DESC); + struct.hash_key.write(oprot); + oprot.writeFieldEnd(); + } + if (struct.sork_keys != null) { + oprot.writeFieldBegin(SORK_KEYS_FIELD_DESC); + { + oprot.writeListBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, struct.sork_keys.size())); + for (com.xiaomi.infra.pegasus.base.blob _iter19 : struct.sork_keys) + { + _iter19.write(oprot); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(MAX_KV_COUNT_FIELD_DESC); + oprot.writeI32(struct.max_kv_count); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(MAX_KV_SIZE_FIELD_DESC); + oprot.writeI32(struct.max_kv_size); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(NO_VALUE_FIELD_DESC); + oprot.writeBool(struct.no_value); + oprot.writeFieldEnd(); + if (struct.start_sortkey != null) { + oprot.writeFieldBegin(START_SORTKEY_FIELD_DESC); + struct.start_sortkey.write(oprot); + oprot.writeFieldEnd(); + } + if (struct.stop_sortkey != null) { + oprot.writeFieldBegin(STOP_SORTKEY_FIELD_DESC); + struct.stop_sortkey.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(START_INCLUSIVE_FIELD_DESC); + oprot.writeBool(struct.start_inclusive); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(STOP_INCLUSIVE_FIELD_DESC); + oprot.writeBool(struct.stop_inclusive); + oprot.writeFieldEnd(); + if (struct.sort_key_filter_type != null) { + oprot.writeFieldBegin(SORT_KEY_FILTER_TYPE_FIELD_DESC); + oprot.writeI32(struct.sort_key_filter_type.getValue()); + oprot.writeFieldEnd(); + } + if (struct.sort_key_filter_pattern != null) { + oprot.writeFieldBegin(SORT_KEY_FILTER_PATTERN_FIELD_DESC); + struct.sort_key_filter_pattern.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_get_requestTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_get_requestTupleScheme getScheme() { + return new multi_get_requestTupleScheme(); + } + } + + private static class multi_get_requestTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_get_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetHash_key()) { + optionals.set(0); + } + if (struct.isSetSork_keys()) { + optionals.set(1); + } + if (struct.isSetMax_kv_count()) { + optionals.set(2); + } + if (struct.isSetMax_kv_size()) { + optionals.set(3); + } + if (struct.isSetNo_value()) { + optionals.set(4); + } + if (struct.isSetStart_sortkey()) { + optionals.set(5); + } + if (struct.isSetStop_sortkey()) { + optionals.set(6); + } + if (struct.isSetStart_inclusive()) { + optionals.set(7); + } + if (struct.isSetStop_inclusive()) { + optionals.set(8); + } + if (struct.isSetSort_key_filter_type()) { + optionals.set(9); + } + if (struct.isSetSort_key_filter_pattern()) { + optionals.set(10); + } + oprot.writeBitSet(optionals, 11); + if (struct.isSetHash_key()) { + struct.hash_key.write(oprot); + } + if (struct.isSetSork_keys()) { + { + oprot.writeI32(struct.sork_keys.size()); + for (com.xiaomi.infra.pegasus.base.blob _iter20 : struct.sork_keys) + { + _iter20.write(oprot); + } + } + } + if (struct.isSetMax_kv_count()) { + oprot.writeI32(struct.max_kv_count); + } + if (struct.isSetMax_kv_size()) { + oprot.writeI32(struct.max_kv_size); + } + if (struct.isSetNo_value()) { + oprot.writeBool(struct.no_value); + } + if (struct.isSetStart_sortkey()) { + struct.start_sortkey.write(oprot); + } + if (struct.isSetStop_sortkey()) { + struct.stop_sortkey.write(oprot); + } + if (struct.isSetStart_inclusive()) { + oprot.writeBool(struct.start_inclusive); + } + if (struct.isSetStop_inclusive()) { + oprot.writeBool(struct.stop_inclusive); + } + if (struct.isSetSort_key_filter_type()) { + oprot.writeI32(struct.sort_key_filter_type.getValue()); + } + if (struct.isSetSort_key_filter_pattern()) { + struct.sort_key_filter_pattern.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_get_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(11); + if (incoming.get(0)) { + struct.hash_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.hash_key.read(iprot); + struct.setHash_keyIsSet(true); + } + if (incoming.get(1)) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list21 = new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, iprot.readI32()); + struct.sork_keys = new java.util.ArrayList(_list21.size); + com.xiaomi.infra.pegasus.base.blob _elem22; + for (int _i23 = 0; _i23 < _list21.size; ++_i23) + { + _elem22 = new com.xiaomi.infra.pegasus.base.blob(); + _elem22.read(iprot); + struct.sork_keys.add(_elem22); + } + } + struct.setSork_keysIsSet(true); + } + if (incoming.get(2)) { + struct.max_kv_count = iprot.readI32(); + struct.setMax_kv_countIsSet(true); + } + if (incoming.get(3)) { + struct.max_kv_size = iprot.readI32(); + struct.setMax_kv_sizeIsSet(true); + } + if (incoming.get(4)) { + struct.no_value = iprot.readBool(); + struct.setNo_valueIsSet(true); + } + if (incoming.get(5)) { + struct.start_sortkey = new com.xiaomi.infra.pegasus.base.blob(); + struct.start_sortkey.read(iprot); + struct.setStart_sortkeyIsSet(true); + } + if (incoming.get(6)) { + struct.stop_sortkey = new com.xiaomi.infra.pegasus.base.blob(); + struct.stop_sortkey.read(iprot); + struct.setStop_sortkeyIsSet(true); + } + if (incoming.get(7)) { + struct.start_inclusive = iprot.readBool(); + struct.setStart_inclusiveIsSet(true); + } + if (incoming.get(8)) { + struct.stop_inclusive = iprot.readBool(); + struct.setStop_inclusiveIsSet(true); + } + if (incoming.get(9)) { + struct.sort_key_filter_type = com.xiaomi.infra.pegasus.apps.filter_type.findByValue(iprot.readI32()); + struct.setSort_key_filter_typeIsSet(true); + } + if (incoming.get(10)) { + struct.sort_key_filter_pattern = new com.xiaomi.infra.pegasus.base.blob(); + struct.sort_key_filter_pattern.read(iprot); + struct.setSort_key_filter_patternIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/multi_get_response.java b/src/main/java/com/xiaomi/infra/pegasus/apps/multi_get_response.java new file mode 100644 index 00000000..4a62aa8d --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/multi_get_response.java @@ -0,0 +1,825 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class multi_get_response implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_get_response"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField ERROR_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("error", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField KVS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("kvs", com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField APP_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("app_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PARTITION_INDEX_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("partition_index", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SERVER_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("server", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING, (short)6); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_get_responseStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_get_responseTupleSchemeFactory(); + + public int error; // required + public java.util.List kvs; // required + public int app_id; // required + public int partition_index; // required + public java.lang.String server; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + ERROR((short)1, "error"), + KVS((short)2, "kvs"), + APP_ID((short)3, "app_id"), + PARTITION_INDEX((short)4, "partition_index"), + SERVER((short)6, "server"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // ERROR + return ERROR; + case 2: // KVS + return KVS; + case 3: // APP_ID + return APP_ID; + case 4: // PARTITION_INDEX + return PARTITION_INDEX; + case 6: // SERVER + return SERVER; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __ERROR_ISSET_ID = 0; + private static final int __APP_ID_ISSET_ID = 1; + private static final int __PARTITION_INDEX_ISSET_ID = 2; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.ERROR, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("error", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.KVS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("kvs", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.ListMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, key_value.class)))); + tmpMap.put(_Fields.APP_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("app_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.PARTITION_INDEX, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("partition_index", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.SERVER, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("server", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_get_response.class, metaDataMap); + } + + public multi_get_response() { + } + + public multi_get_response( + int error, + java.util.List kvs, + int app_id, + int partition_index, + java.lang.String server) + { + this(); + this.error = error; + setErrorIsSet(true); + this.kvs = kvs; + this.app_id = app_id; + setApp_idIsSet(true); + this.partition_index = partition_index; + setPartition_indexIsSet(true); + this.server = server; + } + + /** + * Performs a deep copy on other. + */ + public multi_get_response(multi_get_response other) { + __isset_bitfield = other.__isset_bitfield; + this.error = other.error; + if (other.isSetKvs()) { + java.util.List __this__kvs = new java.util.ArrayList(other.kvs.size()); + for (key_value other_element : other.kvs) { + __this__kvs.add(new key_value(other_element)); + } + this.kvs = __this__kvs; + } + this.app_id = other.app_id; + this.partition_index = other.partition_index; + if (other.isSetServer()) { + this.server = other.server; + } + } + + public multi_get_response deepCopy() { + return new multi_get_response(this); + } + + @Override + public void clear() { + setErrorIsSet(false); + this.error = 0; + this.kvs = null; + setApp_idIsSet(false); + this.app_id = 0; + setPartition_indexIsSet(false); + this.partition_index = 0; + this.server = null; + } + + public int getError() { + return this.error; + } + + public multi_get_response setError(int error) { + this.error = error; + setErrorIsSet(true); + return this; + } + + public void unsetError() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + /** Returns true if field error is set (has been assigned a value) and false otherwise */ + public boolean isSetError() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + public void setErrorIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __ERROR_ISSET_ID, value); + } + + public int getKvsSize() { + return (this.kvs == null) ? 0 : this.kvs.size(); + } + + public java.util.Iterator getKvsIterator() { + return (this.kvs == null) ? null : this.kvs.iterator(); + } + + public void addToKvs(key_value elem) { + if (this.kvs == null) { + this.kvs = new java.util.ArrayList(); + } + this.kvs.add(elem); + } + + public java.util.List getKvs() { + return this.kvs; + } + + public multi_get_response setKvs(java.util.List kvs) { + this.kvs = kvs; + return this; + } + + public void unsetKvs() { + this.kvs = null; + } + + /** Returns true if field kvs is set (has been assigned a value) and false otherwise */ + public boolean isSetKvs() { + return this.kvs != null; + } + + public void setKvsIsSet(boolean value) { + if (!value) { + this.kvs = null; + } + } + + public int getApp_id() { + return this.app_id; + } + + public multi_get_response setApp_id(int app_id) { + this.app_id = app_id; + setApp_idIsSet(true); + return this; + } + + public void unsetApp_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + /** Returns true if field app_id is set (has been assigned a value) and false otherwise */ + public boolean isSetApp_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + public void setApp_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __APP_ID_ISSET_ID, value); + } + + public int getPartition_index() { + return this.partition_index; + } + + public multi_get_response setPartition_index(int partition_index) { + this.partition_index = partition_index; + setPartition_indexIsSet(true); + return this; + } + + public void unsetPartition_index() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + /** Returns true if field partition_index is set (has been assigned a value) and false otherwise */ + public boolean isSetPartition_index() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + public void setPartition_indexIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID, value); + } + + public java.lang.String getServer() { + return this.server; + } + + public multi_get_response setServer(java.lang.String server) { + this.server = server; + return this; + } + + public void unsetServer() { + this.server = null; + } + + /** Returns true if field server is set (has been assigned a value) and false otherwise */ + public boolean isSetServer() { + return this.server != null; + } + + public void setServerIsSet(boolean value) { + if (!value) { + this.server = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case ERROR: + if (value == null) { + unsetError(); + } else { + setError((java.lang.Integer)value); + } + break; + + case KVS: + if (value == null) { + unsetKvs(); + } else { + setKvs((java.util.List)value); + } + break; + + case APP_ID: + if (value == null) { + unsetApp_id(); + } else { + setApp_id((java.lang.Integer)value); + } + break; + + case PARTITION_INDEX: + if (value == null) { + unsetPartition_index(); + } else { + setPartition_index((java.lang.Integer)value); + } + break; + + case SERVER: + if (value == null) { + unsetServer(); + } else { + setServer((java.lang.String)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case ERROR: + return getError(); + + case KVS: + return getKvs(); + + case APP_ID: + return getApp_id(); + + case PARTITION_INDEX: + return getPartition_index(); + + case SERVER: + return getServer(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case ERROR: + return isSetError(); + case KVS: + return isSetKvs(); + case APP_ID: + return isSetApp_id(); + case PARTITION_INDEX: + return isSetPartition_index(); + case SERVER: + return isSetServer(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_get_response) + return this.equals((multi_get_response)that); + return false; + } + + public boolean equals(multi_get_response that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_error = true; + boolean that_present_error = true; + if (this_present_error || that_present_error) { + if (!(this_present_error && that_present_error)) + return false; + if (this.error != that.error) + return false; + } + + boolean this_present_kvs = true && this.isSetKvs(); + boolean that_present_kvs = true && that.isSetKvs(); + if (this_present_kvs || that_present_kvs) { + if (!(this_present_kvs && that_present_kvs)) + return false; + if (!this.kvs.equals(that.kvs)) + return false; + } + + boolean this_present_app_id = true; + boolean that_present_app_id = true; + if (this_present_app_id || that_present_app_id) { + if (!(this_present_app_id && that_present_app_id)) + return false; + if (this.app_id != that.app_id) + return false; + } + + boolean this_present_partition_index = true; + boolean that_present_partition_index = true; + if (this_present_partition_index || that_present_partition_index) { + if (!(this_present_partition_index && that_present_partition_index)) + return false; + if (this.partition_index != that.partition_index) + return false; + } + + boolean this_present_server = true && this.isSetServer(); + boolean that_present_server = true && that.isSetServer(); + if (this_present_server || that_present_server) { + if (!(this_present_server && that_present_server)) + return false; + if (!this.server.equals(that.server)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + error; + + hashCode = hashCode * 8191 + ((isSetKvs()) ? 131071 : 524287); + if (isSetKvs()) + hashCode = hashCode * 8191 + kvs.hashCode(); + + hashCode = hashCode * 8191 + app_id; + + hashCode = hashCode * 8191 + partition_index; + + hashCode = hashCode * 8191 + ((isSetServer()) ? 131071 : 524287); + if (isSetServer()) + hashCode = hashCode * 8191 + server.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(multi_get_response other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetError()).compareTo(other.isSetError()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetError()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.error, other.error); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetKvs()).compareTo(other.isSetKvs()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetKvs()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.kvs, other.kvs); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetApp_id()).compareTo(other.isSetApp_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetApp_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.app_id, other.app_id); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPartition_index()).compareTo(other.isSetPartition_index()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPartition_index()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.partition_index, other.partition_index); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetServer()).compareTo(other.isSetServer()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetServer()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.server, other.server); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_get_response("); + boolean first = true; + + sb.append("error:"); + sb.append(this.error); + first = false; + if (!first) sb.append(", "); + sb.append("kvs:"); + if (this.kvs == null) { + sb.append("null"); + } else { + sb.append(this.kvs); + } + first = false; + if (!first) sb.append(", "); + sb.append("app_id:"); + sb.append(this.app_id); + first = false; + if (!first) sb.append(", "); + sb.append("partition_index:"); + sb.append(this.partition_index); + first = false; + if (!first) sb.append(", "); + sb.append("server:"); + if (this.server == null) { + sb.append("null"); + } else { + sb.append(this.server); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_get_responseStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_get_responseStandardScheme getScheme() { + return new multi_get_responseStandardScheme(); + } + } + + private static class multi_get_responseStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_get_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // ERROR + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // KVS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list24 = iprot.readListBegin(); + struct.kvs = new java.util.ArrayList(_list24.size); + key_value _elem25; + for (int _i26 = 0; _i26 < _list24.size; ++_i26) + { + _elem25 = new key_value(); + _elem25.read(iprot); + struct.kvs.add(_elem25); + } + iprot.readListEnd(); + } + struct.setKvsIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // APP_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // PARTITION_INDEX + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 6: // SERVER + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_get_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldBegin(ERROR_FIELD_DESC); + oprot.writeI32(struct.error); + oprot.writeFieldEnd(); + if (struct.kvs != null) { + oprot.writeFieldBegin(KVS_FIELD_DESC); + { + oprot.writeListBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, struct.kvs.size())); + for (key_value _iter27 : struct.kvs) + { + _iter27.write(oprot); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(APP_ID_FIELD_DESC); + oprot.writeI32(struct.app_id); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(PARTITION_INDEX_FIELD_DESC); + oprot.writeI32(struct.partition_index); + oprot.writeFieldEnd(); + if (struct.server != null) { + oprot.writeFieldBegin(SERVER_FIELD_DESC); + oprot.writeString(struct.server); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_get_responseTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_get_responseTupleScheme getScheme() { + return new multi_get_responseTupleScheme(); + } + } + + private static class multi_get_responseTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_get_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetError()) { + optionals.set(0); + } + if (struct.isSetKvs()) { + optionals.set(1); + } + if (struct.isSetApp_id()) { + optionals.set(2); + } + if (struct.isSetPartition_index()) { + optionals.set(3); + } + if (struct.isSetServer()) { + optionals.set(4); + } + oprot.writeBitSet(optionals, 5); + if (struct.isSetError()) { + oprot.writeI32(struct.error); + } + if (struct.isSetKvs()) { + { + oprot.writeI32(struct.kvs.size()); + for (key_value _iter28 : struct.kvs) + { + _iter28.write(oprot); + } + } + } + if (struct.isSetApp_id()) { + oprot.writeI32(struct.app_id); + } + if (struct.isSetPartition_index()) { + oprot.writeI32(struct.partition_index); + } + if (struct.isSetServer()) { + oprot.writeString(struct.server); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_get_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(5); + if (incoming.get(0)) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } + if (incoming.get(1)) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list29 = new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, iprot.readI32()); + struct.kvs = new java.util.ArrayList(_list29.size); + key_value _elem30; + for (int _i31 = 0; _i31 < _list29.size; ++_i31) + { + _elem30 = new key_value(); + _elem30.read(iprot); + struct.kvs.add(_elem30); + } + } + struct.setKvsIsSet(true); + } + if (incoming.get(2)) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } + if (incoming.get(3)) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } + if (incoming.get(4)) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/multi_put_request.java b/src/main/java/com/xiaomi/infra/pegasus/apps/multi_put_request.java new file mode 100644 index 00000000..e6b22965 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/multi_put_request.java @@ -0,0 +1,638 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class multi_put_request implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_put_request"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField HASH_KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("hash_key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField KVS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("kvs", com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField EXPIRE_TS_SECONDS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("expire_ts_seconds", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_put_requestStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_put_requestTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.blob hash_key; // required + public java.util.List kvs; // required + public int expire_ts_seconds; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + HASH_KEY((short)1, "hash_key"), + KVS((short)2, "kvs"), + EXPIRE_TS_SECONDS((short)3, "expire_ts_seconds"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // HASH_KEY + return HASH_KEY; + case 2: // KVS + return KVS; + case 3: // EXPIRE_TS_SECONDS + return EXPIRE_TS_SECONDS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __EXPIRE_TS_SECONDS_ISSET_ID = 0; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.HASH_KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("hash_key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.KVS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("kvs", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.ListMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, key_value.class)))); + tmpMap.put(_Fields.EXPIRE_TS_SECONDS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("expire_ts_seconds", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_put_request.class, metaDataMap); + } + + public multi_put_request() { + } + + public multi_put_request( + com.xiaomi.infra.pegasus.base.blob hash_key, + java.util.List kvs, + int expire_ts_seconds) + { + this(); + this.hash_key = hash_key; + this.kvs = kvs; + this.expire_ts_seconds = expire_ts_seconds; + setExpire_ts_secondsIsSet(true); + } + + /** + * Performs a deep copy on other. + */ + public multi_put_request(multi_put_request other) { + __isset_bitfield = other.__isset_bitfield; + if (other.isSetHash_key()) { + this.hash_key = new com.xiaomi.infra.pegasus.base.blob(other.hash_key); + } + if (other.isSetKvs()) { + java.util.List __this__kvs = new java.util.ArrayList(other.kvs.size()); + for (key_value other_element : other.kvs) { + __this__kvs.add(new key_value(other_element)); + } + this.kvs = __this__kvs; + } + this.expire_ts_seconds = other.expire_ts_seconds; + } + + public multi_put_request deepCopy() { + return new multi_put_request(this); + } + + @Override + public void clear() { + this.hash_key = null; + this.kvs = null; + setExpire_ts_secondsIsSet(false); + this.expire_ts_seconds = 0; + } + + public com.xiaomi.infra.pegasus.base.blob getHash_key() { + return this.hash_key; + } + + public multi_put_request setHash_key(com.xiaomi.infra.pegasus.base.blob hash_key) { + this.hash_key = hash_key; + return this; + } + + public void unsetHash_key() { + this.hash_key = null; + } + + /** Returns true if field hash_key is set (has been assigned a value) and false otherwise */ + public boolean isSetHash_key() { + return this.hash_key != null; + } + + public void setHash_keyIsSet(boolean value) { + if (!value) { + this.hash_key = null; + } + } + + public int getKvsSize() { + return (this.kvs == null) ? 0 : this.kvs.size(); + } + + public java.util.Iterator getKvsIterator() { + return (this.kvs == null) ? null : this.kvs.iterator(); + } + + public void addToKvs(key_value elem) { + if (this.kvs == null) { + this.kvs = new java.util.ArrayList(); + } + this.kvs.add(elem); + } + + public java.util.List getKvs() { + return this.kvs; + } + + public multi_put_request setKvs(java.util.List kvs) { + this.kvs = kvs; + return this; + } + + public void unsetKvs() { + this.kvs = null; + } + + /** Returns true if field kvs is set (has been assigned a value) and false otherwise */ + public boolean isSetKvs() { + return this.kvs != null; + } + + public void setKvsIsSet(boolean value) { + if (!value) { + this.kvs = null; + } + } + + public int getExpire_ts_seconds() { + return this.expire_ts_seconds; + } + + public multi_put_request setExpire_ts_seconds(int expire_ts_seconds) { + this.expire_ts_seconds = expire_ts_seconds; + setExpire_ts_secondsIsSet(true); + return this; + } + + public void unsetExpire_ts_seconds() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __EXPIRE_TS_SECONDS_ISSET_ID); + } + + /** Returns true if field expire_ts_seconds is set (has been assigned a value) and false otherwise */ + public boolean isSetExpire_ts_seconds() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __EXPIRE_TS_SECONDS_ISSET_ID); + } + + public void setExpire_ts_secondsIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __EXPIRE_TS_SECONDS_ISSET_ID, value); + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case HASH_KEY: + if (value == null) { + unsetHash_key(); + } else { + setHash_key((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case KVS: + if (value == null) { + unsetKvs(); + } else { + setKvs((java.util.List)value); + } + break; + + case EXPIRE_TS_SECONDS: + if (value == null) { + unsetExpire_ts_seconds(); + } else { + setExpire_ts_seconds((java.lang.Integer)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case HASH_KEY: + return getHash_key(); + + case KVS: + return getKvs(); + + case EXPIRE_TS_SECONDS: + return getExpire_ts_seconds(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case HASH_KEY: + return isSetHash_key(); + case KVS: + return isSetKvs(); + case EXPIRE_TS_SECONDS: + return isSetExpire_ts_seconds(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_put_request) + return this.equals((multi_put_request)that); + return false; + } + + public boolean equals(multi_put_request that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_hash_key = true && this.isSetHash_key(); + boolean that_present_hash_key = true && that.isSetHash_key(); + if (this_present_hash_key || that_present_hash_key) { + if (!(this_present_hash_key && that_present_hash_key)) + return false; + if (!this.hash_key.equals(that.hash_key)) + return false; + } + + boolean this_present_kvs = true && this.isSetKvs(); + boolean that_present_kvs = true && that.isSetKvs(); + if (this_present_kvs || that_present_kvs) { + if (!(this_present_kvs && that_present_kvs)) + return false; + if (!this.kvs.equals(that.kvs)) + return false; + } + + boolean this_present_expire_ts_seconds = true; + boolean that_present_expire_ts_seconds = true; + if (this_present_expire_ts_seconds || that_present_expire_ts_seconds) { + if (!(this_present_expire_ts_seconds && that_present_expire_ts_seconds)) + return false; + if (this.expire_ts_seconds != that.expire_ts_seconds) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetHash_key()) ? 131071 : 524287); + if (isSetHash_key()) + hashCode = hashCode * 8191 + hash_key.hashCode(); + + hashCode = hashCode * 8191 + ((isSetKvs()) ? 131071 : 524287); + if (isSetKvs()) + hashCode = hashCode * 8191 + kvs.hashCode(); + + hashCode = hashCode * 8191 + expire_ts_seconds; + + return hashCode; + } + + @Override + public int compareTo(multi_put_request other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetHash_key()).compareTo(other.isSetHash_key()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetHash_key()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.hash_key, other.hash_key); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetKvs()).compareTo(other.isSetKvs()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetKvs()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.kvs, other.kvs); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetExpire_ts_seconds()).compareTo(other.isSetExpire_ts_seconds()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetExpire_ts_seconds()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.expire_ts_seconds, other.expire_ts_seconds); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_put_request("); + boolean first = true; + + sb.append("hash_key:"); + if (this.hash_key == null) { + sb.append("null"); + } else { + sb.append(this.hash_key); + } + first = false; + if (!first) sb.append(", "); + sb.append("kvs:"); + if (this.kvs == null) { + sb.append("null"); + } else { + sb.append(this.kvs); + } + first = false; + if (!first) sb.append(", "); + sb.append("expire_ts_seconds:"); + sb.append(this.expire_ts_seconds); + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (hash_key != null) { + hash_key.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_put_requestStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_put_requestStandardScheme getScheme() { + return new multi_put_requestStandardScheme(); + } + } + + private static class multi_put_requestStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_put_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // HASH_KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.hash_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.hash_key.read(iprot); + struct.setHash_keyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // KVS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list0 = iprot.readListBegin(); + struct.kvs = new java.util.ArrayList(_list0.size); + key_value _elem1; + for (int _i2 = 0; _i2 < _list0.size; ++_i2) + { + _elem1 = new key_value(); + _elem1.read(iprot); + struct.kvs.add(_elem1); + } + iprot.readListEnd(); + } + struct.setKvsIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // EXPIRE_TS_SECONDS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.expire_ts_seconds = iprot.readI32(); + struct.setExpire_ts_secondsIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_put_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.hash_key != null) { + oprot.writeFieldBegin(HASH_KEY_FIELD_DESC); + struct.hash_key.write(oprot); + oprot.writeFieldEnd(); + } + if (struct.kvs != null) { + oprot.writeFieldBegin(KVS_FIELD_DESC); + { + oprot.writeListBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, struct.kvs.size())); + for (key_value _iter3 : struct.kvs) + { + _iter3.write(oprot); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(EXPIRE_TS_SECONDS_FIELD_DESC); + oprot.writeI32(struct.expire_ts_seconds); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_put_requestTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_put_requestTupleScheme getScheme() { + return new multi_put_requestTupleScheme(); + } + } + + private static class multi_put_requestTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_put_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetHash_key()) { + optionals.set(0); + } + if (struct.isSetKvs()) { + optionals.set(1); + } + if (struct.isSetExpire_ts_seconds()) { + optionals.set(2); + } + oprot.writeBitSet(optionals, 3); + if (struct.isSetHash_key()) { + struct.hash_key.write(oprot); + } + if (struct.isSetKvs()) { + { + oprot.writeI32(struct.kvs.size()); + for (key_value _iter4 : struct.kvs) + { + _iter4.write(oprot); + } + } + } + if (struct.isSetExpire_ts_seconds()) { + oprot.writeI32(struct.expire_ts_seconds); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_put_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(3); + if (incoming.get(0)) { + struct.hash_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.hash_key.read(iprot); + struct.setHash_keyIsSet(true); + } + if (incoming.get(1)) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list5 = new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, iprot.readI32()); + struct.kvs = new java.util.ArrayList(_list5.size); + key_value _elem6; + for (int _i7 = 0; _i7 < _list5.size; ++_i7) + { + _elem6 = new key_value(); + _elem6.read(iprot); + struct.kvs.add(_elem6); + } + } + struct.setKvsIsSet(true); + } + if (incoming.get(2)) { + struct.expire_ts_seconds = iprot.readI32(); + struct.setExpire_ts_secondsIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/multi_remove_request.java b/src/main/java/com/xiaomi/infra/pegasus/apps/multi_remove_request.java new file mode 100644 index 00000000..b0776c10 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/multi_remove_request.java @@ -0,0 +1,638 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class multi_remove_request implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_remove_request"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField HASH_KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("hash_key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SORK_KEYS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("sork_keys", com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField MAX_COUNT_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("max_count", com.xiaomi.infra.pegasus.thrift.protocol.TType.I64, (short)3); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_remove_requestStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_remove_requestTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.blob hash_key; // required + public java.util.List sork_keys; // required + public long max_count; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + HASH_KEY((short)1, "hash_key"), + SORK_KEYS((short)2, "sork_keys"), + MAX_COUNT((short)3, "max_count"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // HASH_KEY + return HASH_KEY; + case 2: // SORK_KEYS + return SORK_KEYS; + case 3: // MAX_COUNT + return MAX_COUNT; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __MAX_COUNT_ISSET_ID = 0; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.HASH_KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("hash_key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.SORK_KEYS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("sork_keys", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.ListMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class)))); + tmpMap.put(_Fields.MAX_COUNT, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("max_count", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I64))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_remove_request.class, metaDataMap); + } + + public multi_remove_request() { + } + + public multi_remove_request( + com.xiaomi.infra.pegasus.base.blob hash_key, + java.util.List sork_keys, + long max_count) + { + this(); + this.hash_key = hash_key; + this.sork_keys = sork_keys; + this.max_count = max_count; + setMax_countIsSet(true); + } + + /** + * Performs a deep copy on other. + */ + public multi_remove_request(multi_remove_request other) { + __isset_bitfield = other.__isset_bitfield; + if (other.isSetHash_key()) { + this.hash_key = new com.xiaomi.infra.pegasus.base.blob(other.hash_key); + } + if (other.isSetSork_keys()) { + java.util.List __this__sork_keys = new java.util.ArrayList(other.sork_keys.size()); + for (com.xiaomi.infra.pegasus.base.blob other_element : other.sork_keys) { + __this__sork_keys.add(new com.xiaomi.infra.pegasus.base.blob(other_element)); + } + this.sork_keys = __this__sork_keys; + } + this.max_count = other.max_count; + } + + public multi_remove_request deepCopy() { + return new multi_remove_request(this); + } + + @Override + public void clear() { + this.hash_key = null; + this.sork_keys = null; + setMax_countIsSet(false); + this.max_count = 0; + } + + public com.xiaomi.infra.pegasus.base.blob getHash_key() { + return this.hash_key; + } + + public multi_remove_request setHash_key(com.xiaomi.infra.pegasus.base.blob hash_key) { + this.hash_key = hash_key; + return this; + } + + public void unsetHash_key() { + this.hash_key = null; + } + + /** Returns true if field hash_key is set (has been assigned a value) and false otherwise */ + public boolean isSetHash_key() { + return this.hash_key != null; + } + + public void setHash_keyIsSet(boolean value) { + if (!value) { + this.hash_key = null; + } + } + + public int getSork_keysSize() { + return (this.sork_keys == null) ? 0 : this.sork_keys.size(); + } + + public java.util.Iterator getSork_keysIterator() { + return (this.sork_keys == null) ? null : this.sork_keys.iterator(); + } + + public void addToSork_keys(com.xiaomi.infra.pegasus.base.blob elem) { + if (this.sork_keys == null) { + this.sork_keys = new java.util.ArrayList(); + } + this.sork_keys.add(elem); + } + + public java.util.List getSork_keys() { + return this.sork_keys; + } + + public multi_remove_request setSork_keys(java.util.List sork_keys) { + this.sork_keys = sork_keys; + return this; + } + + public void unsetSork_keys() { + this.sork_keys = null; + } + + /** Returns true if field sork_keys is set (has been assigned a value) and false otherwise */ + public boolean isSetSork_keys() { + return this.sork_keys != null; + } + + public void setSork_keysIsSet(boolean value) { + if (!value) { + this.sork_keys = null; + } + } + + public long getMax_count() { + return this.max_count; + } + + public multi_remove_request setMax_count(long max_count) { + this.max_count = max_count; + setMax_countIsSet(true); + return this; + } + + public void unsetMax_count() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __MAX_COUNT_ISSET_ID); + } + + /** Returns true if field max_count is set (has been assigned a value) and false otherwise */ + public boolean isSetMax_count() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __MAX_COUNT_ISSET_ID); + } + + public void setMax_countIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __MAX_COUNT_ISSET_ID, value); + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case HASH_KEY: + if (value == null) { + unsetHash_key(); + } else { + setHash_key((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case SORK_KEYS: + if (value == null) { + unsetSork_keys(); + } else { + setSork_keys((java.util.List)value); + } + break; + + case MAX_COUNT: + if (value == null) { + unsetMax_count(); + } else { + setMax_count((java.lang.Long)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case HASH_KEY: + return getHash_key(); + + case SORK_KEYS: + return getSork_keys(); + + case MAX_COUNT: + return getMax_count(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case HASH_KEY: + return isSetHash_key(); + case SORK_KEYS: + return isSetSork_keys(); + case MAX_COUNT: + return isSetMax_count(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_remove_request) + return this.equals((multi_remove_request)that); + return false; + } + + public boolean equals(multi_remove_request that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_hash_key = true && this.isSetHash_key(); + boolean that_present_hash_key = true && that.isSetHash_key(); + if (this_present_hash_key || that_present_hash_key) { + if (!(this_present_hash_key && that_present_hash_key)) + return false; + if (!this.hash_key.equals(that.hash_key)) + return false; + } + + boolean this_present_sork_keys = true && this.isSetSork_keys(); + boolean that_present_sork_keys = true && that.isSetSork_keys(); + if (this_present_sork_keys || that_present_sork_keys) { + if (!(this_present_sork_keys && that_present_sork_keys)) + return false; + if (!this.sork_keys.equals(that.sork_keys)) + return false; + } + + boolean this_present_max_count = true; + boolean that_present_max_count = true; + if (this_present_max_count || that_present_max_count) { + if (!(this_present_max_count && that_present_max_count)) + return false; + if (this.max_count != that.max_count) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetHash_key()) ? 131071 : 524287); + if (isSetHash_key()) + hashCode = hashCode * 8191 + hash_key.hashCode(); + + hashCode = hashCode * 8191 + ((isSetSork_keys()) ? 131071 : 524287); + if (isSetSork_keys()) + hashCode = hashCode * 8191 + sork_keys.hashCode(); + + hashCode = hashCode * 8191 + com.xiaomi.infra.pegasus.thrift.TBaseHelper.hashCode(max_count); + + return hashCode; + } + + @Override + public int compareTo(multi_remove_request other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetHash_key()).compareTo(other.isSetHash_key()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetHash_key()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.hash_key, other.hash_key); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetSork_keys()).compareTo(other.isSetSork_keys()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSork_keys()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.sork_keys, other.sork_keys); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetMax_count()).compareTo(other.isSetMax_count()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetMax_count()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.max_count, other.max_count); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_remove_request("); + boolean first = true; + + sb.append("hash_key:"); + if (this.hash_key == null) { + sb.append("null"); + } else { + sb.append(this.hash_key); + } + first = false; + if (!first) sb.append(", "); + sb.append("sork_keys:"); + if (this.sork_keys == null) { + sb.append("null"); + } else { + sb.append(this.sork_keys); + } + first = false; + if (!first) sb.append(", "); + sb.append("max_count:"); + sb.append(this.max_count); + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (hash_key != null) { + hash_key.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_remove_requestStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_remove_requestStandardScheme getScheme() { + return new multi_remove_requestStandardScheme(); + } + } + + private static class multi_remove_requestStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_remove_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // HASH_KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.hash_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.hash_key.read(iprot); + struct.setHash_keyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // SORK_KEYS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list8 = iprot.readListBegin(); + struct.sork_keys = new java.util.ArrayList(_list8.size); + com.xiaomi.infra.pegasus.base.blob _elem9; + for (int _i10 = 0; _i10 < _list8.size; ++_i10) + { + _elem9 = new com.xiaomi.infra.pegasus.base.blob(); + _elem9.read(iprot); + struct.sork_keys.add(_elem9); + } + iprot.readListEnd(); + } + struct.setSork_keysIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // MAX_COUNT + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I64) { + struct.max_count = iprot.readI64(); + struct.setMax_countIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_remove_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.hash_key != null) { + oprot.writeFieldBegin(HASH_KEY_FIELD_DESC); + struct.hash_key.write(oprot); + oprot.writeFieldEnd(); + } + if (struct.sork_keys != null) { + oprot.writeFieldBegin(SORK_KEYS_FIELD_DESC); + { + oprot.writeListBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, struct.sork_keys.size())); + for (com.xiaomi.infra.pegasus.base.blob _iter11 : struct.sork_keys) + { + _iter11.write(oprot); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(MAX_COUNT_FIELD_DESC); + oprot.writeI64(struct.max_count); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_remove_requestTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_remove_requestTupleScheme getScheme() { + return new multi_remove_requestTupleScheme(); + } + } + + private static class multi_remove_requestTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_remove_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetHash_key()) { + optionals.set(0); + } + if (struct.isSetSork_keys()) { + optionals.set(1); + } + if (struct.isSetMax_count()) { + optionals.set(2); + } + oprot.writeBitSet(optionals, 3); + if (struct.isSetHash_key()) { + struct.hash_key.write(oprot); + } + if (struct.isSetSork_keys()) { + { + oprot.writeI32(struct.sork_keys.size()); + for (com.xiaomi.infra.pegasus.base.blob _iter12 : struct.sork_keys) + { + _iter12.write(oprot); + } + } + } + if (struct.isSetMax_count()) { + oprot.writeI64(struct.max_count); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_remove_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(3); + if (incoming.get(0)) { + struct.hash_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.hash_key.read(iprot); + struct.setHash_keyIsSet(true); + } + if (incoming.get(1)) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list13 = new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, iprot.readI32()); + struct.sork_keys = new java.util.ArrayList(_list13.size); + com.xiaomi.infra.pegasus.base.blob _elem14; + for (int _i15 = 0; _i15 < _list13.size; ++_i15) + { + _elem14 = new com.xiaomi.infra.pegasus.base.blob(); + _elem14.read(iprot); + struct.sork_keys.add(_elem14); + } + } + struct.setSork_keysIsSet(true); + } + if (incoming.get(2)) { + struct.max_count = iprot.readI64(); + struct.setMax_countIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/multi_remove_response.java b/src/main/java/com/xiaomi/infra/pegasus/apps/multi_remove_response.java new file mode 100644 index 00000000..96033b2b --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/multi_remove_response.java @@ -0,0 +1,859 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class multi_remove_response implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_remove_response"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField ERROR_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("error", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField COUNT_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("count", com.xiaomi.infra.pegasus.thrift.protocol.TType.I64, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField APP_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("app_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PARTITION_INDEX_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("partition_index", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField DECREE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("decree", com.xiaomi.infra.pegasus.thrift.protocol.TType.I64, (short)5); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SERVER_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("server", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING, (short)6); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_remove_responseStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_remove_responseTupleSchemeFactory(); + + public int error; // required + public long count; // required + public int app_id; // required + public int partition_index; // required + public long decree; // required + public java.lang.String server; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + ERROR((short)1, "error"), + COUNT((short)2, "count"), + APP_ID((short)3, "app_id"), + PARTITION_INDEX((short)4, "partition_index"), + DECREE((short)5, "decree"), + SERVER((short)6, "server"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // ERROR + return ERROR; + case 2: // COUNT + return COUNT; + case 3: // APP_ID + return APP_ID; + case 4: // PARTITION_INDEX + return PARTITION_INDEX; + case 5: // DECREE + return DECREE; + case 6: // SERVER + return SERVER; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __ERROR_ISSET_ID = 0; + private static final int __COUNT_ISSET_ID = 1; + private static final int __APP_ID_ISSET_ID = 2; + private static final int __PARTITION_INDEX_ISSET_ID = 3; + private static final int __DECREE_ISSET_ID = 4; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.ERROR, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("error", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.COUNT, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("count", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I64))); + tmpMap.put(_Fields.APP_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("app_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.PARTITION_INDEX, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("partition_index", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.DECREE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("decree", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I64))); + tmpMap.put(_Fields.SERVER, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("server", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_remove_response.class, metaDataMap); + } + + public multi_remove_response() { + } + + public multi_remove_response( + int error, + long count, + int app_id, + int partition_index, + long decree, + java.lang.String server) + { + this(); + this.error = error; + setErrorIsSet(true); + this.count = count; + setCountIsSet(true); + this.app_id = app_id; + setApp_idIsSet(true); + this.partition_index = partition_index; + setPartition_indexIsSet(true); + this.decree = decree; + setDecreeIsSet(true); + this.server = server; + } + + /** + * Performs a deep copy on other. + */ + public multi_remove_response(multi_remove_response other) { + __isset_bitfield = other.__isset_bitfield; + this.error = other.error; + this.count = other.count; + this.app_id = other.app_id; + this.partition_index = other.partition_index; + this.decree = other.decree; + if (other.isSetServer()) { + this.server = other.server; + } + } + + public multi_remove_response deepCopy() { + return new multi_remove_response(this); + } + + @Override + public void clear() { + setErrorIsSet(false); + this.error = 0; + setCountIsSet(false); + this.count = 0; + setApp_idIsSet(false); + this.app_id = 0; + setPartition_indexIsSet(false); + this.partition_index = 0; + setDecreeIsSet(false); + this.decree = 0; + this.server = null; + } + + public int getError() { + return this.error; + } + + public multi_remove_response setError(int error) { + this.error = error; + setErrorIsSet(true); + return this; + } + + public void unsetError() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + /** Returns true if field error is set (has been assigned a value) and false otherwise */ + public boolean isSetError() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + public void setErrorIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __ERROR_ISSET_ID, value); + } + + public long getCount() { + return this.count; + } + + public multi_remove_response setCount(long count) { + this.count = count; + setCountIsSet(true); + return this; + } + + public void unsetCount() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __COUNT_ISSET_ID); + } + + /** Returns true if field count is set (has been assigned a value) and false otherwise */ + public boolean isSetCount() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __COUNT_ISSET_ID); + } + + public void setCountIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __COUNT_ISSET_ID, value); + } + + public int getApp_id() { + return this.app_id; + } + + public multi_remove_response setApp_id(int app_id) { + this.app_id = app_id; + setApp_idIsSet(true); + return this; + } + + public void unsetApp_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + /** Returns true if field app_id is set (has been assigned a value) and false otherwise */ + public boolean isSetApp_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + public void setApp_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __APP_ID_ISSET_ID, value); + } + + public int getPartition_index() { + return this.partition_index; + } + + public multi_remove_response setPartition_index(int partition_index) { + this.partition_index = partition_index; + setPartition_indexIsSet(true); + return this; + } + + public void unsetPartition_index() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + /** Returns true if field partition_index is set (has been assigned a value) and false otherwise */ + public boolean isSetPartition_index() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + public void setPartition_indexIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID, value); + } + + public long getDecree() { + return this.decree; + } + + public multi_remove_response setDecree(long decree) { + this.decree = decree; + setDecreeIsSet(true); + return this; + } + + public void unsetDecree() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __DECREE_ISSET_ID); + } + + /** Returns true if field decree is set (has been assigned a value) and false otherwise */ + public boolean isSetDecree() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __DECREE_ISSET_ID); + } + + public void setDecreeIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __DECREE_ISSET_ID, value); + } + + public java.lang.String getServer() { + return this.server; + } + + public multi_remove_response setServer(java.lang.String server) { + this.server = server; + return this; + } + + public void unsetServer() { + this.server = null; + } + + /** Returns true if field server is set (has been assigned a value) and false otherwise */ + public boolean isSetServer() { + return this.server != null; + } + + public void setServerIsSet(boolean value) { + if (!value) { + this.server = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case ERROR: + if (value == null) { + unsetError(); + } else { + setError((java.lang.Integer)value); + } + break; + + case COUNT: + if (value == null) { + unsetCount(); + } else { + setCount((java.lang.Long)value); + } + break; + + case APP_ID: + if (value == null) { + unsetApp_id(); + } else { + setApp_id((java.lang.Integer)value); + } + break; + + case PARTITION_INDEX: + if (value == null) { + unsetPartition_index(); + } else { + setPartition_index((java.lang.Integer)value); + } + break; + + case DECREE: + if (value == null) { + unsetDecree(); + } else { + setDecree((java.lang.Long)value); + } + break; + + case SERVER: + if (value == null) { + unsetServer(); + } else { + setServer((java.lang.String)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case ERROR: + return getError(); + + case COUNT: + return getCount(); + + case APP_ID: + return getApp_id(); + + case PARTITION_INDEX: + return getPartition_index(); + + case DECREE: + return getDecree(); + + case SERVER: + return getServer(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case ERROR: + return isSetError(); + case COUNT: + return isSetCount(); + case APP_ID: + return isSetApp_id(); + case PARTITION_INDEX: + return isSetPartition_index(); + case DECREE: + return isSetDecree(); + case SERVER: + return isSetServer(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_remove_response) + return this.equals((multi_remove_response)that); + return false; + } + + public boolean equals(multi_remove_response that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_error = true; + boolean that_present_error = true; + if (this_present_error || that_present_error) { + if (!(this_present_error && that_present_error)) + return false; + if (this.error != that.error) + return false; + } + + boolean this_present_count = true; + boolean that_present_count = true; + if (this_present_count || that_present_count) { + if (!(this_present_count && that_present_count)) + return false; + if (this.count != that.count) + return false; + } + + boolean this_present_app_id = true; + boolean that_present_app_id = true; + if (this_present_app_id || that_present_app_id) { + if (!(this_present_app_id && that_present_app_id)) + return false; + if (this.app_id != that.app_id) + return false; + } + + boolean this_present_partition_index = true; + boolean that_present_partition_index = true; + if (this_present_partition_index || that_present_partition_index) { + if (!(this_present_partition_index && that_present_partition_index)) + return false; + if (this.partition_index != that.partition_index) + return false; + } + + boolean this_present_decree = true; + boolean that_present_decree = true; + if (this_present_decree || that_present_decree) { + if (!(this_present_decree && that_present_decree)) + return false; + if (this.decree != that.decree) + return false; + } + + boolean this_present_server = true && this.isSetServer(); + boolean that_present_server = true && that.isSetServer(); + if (this_present_server || that_present_server) { + if (!(this_present_server && that_present_server)) + return false; + if (!this.server.equals(that.server)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + error; + + hashCode = hashCode * 8191 + com.xiaomi.infra.pegasus.thrift.TBaseHelper.hashCode(count); + + hashCode = hashCode * 8191 + app_id; + + hashCode = hashCode * 8191 + partition_index; + + hashCode = hashCode * 8191 + com.xiaomi.infra.pegasus.thrift.TBaseHelper.hashCode(decree); + + hashCode = hashCode * 8191 + ((isSetServer()) ? 131071 : 524287); + if (isSetServer()) + hashCode = hashCode * 8191 + server.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(multi_remove_response other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetError()).compareTo(other.isSetError()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetError()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.error, other.error); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetCount()).compareTo(other.isSetCount()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetCount()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.count, other.count); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetApp_id()).compareTo(other.isSetApp_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetApp_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.app_id, other.app_id); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPartition_index()).compareTo(other.isSetPartition_index()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPartition_index()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.partition_index, other.partition_index); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetDecree()).compareTo(other.isSetDecree()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetDecree()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.decree, other.decree); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetServer()).compareTo(other.isSetServer()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetServer()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.server, other.server); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_remove_response("); + boolean first = true; + + sb.append("error:"); + sb.append(this.error); + first = false; + if (!first) sb.append(", "); + sb.append("count:"); + sb.append(this.count); + first = false; + if (!first) sb.append(", "); + sb.append("app_id:"); + sb.append(this.app_id); + first = false; + if (!first) sb.append(", "); + sb.append("partition_index:"); + sb.append(this.partition_index); + first = false; + if (!first) sb.append(", "); + sb.append("decree:"); + sb.append(this.decree); + first = false; + if (!first) sb.append(", "); + sb.append("server:"); + if (this.server == null) { + sb.append("null"); + } else { + sb.append(this.server); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_remove_responseStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_remove_responseStandardScheme getScheme() { + return new multi_remove_responseStandardScheme(); + } + } + + private static class multi_remove_responseStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_remove_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // ERROR + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // COUNT + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I64) { + struct.count = iprot.readI64(); + struct.setCountIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // APP_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // PARTITION_INDEX + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 5: // DECREE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I64) { + struct.decree = iprot.readI64(); + struct.setDecreeIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 6: // SERVER + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_remove_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldBegin(ERROR_FIELD_DESC); + oprot.writeI32(struct.error); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(COUNT_FIELD_DESC); + oprot.writeI64(struct.count); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(APP_ID_FIELD_DESC); + oprot.writeI32(struct.app_id); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(PARTITION_INDEX_FIELD_DESC); + oprot.writeI32(struct.partition_index); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(DECREE_FIELD_DESC); + oprot.writeI64(struct.decree); + oprot.writeFieldEnd(); + if (struct.server != null) { + oprot.writeFieldBegin(SERVER_FIELD_DESC); + oprot.writeString(struct.server); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_remove_responseTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_remove_responseTupleScheme getScheme() { + return new multi_remove_responseTupleScheme(); + } + } + + private static class multi_remove_responseTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_remove_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetError()) { + optionals.set(0); + } + if (struct.isSetCount()) { + optionals.set(1); + } + if (struct.isSetApp_id()) { + optionals.set(2); + } + if (struct.isSetPartition_index()) { + optionals.set(3); + } + if (struct.isSetDecree()) { + optionals.set(4); + } + if (struct.isSetServer()) { + optionals.set(5); + } + oprot.writeBitSet(optionals, 6); + if (struct.isSetError()) { + oprot.writeI32(struct.error); + } + if (struct.isSetCount()) { + oprot.writeI64(struct.count); + } + if (struct.isSetApp_id()) { + oprot.writeI32(struct.app_id); + } + if (struct.isSetPartition_index()) { + oprot.writeI32(struct.partition_index); + } + if (struct.isSetDecree()) { + oprot.writeI64(struct.decree); + } + if (struct.isSetServer()) { + oprot.writeString(struct.server); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_remove_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(6); + if (incoming.get(0)) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } + if (incoming.get(1)) { + struct.count = iprot.readI64(); + struct.setCountIsSet(true); + } + if (incoming.get(2)) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } + if (incoming.get(3)) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } + if (incoming.get(4)) { + struct.decree = iprot.readI64(); + struct.setDecreeIsSet(true); + } + if (incoming.get(5)) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/read_response.java b/src/main/java/com/xiaomi/infra/pegasus/apps/read_response.java new file mode 100644 index 00000000..62c29fc8 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/read_response.java @@ -0,0 +1,776 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class read_response implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("read_response"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField ERROR_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("error", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField VALUE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("value", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField APP_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("app_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PARTITION_INDEX_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("partition_index", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SERVER_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("server", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING, (short)6); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new read_responseStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new read_responseTupleSchemeFactory(); + + public int error; // required + public com.xiaomi.infra.pegasus.base.blob value; // required + public int app_id; // required + public int partition_index; // required + public java.lang.String server; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + ERROR((short)1, "error"), + VALUE((short)2, "value"), + APP_ID((short)3, "app_id"), + PARTITION_INDEX((short)4, "partition_index"), + SERVER((short)6, "server"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // ERROR + return ERROR; + case 2: // VALUE + return VALUE; + case 3: // APP_ID + return APP_ID; + case 4: // PARTITION_INDEX + return PARTITION_INDEX; + case 6: // SERVER + return SERVER; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __ERROR_ISSET_ID = 0; + private static final int __APP_ID_ISSET_ID = 1; + private static final int __PARTITION_INDEX_ISSET_ID = 2; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.ERROR, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("error", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.VALUE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("value", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.APP_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("app_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.PARTITION_INDEX, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("partition_index", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.SERVER, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("server", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(read_response.class, metaDataMap); + } + + public read_response() { + } + + public read_response( + int error, + com.xiaomi.infra.pegasus.base.blob value, + int app_id, + int partition_index, + java.lang.String server) + { + this(); + this.error = error; + setErrorIsSet(true); + this.value = value; + this.app_id = app_id; + setApp_idIsSet(true); + this.partition_index = partition_index; + setPartition_indexIsSet(true); + this.server = server; + } + + /** + * Performs a deep copy on other. + */ + public read_response(read_response other) { + __isset_bitfield = other.__isset_bitfield; + this.error = other.error; + if (other.isSetValue()) { + this.value = new com.xiaomi.infra.pegasus.base.blob(other.value); + } + this.app_id = other.app_id; + this.partition_index = other.partition_index; + if (other.isSetServer()) { + this.server = other.server; + } + } + + public read_response deepCopy() { + return new read_response(this); + } + + @Override + public void clear() { + setErrorIsSet(false); + this.error = 0; + this.value = null; + setApp_idIsSet(false); + this.app_id = 0; + setPartition_indexIsSet(false); + this.partition_index = 0; + this.server = null; + } + + public int getError() { + return this.error; + } + + public read_response setError(int error) { + this.error = error; + setErrorIsSet(true); + return this; + } + + public void unsetError() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + /** Returns true if field error is set (has been assigned a value) and false otherwise */ + public boolean isSetError() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + public void setErrorIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __ERROR_ISSET_ID, value); + } + + public com.xiaomi.infra.pegasus.base.blob getValue() { + return this.value; + } + + public read_response setValue(com.xiaomi.infra.pegasus.base.blob value) { + this.value = value; + return this; + } + + public void unsetValue() { + this.value = null; + } + + /** Returns true if field value is set (has been assigned a value) and false otherwise */ + public boolean isSetValue() { + return this.value != null; + } + + public void setValueIsSet(boolean value) { + if (!value) { + this.value = null; + } + } + + public int getApp_id() { + return this.app_id; + } + + public read_response setApp_id(int app_id) { + this.app_id = app_id; + setApp_idIsSet(true); + return this; + } + + public void unsetApp_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + /** Returns true if field app_id is set (has been assigned a value) and false otherwise */ + public boolean isSetApp_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + public void setApp_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __APP_ID_ISSET_ID, value); + } + + public int getPartition_index() { + return this.partition_index; + } + + public read_response setPartition_index(int partition_index) { + this.partition_index = partition_index; + setPartition_indexIsSet(true); + return this; + } + + public void unsetPartition_index() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + /** Returns true if field partition_index is set (has been assigned a value) and false otherwise */ + public boolean isSetPartition_index() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + public void setPartition_indexIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID, value); + } + + public java.lang.String getServer() { + return this.server; + } + + public read_response setServer(java.lang.String server) { + this.server = server; + return this; + } + + public void unsetServer() { + this.server = null; + } + + /** Returns true if field server is set (has been assigned a value) and false otherwise */ + public boolean isSetServer() { + return this.server != null; + } + + public void setServerIsSet(boolean value) { + if (!value) { + this.server = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case ERROR: + if (value == null) { + unsetError(); + } else { + setError((java.lang.Integer)value); + } + break; + + case VALUE: + if (value == null) { + unsetValue(); + } else { + setValue((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case APP_ID: + if (value == null) { + unsetApp_id(); + } else { + setApp_id((java.lang.Integer)value); + } + break; + + case PARTITION_INDEX: + if (value == null) { + unsetPartition_index(); + } else { + setPartition_index((java.lang.Integer)value); + } + break; + + case SERVER: + if (value == null) { + unsetServer(); + } else { + setServer((java.lang.String)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case ERROR: + return getError(); + + case VALUE: + return getValue(); + + case APP_ID: + return getApp_id(); + + case PARTITION_INDEX: + return getPartition_index(); + + case SERVER: + return getServer(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case ERROR: + return isSetError(); + case VALUE: + return isSetValue(); + case APP_ID: + return isSetApp_id(); + case PARTITION_INDEX: + return isSetPartition_index(); + case SERVER: + return isSetServer(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof read_response) + return this.equals((read_response)that); + return false; + } + + public boolean equals(read_response that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_error = true; + boolean that_present_error = true; + if (this_present_error || that_present_error) { + if (!(this_present_error && that_present_error)) + return false; + if (this.error != that.error) + return false; + } + + boolean this_present_value = true && this.isSetValue(); + boolean that_present_value = true && that.isSetValue(); + if (this_present_value || that_present_value) { + if (!(this_present_value && that_present_value)) + return false; + if (!this.value.equals(that.value)) + return false; + } + + boolean this_present_app_id = true; + boolean that_present_app_id = true; + if (this_present_app_id || that_present_app_id) { + if (!(this_present_app_id && that_present_app_id)) + return false; + if (this.app_id != that.app_id) + return false; + } + + boolean this_present_partition_index = true; + boolean that_present_partition_index = true; + if (this_present_partition_index || that_present_partition_index) { + if (!(this_present_partition_index && that_present_partition_index)) + return false; + if (this.partition_index != that.partition_index) + return false; + } + + boolean this_present_server = true && this.isSetServer(); + boolean that_present_server = true && that.isSetServer(); + if (this_present_server || that_present_server) { + if (!(this_present_server && that_present_server)) + return false; + if (!this.server.equals(that.server)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + error; + + hashCode = hashCode * 8191 + ((isSetValue()) ? 131071 : 524287); + if (isSetValue()) + hashCode = hashCode * 8191 + value.hashCode(); + + hashCode = hashCode * 8191 + app_id; + + hashCode = hashCode * 8191 + partition_index; + + hashCode = hashCode * 8191 + ((isSetServer()) ? 131071 : 524287); + if (isSetServer()) + hashCode = hashCode * 8191 + server.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(read_response other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetError()).compareTo(other.isSetError()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetError()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.error, other.error); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetValue()).compareTo(other.isSetValue()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetValue()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.value, other.value); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetApp_id()).compareTo(other.isSetApp_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetApp_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.app_id, other.app_id); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPartition_index()).compareTo(other.isSetPartition_index()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPartition_index()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.partition_index, other.partition_index); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetServer()).compareTo(other.isSetServer()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetServer()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.server, other.server); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("read_response("); + boolean first = true; + + sb.append("error:"); + sb.append(this.error); + first = false; + if (!first) sb.append(", "); + sb.append("value:"); + if (this.value == null) { + sb.append("null"); + } else { + sb.append(this.value); + } + first = false; + if (!first) sb.append(", "); + sb.append("app_id:"); + sb.append(this.app_id); + first = false; + if (!first) sb.append(", "); + sb.append("partition_index:"); + sb.append(this.partition_index); + first = false; + if (!first) sb.append(", "); + sb.append("server:"); + if (this.server == null) { + sb.append("null"); + } else { + sb.append(this.server); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (value != null) { + value.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class read_responseStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public read_responseStandardScheme getScheme() { + return new read_responseStandardScheme(); + } + } + + private static class read_responseStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, read_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // ERROR + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // VALUE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.value = new com.xiaomi.infra.pegasus.base.blob(); + struct.value.read(iprot); + struct.setValueIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // APP_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // PARTITION_INDEX + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 6: // SERVER + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, read_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldBegin(ERROR_FIELD_DESC); + oprot.writeI32(struct.error); + oprot.writeFieldEnd(); + if (struct.value != null) { + oprot.writeFieldBegin(VALUE_FIELD_DESC); + struct.value.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(APP_ID_FIELD_DESC); + oprot.writeI32(struct.app_id); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(PARTITION_INDEX_FIELD_DESC); + oprot.writeI32(struct.partition_index); + oprot.writeFieldEnd(); + if (struct.server != null) { + oprot.writeFieldBegin(SERVER_FIELD_DESC); + oprot.writeString(struct.server); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class read_responseTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public read_responseTupleScheme getScheme() { + return new read_responseTupleScheme(); + } + } + + private static class read_responseTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, read_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetError()) { + optionals.set(0); + } + if (struct.isSetValue()) { + optionals.set(1); + } + if (struct.isSetApp_id()) { + optionals.set(2); + } + if (struct.isSetPartition_index()) { + optionals.set(3); + } + if (struct.isSetServer()) { + optionals.set(4); + } + oprot.writeBitSet(optionals, 5); + if (struct.isSetError()) { + oprot.writeI32(struct.error); + } + if (struct.isSetValue()) { + struct.value.write(oprot); + } + if (struct.isSetApp_id()) { + oprot.writeI32(struct.app_id); + } + if (struct.isSetPartition_index()) { + oprot.writeI32(struct.partition_index); + } + if (struct.isSetServer()) { + oprot.writeString(struct.server); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, read_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(5); + if (incoming.get(0)) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } + if (incoming.get(1)) { + struct.value = new com.xiaomi.infra.pegasus.base.blob(); + struct.value.read(iprot); + struct.setValueIsSet(true); + } + if (incoming.get(2)) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } + if (incoming.get(3)) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } + if (incoming.get(4)) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/rrdb.java b/src/main/java/com/xiaomi/infra/pegasus/apps/rrdb.java new file mode 100644 index 00000000..db84c381 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/rrdb.java @@ -0,0 +1,9372 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class rrdb { + + public interface Iface { + + public update_response put(update_request update) throws com.xiaomi.infra.pegasus.thrift.TException; + + public update_response multi_put(multi_put_request request) throws com.xiaomi.infra.pegasus.thrift.TException; + + public update_response remove(com.xiaomi.infra.pegasus.base.blob key) throws com.xiaomi.infra.pegasus.thrift.TException; + + public multi_remove_response multi_remove(multi_remove_request request) throws com.xiaomi.infra.pegasus.thrift.TException; + + public read_response get(com.xiaomi.infra.pegasus.base.blob key) throws com.xiaomi.infra.pegasus.thrift.TException; + + public multi_get_response multi_get(multi_get_request request) throws com.xiaomi.infra.pegasus.thrift.TException; + + public count_response sortkey_count(com.xiaomi.infra.pegasus.base.blob hash_key) throws com.xiaomi.infra.pegasus.thrift.TException; + + public ttl_response ttl(com.xiaomi.infra.pegasus.base.blob key) throws com.xiaomi.infra.pegasus.thrift.TException; + + public scan_response get_scanner(get_scanner_request request) throws com.xiaomi.infra.pegasus.thrift.TException; + + public scan_response scan(scan_request request) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void clear_scanner(long context_id) throws com.xiaomi.infra.pegasus.thrift.TException; + + } + + public interface AsyncIface { + + public void put(update_request update, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void multi_put(multi_put_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void remove(com.xiaomi.infra.pegasus.base.blob key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void multi_remove(multi_remove_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void get(com.xiaomi.infra.pegasus.base.blob key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void multi_get(multi_get_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void sortkey_count(com.xiaomi.infra.pegasus.base.blob hash_key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void ttl(com.xiaomi.infra.pegasus.base.blob key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void get_scanner(get_scanner_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void scan(scan_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void clear_scanner(long context_id, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException; + + } + + public static class Client extends com.xiaomi.infra.pegasus.thrift.TServiceClient implements Iface { + public static class Factory implements com.xiaomi.infra.pegasus.thrift.TServiceClientFactory { + public Factory() {} + public Client getClient(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) { + return new Client(prot); + } + public Client getClient(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) { + return new Client(iprot, oprot); + } + } + + public Client(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) + { + super(prot, prot); + } + + public Client(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) { + super(iprot, oprot); + } + + public update_response put(update_request update) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_put(update); + return recv_put(); + } + + public void send_put(update_request update) throws com.xiaomi.infra.pegasus.thrift.TException + { + put_args args = new put_args(); + args.setUpdate(update); + sendBase("put", args); + } + + public update_response recv_put() throws com.xiaomi.infra.pegasus.thrift.TException + { + put_result result = new put_result(); + receiveBase(result, "put"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "put failed: unknown result"); + } + + public update_response multi_put(multi_put_request request) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_multi_put(request); + return recv_multi_put(); + } + + public void send_multi_put(multi_put_request request) throws com.xiaomi.infra.pegasus.thrift.TException + { + multi_put_args args = new multi_put_args(); + args.setRequest(request); + sendBase("multi_put", args); + } + + public update_response recv_multi_put() throws com.xiaomi.infra.pegasus.thrift.TException + { + multi_put_result result = new multi_put_result(); + receiveBase(result, "multi_put"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "multi_put failed: unknown result"); + } + + public update_response remove(com.xiaomi.infra.pegasus.base.blob key) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_remove(key); + return recv_remove(); + } + + public void send_remove(com.xiaomi.infra.pegasus.base.blob key) throws com.xiaomi.infra.pegasus.thrift.TException + { + remove_args args = new remove_args(); + args.setKey(key); + sendBase("remove", args); + } + + public update_response recv_remove() throws com.xiaomi.infra.pegasus.thrift.TException + { + remove_result result = new remove_result(); + receiveBase(result, "remove"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "remove failed: unknown result"); + } + + public multi_remove_response multi_remove(multi_remove_request request) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_multi_remove(request); + return recv_multi_remove(); + } + + public void send_multi_remove(multi_remove_request request) throws com.xiaomi.infra.pegasus.thrift.TException + { + multi_remove_args args = new multi_remove_args(); + args.setRequest(request); + sendBase("multi_remove", args); + } + + public multi_remove_response recv_multi_remove() throws com.xiaomi.infra.pegasus.thrift.TException + { + multi_remove_result result = new multi_remove_result(); + receiveBase(result, "multi_remove"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "multi_remove failed: unknown result"); + } + + public read_response get(com.xiaomi.infra.pegasus.base.blob key) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_get(key); + return recv_get(); + } + + public void send_get(com.xiaomi.infra.pegasus.base.blob key) throws com.xiaomi.infra.pegasus.thrift.TException + { + get_args args = new get_args(); + args.setKey(key); + sendBase("get", args); + } + + public read_response recv_get() throws com.xiaomi.infra.pegasus.thrift.TException + { + get_result result = new get_result(); + receiveBase(result, "get"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "get failed: unknown result"); + } + + public multi_get_response multi_get(multi_get_request request) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_multi_get(request); + return recv_multi_get(); + } + + public void send_multi_get(multi_get_request request) throws com.xiaomi.infra.pegasus.thrift.TException + { + multi_get_args args = new multi_get_args(); + args.setRequest(request); + sendBase("multi_get", args); + } + + public multi_get_response recv_multi_get() throws com.xiaomi.infra.pegasus.thrift.TException + { + multi_get_result result = new multi_get_result(); + receiveBase(result, "multi_get"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "multi_get failed: unknown result"); + } + + public count_response sortkey_count(com.xiaomi.infra.pegasus.base.blob hash_key) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_sortkey_count(hash_key); + return recv_sortkey_count(); + } + + public void send_sortkey_count(com.xiaomi.infra.pegasus.base.blob hash_key) throws com.xiaomi.infra.pegasus.thrift.TException + { + sortkey_count_args args = new sortkey_count_args(); + args.setHash_key(hash_key); + sendBase("sortkey_count", args); + } + + public count_response recv_sortkey_count() throws com.xiaomi.infra.pegasus.thrift.TException + { + sortkey_count_result result = new sortkey_count_result(); + receiveBase(result, "sortkey_count"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "sortkey_count failed: unknown result"); + } + + public ttl_response ttl(com.xiaomi.infra.pegasus.base.blob key) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_ttl(key); + return recv_ttl(); + } + + public void send_ttl(com.xiaomi.infra.pegasus.base.blob key) throws com.xiaomi.infra.pegasus.thrift.TException + { + ttl_args args = new ttl_args(); + args.setKey(key); + sendBase("ttl", args); + } + + public ttl_response recv_ttl() throws com.xiaomi.infra.pegasus.thrift.TException + { + ttl_result result = new ttl_result(); + receiveBase(result, "ttl"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "ttl failed: unknown result"); + } + + public scan_response get_scanner(get_scanner_request request) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_get_scanner(request); + return recv_get_scanner(); + } + + public void send_get_scanner(get_scanner_request request) throws com.xiaomi.infra.pegasus.thrift.TException + { + get_scanner_args args = new get_scanner_args(); + args.setRequest(request); + sendBase("get_scanner", args); + } + + public scan_response recv_get_scanner() throws com.xiaomi.infra.pegasus.thrift.TException + { + get_scanner_result result = new get_scanner_result(); + receiveBase(result, "get_scanner"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "get_scanner failed: unknown result"); + } + + public scan_response scan(scan_request request) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_scan(request); + return recv_scan(); + } + + public void send_scan(scan_request request) throws com.xiaomi.infra.pegasus.thrift.TException + { + scan_args args = new scan_args(); + args.setRequest(request); + sendBase("scan", args); + } + + public scan_response recv_scan() throws com.xiaomi.infra.pegasus.thrift.TException + { + scan_result result = new scan_result(); + receiveBase(result, "scan"); + if (result.isSetSuccess()) { + return result.success; + } + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "scan failed: unknown result"); + } + + public void clear_scanner(long context_id) throws com.xiaomi.infra.pegasus.thrift.TException + { + send_clear_scanner(context_id); + } + + public void send_clear_scanner(long context_id) throws com.xiaomi.infra.pegasus.thrift.TException + { + clear_scanner_args args = new clear_scanner_args(); + args.setContext_id(context_id); + sendBaseOneway("clear_scanner", args); + } + + } + public static class AsyncClient extends com.xiaomi.infra.pegasus.thrift.async.TAsyncClient implements AsyncIface { + public static class Factory implements com.xiaomi.infra.pegasus.thrift.async.TAsyncClientFactory { + private com.xiaomi.infra.pegasus.thrift.async.TAsyncClientManager clientManager; + private com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory; + public Factory(com.xiaomi.infra.pegasus.thrift.async.TAsyncClientManager clientManager, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory) { + this.clientManager = clientManager; + this.protocolFactory = protocolFactory; + } + public AsyncClient getAsyncClient(com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) { + return new AsyncClient(protocolFactory, clientManager, transport); + } + } + + public AsyncClient(com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.async.TAsyncClientManager clientManager, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) { + super(protocolFactory, clientManager, transport); + } + + public void put(update_request update, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + put_call method_call = new put_call(update, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class put_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private update_request update; + public put_call(update_request update, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.update = update; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("put", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + put_args args = new put_args(); + args.setUpdate(update); + args.write(prot); + prot.writeMessageEnd(); + } + + public update_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_put(); + } + } + + public void multi_put(multi_put_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + multi_put_call method_call = new multi_put_call(request, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class multi_put_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private multi_put_request request; + public multi_put_call(multi_put_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.request = request; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("multi_put", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + multi_put_args args = new multi_put_args(); + args.setRequest(request); + args.write(prot); + prot.writeMessageEnd(); + } + + public update_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_multi_put(); + } + } + + public void remove(com.xiaomi.infra.pegasus.base.blob key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + remove_call method_call = new remove_call(key, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class remove_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private com.xiaomi.infra.pegasus.base.blob key; + public remove_call(com.xiaomi.infra.pegasus.base.blob key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.key = key; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("remove", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + remove_args args = new remove_args(); + args.setKey(key); + args.write(prot); + prot.writeMessageEnd(); + } + + public update_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_remove(); + } + } + + public void multi_remove(multi_remove_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + multi_remove_call method_call = new multi_remove_call(request, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class multi_remove_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private multi_remove_request request; + public multi_remove_call(multi_remove_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.request = request; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("multi_remove", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + multi_remove_args args = new multi_remove_args(); + args.setRequest(request); + args.write(prot); + prot.writeMessageEnd(); + } + + public multi_remove_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_multi_remove(); + } + } + + public void get(com.xiaomi.infra.pegasus.base.blob key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + get_call method_call = new get_call(key, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class get_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private com.xiaomi.infra.pegasus.base.blob key; + public get_call(com.xiaomi.infra.pegasus.base.blob key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.key = key; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("get", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + get_args args = new get_args(); + args.setKey(key); + args.write(prot); + prot.writeMessageEnd(); + } + + public read_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_get(); + } + } + + public void multi_get(multi_get_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + multi_get_call method_call = new multi_get_call(request, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class multi_get_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private multi_get_request request; + public multi_get_call(multi_get_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.request = request; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("multi_get", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + multi_get_args args = new multi_get_args(); + args.setRequest(request); + args.write(prot); + prot.writeMessageEnd(); + } + + public multi_get_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_multi_get(); + } + } + + public void sortkey_count(com.xiaomi.infra.pegasus.base.blob hash_key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + sortkey_count_call method_call = new sortkey_count_call(hash_key, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class sortkey_count_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private com.xiaomi.infra.pegasus.base.blob hash_key; + public sortkey_count_call(com.xiaomi.infra.pegasus.base.blob hash_key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.hash_key = hash_key; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("sortkey_count", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + sortkey_count_args args = new sortkey_count_args(); + args.setHash_key(hash_key); + args.write(prot); + prot.writeMessageEnd(); + } + + public count_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_sortkey_count(); + } + } + + public void ttl(com.xiaomi.infra.pegasus.base.blob key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + ttl_call method_call = new ttl_call(key, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class ttl_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private com.xiaomi.infra.pegasus.base.blob key; + public ttl_call(com.xiaomi.infra.pegasus.base.blob key, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.key = key; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("ttl", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + ttl_args args = new ttl_args(); + args.setKey(key); + args.write(prot); + prot.writeMessageEnd(); + } + + public ttl_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_ttl(); + } + } + + public void get_scanner(get_scanner_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + get_scanner_call method_call = new get_scanner_call(request, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class get_scanner_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private get_scanner_request request; + public get_scanner_call(get_scanner_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.request = request; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("get_scanner", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + get_scanner_args args = new get_scanner_args(); + args.setRequest(request); + args.write(prot); + prot.writeMessageEnd(); + } + + public scan_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_get_scanner(); + } + } + + public void scan(scan_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + scan_call method_call = new scan_call(request, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class scan_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private scan_request request; + public scan_call(scan_request request, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, false); + this.request = request; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("scan", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.CALL, 0)); + scan_args args = new scan_args(); + args.setRequest(request); + args.write(prot); + prot.writeMessageEnd(); + } + + public scan_response getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return (new Client(prot)).recv_scan(); + } + } + + public void clear_scanner(long context_id, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + checkReady(); + clear_scanner_call method_call = new clear_scanner_call(context_id, resultHandler, this, ___protocolFactory, ___transport); + this.___currentMethod = method_call; + ___manager.call(method_call); + } + + public static class clear_scanner_call extends com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall { + private long context_id; + public clear_scanner_call(long context_id, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler, com.xiaomi.infra.pegasus.thrift.async.TAsyncClient client, com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory protocolFactory, com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport transport) throws com.xiaomi.infra.pegasus.thrift.TException { + super(client, protocolFactory, transport, resultHandler, true); + this.context_id = context_id; + } + + public void write_args(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot) throws com.xiaomi.infra.pegasus.thrift.TException { + prot.writeMessageBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TMessage("clear_scanner", com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.ONEWAY, 0)); + clear_scanner_args args = new clear_scanner_args(); + args.setContext_id(context_id); + args.write(prot); + prot.writeMessageEnd(); + } + + public Void getResult() throws com.xiaomi.infra.pegasus.thrift.TException { + if (getState() != com.xiaomi.infra.pegasus.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { + throw new java.lang.IllegalStateException("Method call not finished!"); + } + com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport memoryTransport = new com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport(getFrameBuffer().array()); + com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport); + return null; + } + } + + } + + public static class Processor extends com.xiaomi.infra.pegasus.thrift.TBaseProcessor implements com.xiaomi.infra.pegasus.thrift.TProcessor { + private static final org.slf4j.Logger _LOGGER = org.slf4j.LoggerFactory.getLogger(Processor.class.getName()); + public Processor(I iface) { + super(iface, getProcessMap(new java.util.HashMap>())); + } + + protected Processor(I iface, java.util.Map> processMap) { + super(iface, getProcessMap(processMap)); + } + + private static java.util.Map> getProcessMap(java.util.Map> processMap) { + processMap.put("put", new put()); + processMap.put("multi_put", new multi_put()); + processMap.put("remove", new remove()); + processMap.put("multi_remove", new multi_remove()); + processMap.put("get", new get()); + processMap.put("multi_get", new multi_get()); + processMap.put("sortkey_count", new sortkey_count()); + processMap.put("ttl", new ttl()); + processMap.put("get_scanner", new get_scanner()); + processMap.put("scan", new scan()); + processMap.put("clear_scanner", new clear_scanner()); + return processMap; + } + + public static class put extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public put() { + super("put"); + } + + public put_args getEmptyArgsInstance() { + return new put_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public put_result getResult(I iface, put_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + put_result result = new put_result(); + result.success = iface.put(args.update); + return result; + } + } + + public static class multi_put extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public multi_put() { + super("multi_put"); + } + + public multi_put_args getEmptyArgsInstance() { + return new multi_put_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public multi_put_result getResult(I iface, multi_put_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + multi_put_result result = new multi_put_result(); + result.success = iface.multi_put(args.request); + return result; + } + } + + public static class remove extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public remove() { + super("remove"); + } + + public remove_args getEmptyArgsInstance() { + return new remove_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public remove_result getResult(I iface, remove_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + remove_result result = new remove_result(); + result.success = iface.remove(args.key); + return result; + } + } + + public static class multi_remove extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public multi_remove() { + super("multi_remove"); + } + + public multi_remove_args getEmptyArgsInstance() { + return new multi_remove_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public multi_remove_result getResult(I iface, multi_remove_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + multi_remove_result result = new multi_remove_result(); + result.success = iface.multi_remove(args.request); + return result; + } + } + + public static class get extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public get() { + super("get"); + } + + public get_args getEmptyArgsInstance() { + return new get_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public get_result getResult(I iface, get_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + get_result result = new get_result(); + result.success = iface.get(args.key); + return result; + } + } + + public static class multi_get extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public multi_get() { + super("multi_get"); + } + + public multi_get_args getEmptyArgsInstance() { + return new multi_get_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public multi_get_result getResult(I iface, multi_get_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + multi_get_result result = new multi_get_result(); + result.success = iface.multi_get(args.request); + return result; + } + } + + public static class sortkey_count extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public sortkey_count() { + super("sortkey_count"); + } + + public sortkey_count_args getEmptyArgsInstance() { + return new sortkey_count_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public sortkey_count_result getResult(I iface, sortkey_count_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + sortkey_count_result result = new sortkey_count_result(); + result.success = iface.sortkey_count(args.hash_key); + return result; + } + } + + public static class ttl extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public ttl() { + super("ttl"); + } + + public ttl_args getEmptyArgsInstance() { + return new ttl_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public ttl_result getResult(I iface, ttl_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + ttl_result result = new ttl_result(); + result.success = iface.ttl(args.key); + return result; + } + } + + public static class get_scanner extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public get_scanner() { + super("get_scanner"); + } + + public get_scanner_args getEmptyArgsInstance() { + return new get_scanner_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public get_scanner_result getResult(I iface, get_scanner_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + get_scanner_result result = new get_scanner_result(); + result.success = iface.get_scanner(args.request); + return result; + } + } + + public static class scan extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public scan() { + super("scan"); + } + + public scan_args getEmptyArgsInstance() { + return new scan_args(); + } + + protected boolean isOneway() { + return false; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public scan_result getResult(I iface, scan_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + scan_result result = new scan_result(); + result.success = iface.scan(args.request); + return result; + } + } + + public static class clear_scanner extends com.xiaomi.infra.pegasus.thrift.ProcessFunction { + public clear_scanner() { + super("clear_scanner"); + } + + public clear_scanner_args getEmptyArgsInstance() { + return new clear_scanner_args(); + } + + protected boolean isOneway() { + return true; + } + + @Override + protected boolean handleRuntimeExceptions() { + return false; + } + + public com.xiaomi.infra.pegasus.thrift.TBase getResult(I iface, clear_scanner_args args) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.clear_scanner(args.context_id); + return null; + } + } + + } + + public static class AsyncProcessor extends com.xiaomi.infra.pegasus.thrift.TBaseAsyncProcessor { + private static final org.slf4j.Logger _LOGGER = org.slf4j.LoggerFactory.getLogger(AsyncProcessor.class.getName()); + public AsyncProcessor(I iface) { + super(iface, getProcessMap(new java.util.HashMap>())); + } + + protected AsyncProcessor(I iface, java.util.Map> processMap) { + super(iface, getProcessMap(processMap)); + } + + private static java.util.Map> getProcessMap(java.util.Map> processMap) { + processMap.put("put", new put()); + processMap.put("multi_put", new multi_put()); + processMap.put("remove", new remove()); + processMap.put("multi_remove", new multi_remove()); + processMap.put("get", new get()); + processMap.put("multi_get", new multi_get()); + processMap.put("sortkey_count", new sortkey_count()); + processMap.put("ttl", new ttl()); + processMap.put("get_scanner", new get_scanner()); + processMap.put("scan", new scan()); + processMap.put("clear_scanner", new clear_scanner()); + return processMap; + } + + public static class put extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public put() { + super("put"); + } + + public put_args getEmptyArgsInstance() { + return new put_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(update_response o) { + put_result result = new put_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + put_result result = new put_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, put_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.put(args.update,resultHandler); + } + } + + public static class multi_put extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public multi_put() { + super("multi_put"); + } + + public multi_put_args getEmptyArgsInstance() { + return new multi_put_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(update_response o) { + multi_put_result result = new multi_put_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + multi_put_result result = new multi_put_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, multi_put_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.multi_put(args.request,resultHandler); + } + } + + public static class remove extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public remove() { + super("remove"); + } + + public remove_args getEmptyArgsInstance() { + return new remove_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(update_response o) { + remove_result result = new remove_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + remove_result result = new remove_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, remove_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.remove(args.key,resultHandler); + } + } + + public static class multi_remove extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public multi_remove() { + super("multi_remove"); + } + + public multi_remove_args getEmptyArgsInstance() { + return new multi_remove_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(multi_remove_response o) { + multi_remove_result result = new multi_remove_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + multi_remove_result result = new multi_remove_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, multi_remove_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.multi_remove(args.request,resultHandler); + } + } + + public static class get extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public get() { + super("get"); + } + + public get_args getEmptyArgsInstance() { + return new get_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(read_response o) { + get_result result = new get_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + get_result result = new get_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, get_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.get(args.key,resultHandler); + } + } + + public static class multi_get extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public multi_get() { + super("multi_get"); + } + + public multi_get_args getEmptyArgsInstance() { + return new multi_get_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(multi_get_response o) { + multi_get_result result = new multi_get_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + multi_get_result result = new multi_get_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, multi_get_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.multi_get(args.request,resultHandler); + } + } + + public static class sortkey_count extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public sortkey_count() { + super("sortkey_count"); + } + + public sortkey_count_args getEmptyArgsInstance() { + return new sortkey_count_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(count_response o) { + sortkey_count_result result = new sortkey_count_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + sortkey_count_result result = new sortkey_count_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, sortkey_count_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.sortkey_count(args.hash_key,resultHandler); + } + } + + public static class ttl extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public ttl() { + super("ttl"); + } + + public ttl_args getEmptyArgsInstance() { + return new ttl_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(ttl_response o) { + ttl_result result = new ttl_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + ttl_result result = new ttl_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, ttl_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.ttl(args.key,resultHandler); + } + } + + public static class get_scanner extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public get_scanner() { + super("get_scanner"); + } + + public get_scanner_args getEmptyArgsInstance() { + return new get_scanner_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(scan_response o) { + get_scanner_result result = new get_scanner_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + get_scanner_result result = new get_scanner_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, get_scanner_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.get_scanner(args.request,resultHandler); + } + } + + public static class scan extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public scan() { + super("scan"); + } + + public scan_args getEmptyArgsInstance() { + return new scan_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(scan_response o) { + scan_result result = new scan_result(); + result.success = o; + try { + fcall.sendResponse(fb, result, com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY,seqid); + } catch (com.xiaomi.infra.pegasus.thrift.transport.TTransportException e) { + _LOGGER.error("TTransportException writing to internal frame buffer", e); + fb.close(); + } catch (java.lang.Exception e) { + _LOGGER.error("Exception writing to internal frame buffer", e); + onError(e); + } + } + public void onError(java.lang.Exception e) { + byte msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.REPLY; + com.xiaomi.infra.pegasus.thrift.TSerializable msg; + scan_result result = new scan_result(); + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + return; + } else if (e instanceof com.xiaomi.infra.pegasus.thrift.TApplicationException) { + _LOGGER.error("TApplicationException inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = (com.xiaomi.infra.pegasus.thrift.TApplicationException)e; + } else { + _LOGGER.error("Exception inside handler", e); + msgType = com.xiaomi.infra.pegasus.thrift.protocol.TMessageType.EXCEPTION; + msg = new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage()); + } + try { + fcall.sendResponse(fb,msg,msgType,seqid); + } catch (java.lang.Exception ex) { + _LOGGER.error("Exception writing to internal frame buffer", ex); + fb.close(); + } + } + }; + } + + protected boolean isOneway() { + return false; + } + + public void start(I iface, scan_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.scan(args.request,resultHandler); + } + } + + public static class clear_scanner extends com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction { + public clear_scanner() { + super("clear_scanner"); + } + + public clear_scanner_args getEmptyArgsInstance() { + return new clear_scanner_args(); + } + + public com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback getResultHandler(final com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, final int seqid) { + final com.xiaomi.infra.pegasus.thrift.AsyncProcessFunction fcall = this; + return new com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback() { + public void onComplete(Void o) { + } + public void onError(java.lang.Exception e) { + if (e instanceof com.xiaomi.infra.pegasus.thrift.transport.TTransportException) { + _LOGGER.error("TTransportException inside handler", e); + fb.close(); + } else { + _LOGGER.error("Exception inside oneway handler", e); + } + } + }; + } + + protected boolean isOneway() { + return true; + } + + public void start(I iface, clear_scanner_args args, com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback resultHandler) throws com.xiaomi.infra.pegasus.thrift.TException { + iface.clear_scanner(args.context_id,resultHandler); + } + } + + } + + public static class put_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("put_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField UPDATE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("update", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new put_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new put_argsTupleSchemeFactory(); + + public update_request update; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + UPDATE((short)1, "update"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // UPDATE + return UPDATE; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.UPDATE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("update", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, update_request.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(put_args.class, metaDataMap); + } + + public put_args() { + } + + public put_args( + update_request update) + { + this(); + this.update = update; + } + + /** + * Performs a deep copy on other. + */ + public put_args(put_args other) { + if (other.isSetUpdate()) { + this.update = new update_request(other.update); + } + } + + public put_args deepCopy() { + return new put_args(this); + } + + @Override + public void clear() { + this.update = null; + } + + public update_request getUpdate() { + return this.update; + } + + public put_args setUpdate(update_request update) { + this.update = update; + return this; + } + + public void unsetUpdate() { + this.update = null; + } + + /** Returns true if field update is set (has been assigned a value) and false otherwise */ + public boolean isSetUpdate() { + return this.update != null; + } + + public void setUpdateIsSet(boolean value) { + if (!value) { + this.update = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case UPDATE: + if (value == null) { + unsetUpdate(); + } else { + setUpdate((update_request)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case UPDATE: + return getUpdate(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case UPDATE: + return isSetUpdate(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof put_args) + return this.equals((put_args)that); + return false; + } + + public boolean equals(put_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_update = true && this.isSetUpdate(); + boolean that_present_update = true && that.isSetUpdate(); + if (this_present_update || that_present_update) { + if (!(this_present_update && that_present_update)) + return false; + if (!this.update.equals(that.update)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetUpdate()) ? 131071 : 524287); + if (isSetUpdate()) + hashCode = hashCode * 8191 + update.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(put_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetUpdate()).compareTo(other.isSetUpdate()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetUpdate()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.update, other.update); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("put_args("); + boolean first = true; + + sb.append("update:"); + if (this.update == null) { + sb.append("null"); + } else { + sb.append(this.update); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (update != null) { + update.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class put_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public put_argsStandardScheme getScheme() { + return new put_argsStandardScheme(); + } + } + + private static class put_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, put_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // UPDATE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.update = new update_request(); + struct.update.read(iprot); + struct.setUpdateIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, put_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.update != null) { + oprot.writeFieldBegin(UPDATE_FIELD_DESC); + struct.update.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class put_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public put_argsTupleScheme getScheme() { + return new put_argsTupleScheme(); + } + } + + private static class put_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, put_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetUpdate()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetUpdate()) { + struct.update.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, put_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.update = new update_request(); + struct.update.read(iprot); + struct.setUpdateIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class put_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("put_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new put_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new put_resultTupleSchemeFactory(); + + public update_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, update_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(put_result.class, metaDataMap); + } + + public put_result() { + } + + public put_result( + update_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public put_result(put_result other) { + if (other.isSetSuccess()) { + this.success = new update_response(other.success); + } + } + + public put_result deepCopy() { + return new put_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public update_response getSuccess() { + return this.success; + } + + public put_result setSuccess(update_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((update_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof put_result) + return this.equals((put_result)that); + return false; + } + + public boolean equals(put_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(put_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("put_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class put_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public put_resultStandardScheme getScheme() { + return new put_resultStandardScheme(); + } + } + + private static class put_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, put_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new update_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, put_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class put_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public put_resultTupleScheme getScheme() { + return new put_resultTupleScheme(); + } + } + + private static class put_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, put_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, put_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new update_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class multi_put_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_put_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField REQUEST_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("request", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_put_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_put_argsTupleSchemeFactory(); + + public multi_put_request request; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + REQUEST((short)1, "request"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // REQUEST + return REQUEST; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.REQUEST, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("request", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, multi_put_request.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_put_args.class, metaDataMap); + } + + public multi_put_args() { + } + + public multi_put_args( + multi_put_request request) + { + this(); + this.request = request; + } + + /** + * Performs a deep copy on other. + */ + public multi_put_args(multi_put_args other) { + if (other.isSetRequest()) { + this.request = new multi_put_request(other.request); + } + } + + public multi_put_args deepCopy() { + return new multi_put_args(this); + } + + @Override + public void clear() { + this.request = null; + } + + public multi_put_request getRequest() { + return this.request; + } + + public multi_put_args setRequest(multi_put_request request) { + this.request = request; + return this; + } + + public void unsetRequest() { + this.request = null; + } + + /** Returns true if field request is set (has been assigned a value) and false otherwise */ + public boolean isSetRequest() { + return this.request != null; + } + + public void setRequestIsSet(boolean value) { + if (!value) { + this.request = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case REQUEST: + if (value == null) { + unsetRequest(); + } else { + setRequest((multi_put_request)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case REQUEST: + return getRequest(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case REQUEST: + return isSetRequest(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_put_args) + return this.equals((multi_put_args)that); + return false; + } + + public boolean equals(multi_put_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_request = true && this.isSetRequest(); + boolean that_present_request = true && that.isSetRequest(); + if (this_present_request || that_present_request) { + if (!(this_present_request && that_present_request)) + return false; + if (!this.request.equals(that.request)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetRequest()) ? 131071 : 524287); + if (isSetRequest()) + hashCode = hashCode * 8191 + request.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(multi_put_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetRequest()).compareTo(other.isSetRequest()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetRequest()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.request, other.request); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_put_args("); + boolean first = true; + + sb.append("request:"); + if (this.request == null) { + sb.append("null"); + } else { + sb.append(this.request); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (request != null) { + request.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_put_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_put_argsStandardScheme getScheme() { + return new multi_put_argsStandardScheme(); + } + } + + private static class multi_put_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_put_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // REQUEST + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.request = new multi_put_request(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_put_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.request != null) { + oprot.writeFieldBegin(REQUEST_FIELD_DESC); + struct.request.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_put_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_put_argsTupleScheme getScheme() { + return new multi_put_argsTupleScheme(); + } + } + + private static class multi_put_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_put_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetRequest()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetRequest()) { + struct.request.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_put_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.request = new multi_put_request(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class multi_put_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_put_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_put_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_put_resultTupleSchemeFactory(); + + public update_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, update_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_put_result.class, metaDataMap); + } + + public multi_put_result() { + } + + public multi_put_result( + update_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public multi_put_result(multi_put_result other) { + if (other.isSetSuccess()) { + this.success = new update_response(other.success); + } + } + + public multi_put_result deepCopy() { + return new multi_put_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public update_response getSuccess() { + return this.success; + } + + public multi_put_result setSuccess(update_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((update_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_put_result) + return this.equals((multi_put_result)that); + return false; + } + + public boolean equals(multi_put_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(multi_put_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_put_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_put_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_put_resultStandardScheme getScheme() { + return new multi_put_resultStandardScheme(); + } + } + + private static class multi_put_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_put_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new update_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_put_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_put_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_put_resultTupleScheme getScheme() { + return new multi_put_resultTupleScheme(); + } + } + + private static class multi_put_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_put_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_put_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new update_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class remove_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("remove_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new remove_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new remove_argsTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.blob key; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + KEY((short)1, "key"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // KEY + return KEY; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(remove_args.class, metaDataMap); + } + + public remove_args() { + } + + public remove_args( + com.xiaomi.infra.pegasus.base.blob key) + { + this(); + this.key = key; + } + + /** + * Performs a deep copy on other. + */ + public remove_args(remove_args other) { + if (other.isSetKey()) { + this.key = new com.xiaomi.infra.pegasus.base.blob(other.key); + } + } + + public remove_args deepCopy() { + return new remove_args(this); + } + + @Override + public void clear() { + this.key = null; + } + + public com.xiaomi.infra.pegasus.base.blob getKey() { + return this.key; + } + + public remove_args setKey(com.xiaomi.infra.pegasus.base.blob key) { + this.key = key; + return this; + } + + public void unsetKey() { + this.key = null; + } + + /** Returns true if field key is set (has been assigned a value) and false otherwise */ + public boolean isSetKey() { + return this.key != null; + } + + public void setKeyIsSet(boolean value) { + if (!value) { + this.key = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case KEY: + if (value == null) { + unsetKey(); + } else { + setKey((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case KEY: + return getKey(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case KEY: + return isSetKey(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof remove_args) + return this.equals((remove_args)that); + return false; + } + + public boolean equals(remove_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_key = true && this.isSetKey(); + boolean that_present_key = true && that.isSetKey(); + if (this_present_key || that_present_key) { + if (!(this_present_key && that_present_key)) + return false; + if (!this.key.equals(that.key)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetKey()) ? 131071 : 524287); + if (isSetKey()) + hashCode = hashCode * 8191 + key.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(remove_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetKey()).compareTo(other.isSetKey()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetKey()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.key, other.key); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("remove_args("); + boolean first = true; + + sb.append("key:"); + if (this.key == null) { + sb.append("null"); + } else { + sb.append(this.key); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (key != null) { + key.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class remove_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public remove_argsStandardScheme getScheme() { + return new remove_argsStandardScheme(); + } + } + + private static class remove_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, remove_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.key = new com.xiaomi.infra.pegasus.base.blob(); + struct.key.read(iprot); + struct.setKeyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, remove_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.key != null) { + oprot.writeFieldBegin(KEY_FIELD_DESC); + struct.key.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class remove_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public remove_argsTupleScheme getScheme() { + return new remove_argsTupleScheme(); + } + } + + private static class remove_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, remove_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetKey()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetKey()) { + struct.key.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, remove_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.key = new com.xiaomi.infra.pegasus.base.blob(); + struct.key.read(iprot); + struct.setKeyIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class remove_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("remove_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new remove_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new remove_resultTupleSchemeFactory(); + + public update_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, update_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(remove_result.class, metaDataMap); + } + + public remove_result() { + } + + public remove_result( + update_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public remove_result(remove_result other) { + if (other.isSetSuccess()) { + this.success = new update_response(other.success); + } + } + + public remove_result deepCopy() { + return new remove_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public update_response getSuccess() { + return this.success; + } + + public remove_result setSuccess(update_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((update_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof remove_result) + return this.equals((remove_result)that); + return false; + } + + public boolean equals(remove_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(remove_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("remove_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class remove_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public remove_resultStandardScheme getScheme() { + return new remove_resultStandardScheme(); + } + } + + private static class remove_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, remove_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new update_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, remove_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class remove_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public remove_resultTupleScheme getScheme() { + return new remove_resultTupleScheme(); + } + } + + private static class remove_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, remove_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, remove_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new update_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class multi_remove_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_remove_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField REQUEST_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("request", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_remove_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_remove_argsTupleSchemeFactory(); + + public multi_remove_request request; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + REQUEST((short)1, "request"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // REQUEST + return REQUEST; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.REQUEST, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("request", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, multi_remove_request.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_remove_args.class, metaDataMap); + } + + public multi_remove_args() { + } + + public multi_remove_args( + multi_remove_request request) + { + this(); + this.request = request; + } + + /** + * Performs a deep copy on other. + */ + public multi_remove_args(multi_remove_args other) { + if (other.isSetRequest()) { + this.request = new multi_remove_request(other.request); + } + } + + public multi_remove_args deepCopy() { + return new multi_remove_args(this); + } + + @Override + public void clear() { + this.request = null; + } + + public multi_remove_request getRequest() { + return this.request; + } + + public multi_remove_args setRequest(multi_remove_request request) { + this.request = request; + return this; + } + + public void unsetRequest() { + this.request = null; + } + + /** Returns true if field request is set (has been assigned a value) and false otherwise */ + public boolean isSetRequest() { + return this.request != null; + } + + public void setRequestIsSet(boolean value) { + if (!value) { + this.request = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case REQUEST: + if (value == null) { + unsetRequest(); + } else { + setRequest((multi_remove_request)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case REQUEST: + return getRequest(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case REQUEST: + return isSetRequest(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_remove_args) + return this.equals((multi_remove_args)that); + return false; + } + + public boolean equals(multi_remove_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_request = true && this.isSetRequest(); + boolean that_present_request = true && that.isSetRequest(); + if (this_present_request || that_present_request) { + if (!(this_present_request && that_present_request)) + return false; + if (!this.request.equals(that.request)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetRequest()) ? 131071 : 524287); + if (isSetRequest()) + hashCode = hashCode * 8191 + request.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(multi_remove_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetRequest()).compareTo(other.isSetRequest()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetRequest()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.request, other.request); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_remove_args("); + boolean first = true; + + sb.append("request:"); + if (this.request == null) { + sb.append("null"); + } else { + sb.append(this.request); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (request != null) { + request.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_remove_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_remove_argsStandardScheme getScheme() { + return new multi_remove_argsStandardScheme(); + } + } + + private static class multi_remove_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_remove_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // REQUEST + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.request = new multi_remove_request(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_remove_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.request != null) { + oprot.writeFieldBegin(REQUEST_FIELD_DESC); + struct.request.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_remove_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_remove_argsTupleScheme getScheme() { + return new multi_remove_argsTupleScheme(); + } + } + + private static class multi_remove_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_remove_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetRequest()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetRequest()) { + struct.request.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_remove_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.request = new multi_remove_request(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class multi_remove_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_remove_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_remove_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_remove_resultTupleSchemeFactory(); + + public multi_remove_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, multi_remove_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_remove_result.class, metaDataMap); + } + + public multi_remove_result() { + } + + public multi_remove_result( + multi_remove_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public multi_remove_result(multi_remove_result other) { + if (other.isSetSuccess()) { + this.success = new multi_remove_response(other.success); + } + } + + public multi_remove_result deepCopy() { + return new multi_remove_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public multi_remove_response getSuccess() { + return this.success; + } + + public multi_remove_result setSuccess(multi_remove_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((multi_remove_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_remove_result) + return this.equals((multi_remove_result)that); + return false; + } + + public boolean equals(multi_remove_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(multi_remove_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_remove_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_remove_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_remove_resultStandardScheme getScheme() { + return new multi_remove_resultStandardScheme(); + } + } + + private static class multi_remove_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_remove_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new multi_remove_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_remove_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_remove_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_remove_resultTupleScheme getScheme() { + return new multi_remove_resultTupleScheme(); + } + } + + private static class multi_remove_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_remove_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_remove_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new multi_remove_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class get_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("get_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new get_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new get_argsTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.blob key; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + KEY((short)1, "key"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // KEY + return KEY; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(get_args.class, metaDataMap); + } + + public get_args() { + } + + public get_args( + com.xiaomi.infra.pegasus.base.blob key) + { + this(); + this.key = key; + } + + /** + * Performs a deep copy on other. + */ + public get_args(get_args other) { + if (other.isSetKey()) { + this.key = new com.xiaomi.infra.pegasus.base.blob(other.key); + } + } + + public get_args deepCopy() { + return new get_args(this); + } + + @Override + public void clear() { + this.key = null; + } + + public com.xiaomi.infra.pegasus.base.blob getKey() { + return this.key; + } + + public get_args setKey(com.xiaomi.infra.pegasus.base.blob key) { + this.key = key; + return this; + } + + public void unsetKey() { + this.key = null; + } + + /** Returns true if field key is set (has been assigned a value) and false otherwise */ + public boolean isSetKey() { + return this.key != null; + } + + public void setKeyIsSet(boolean value) { + if (!value) { + this.key = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case KEY: + if (value == null) { + unsetKey(); + } else { + setKey((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case KEY: + return getKey(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case KEY: + return isSetKey(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof get_args) + return this.equals((get_args)that); + return false; + } + + public boolean equals(get_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_key = true && this.isSetKey(); + boolean that_present_key = true && that.isSetKey(); + if (this_present_key || that_present_key) { + if (!(this_present_key && that_present_key)) + return false; + if (!this.key.equals(that.key)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetKey()) ? 131071 : 524287); + if (isSetKey()) + hashCode = hashCode * 8191 + key.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(get_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetKey()).compareTo(other.isSetKey()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetKey()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.key, other.key); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("get_args("); + boolean first = true; + + sb.append("key:"); + if (this.key == null) { + sb.append("null"); + } else { + sb.append(this.key); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (key != null) { + key.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class get_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public get_argsStandardScheme getScheme() { + return new get_argsStandardScheme(); + } + } + + private static class get_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, get_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.key = new com.xiaomi.infra.pegasus.base.blob(); + struct.key.read(iprot); + struct.setKeyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, get_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.key != null) { + oprot.writeFieldBegin(KEY_FIELD_DESC); + struct.key.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class get_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public get_argsTupleScheme getScheme() { + return new get_argsTupleScheme(); + } + } + + private static class get_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, get_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetKey()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetKey()) { + struct.key.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, get_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.key = new com.xiaomi.infra.pegasus.base.blob(); + struct.key.read(iprot); + struct.setKeyIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class get_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("get_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new get_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new get_resultTupleSchemeFactory(); + + public read_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, read_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(get_result.class, metaDataMap); + } + + public get_result() { + } + + public get_result( + read_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public get_result(get_result other) { + if (other.isSetSuccess()) { + this.success = new read_response(other.success); + } + } + + public get_result deepCopy() { + return new get_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public read_response getSuccess() { + return this.success; + } + + public get_result setSuccess(read_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((read_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof get_result) + return this.equals((get_result)that); + return false; + } + + public boolean equals(get_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(get_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("get_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class get_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public get_resultStandardScheme getScheme() { + return new get_resultStandardScheme(); + } + } + + private static class get_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, get_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new read_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, get_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class get_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public get_resultTupleScheme getScheme() { + return new get_resultTupleScheme(); + } + } + + private static class get_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, get_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, get_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new read_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class multi_get_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_get_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField REQUEST_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("request", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_get_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_get_argsTupleSchemeFactory(); + + public multi_get_request request; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + REQUEST((short)1, "request"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // REQUEST + return REQUEST; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.REQUEST, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("request", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, multi_get_request.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_get_args.class, metaDataMap); + } + + public multi_get_args() { + } + + public multi_get_args( + multi_get_request request) + { + this(); + this.request = request; + } + + /** + * Performs a deep copy on other. + */ + public multi_get_args(multi_get_args other) { + if (other.isSetRequest()) { + this.request = new multi_get_request(other.request); + } + } + + public multi_get_args deepCopy() { + return new multi_get_args(this); + } + + @Override + public void clear() { + this.request = null; + } + + public multi_get_request getRequest() { + return this.request; + } + + public multi_get_args setRequest(multi_get_request request) { + this.request = request; + return this; + } + + public void unsetRequest() { + this.request = null; + } + + /** Returns true if field request is set (has been assigned a value) and false otherwise */ + public boolean isSetRequest() { + return this.request != null; + } + + public void setRequestIsSet(boolean value) { + if (!value) { + this.request = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case REQUEST: + if (value == null) { + unsetRequest(); + } else { + setRequest((multi_get_request)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case REQUEST: + return getRequest(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case REQUEST: + return isSetRequest(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_get_args) + return this.equals((multi_get_args)that); + return false; + } + + public boolean equals(multi_get_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_request = true && this.isSetRequest(); + boolean that_present_request = true && that.isSetRequest(); + if (this_present_request || that_present_request) { + if (!(this_present_request && that_present_request)) + return false; + if (!this.request.equals(that.request)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetRequest()) ? 131071 : 524287); + if (isSetRequest()) + hashCode = hashCode * 8191 + request.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(multi_get_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetRequest()).compareTo(other.isSetRequest()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetRequest()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.request, other.request); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_get_args("); + boolean first = true; + + sb.append("request:"); + if (this.request == null) { + sb.append("null"); + } else { + sb.append(this.request); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (request != null) { + request.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_get_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_get_argsStandardScheme getScheme() { + return new multi_get_argsStandardScheme(); + } + } + + private static class multi_get_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_get_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // REQUEST + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.request = new multi_get_request(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_get_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.request != null) { + oprot.writeFieldBegin(REQUEST_FIELD_DESC); + struct.request.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_get_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_get_argsTupleScheme getScheme() { + return new multi_get_argsTupleScheme(); + } + } + + private static class multi_get_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_get_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetRequest()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetRequest()) { + struct.request.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_get_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.request = new multi_get_request(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class multi_get_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("multi_get_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new multi_get_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new multi_get_resultTupleSchemeFactory(); + + public multi_get_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, multi_get_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(multi_get_result.class, metaDataMap); + } + + public multi_get_result() { + } + + public multi_get_result( + multi_get_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public multi_get_result(multi_get_result other) { + if (other.isSetSuccess()) { + this.success = new multi_get_response(other.success); + } + } + + public multi_get_result deepCopy() { + return new multi_get_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public multi_get_response getSuccess() { + return this.success; + } + + public multi_get_result setSuccess(multi_get_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((multi_get_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof multi_get_result) + return this.equals((multi_get_result)that); + return false; + } + + public boolean equals(multi_get_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(multi_get_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("multi_get_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class multi_get_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_get_resultStandardScheme getScheme() { + return new multi_get_resultStandardScheme(); + } + } + + private static class multi_get_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, multi_get_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new multi_get_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, multi_get_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class multi_get_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public multi_get_resultTupleScheme getScheme() { + return new multi_get_resultTupleScheme(); + } + } + + private static class multi_get_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_get_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, multi_get_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new multi_get_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class sortkey_count_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("sortkey_count_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField HASH_KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("hash_key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new sortkey_count_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new sortkey_count_argsTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.blob hash_key; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + HASH_KEY((short)1, "hash_key"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // HASH_KEY + return HASH_KEY; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.HASH_KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("hash_key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(sortkey_count_args.class, metaDataMap); + } + + public sortkey_count_args() { + } + + public sortkey_count_args( + com.xiaomi.infra.pegasus.base.blob hash_key) + { + this(); + this.hash_key = hash_key; + } + + /** + * Performs a deep copy on other. + */ + public sortkey_count_args(sortkey_count_args other) { + if (other.isSetHash_key()) { + this.hash_key = new com.xiaomi.infra.pegasus.base.blob(other.hash_key); + } + } + + public sortkey_count_args deepCopy() { + return new sortkey_count_args(this); + } + + @Override + public void clear() { + this.hash_key = null; + } + + public com.xiaomi.infra.pegasus.base.blob getHash_key() { + return this.hash_key; + } + + public sortkey_count_args setHash_key(com.xiaomi.infra.pegasus.base.blob hash_key) { + this.hash_key = hash_key; + return this; + } + + public void unsetHash_key() { + this.hash_key = null; + } + + /** Returns true if field hash_key is set (has been assigned a value) and false otherwise */ + public boolean isSetHash_key() { + return this.hash_key != null; + } + + public void setHash_keyIsSet(boolean value) { + if (!value) { + this.hash_key = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case HASH_KEY: + if (value == null) { + unsetHash_key(); + } else { + setHash_key((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case HASH_KEY: + return getHash_key(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case HASH_KEY: + return isSetHash_key(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof sortkey_count_args) + return this.equals((sortkey_count_args)that); + return false; + } + + public boolean equals(sortkey_count_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_hash_key = true && this.isSetHash_key(); + boolean that_present_hash_key = true && that.isSetHash_key(); + if (this_present_hash_key || that_present_hash_key) { + if (!(this_present_hash_key && that_present_hash_key)) + return false; + if (!this.hash_key.equals(that.hash_key)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetHash_key()) ? 131071 : 524287); + if (isSetHash_key()) + hashCode = hashCode * 8191 + hash_key.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(sortkey_count_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetHash_key()).compareTo(other.isSetHash_key()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetHash_key()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.hash_key, other.hash_key); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("sortkey_count_args("); + boolean first = true; + + sb.append("hash_key:"); + if (this.hash_key == null) { + sb.append("null"); + } else { + sb.append(this.hash_key); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (hash_key != null) { + hash_key.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class sortkey_count_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public sortkey_count_argsStandardScheme getScheme() { + return new sortkey_count_argsStandardScheme(); + } + } + + private static class sortkey_count_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, sortkey_count_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // HASH_KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.hash_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.hash_key.read(iprot); + struct.setHash_keyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, sortkey_count_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.hash_key != null) { + oprot.writeFieldBegin(HASH_KEY_FIELD_DESC); + struct.hash_key.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class sortkey_count_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public sortkey_count_argsTupleScheme getScheme() { + return new sortkey_count_argsTupleScheme(); + } + } + + private static class sortkey_count_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, sortkey_count_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetHash_key()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetHash_key()) { + struct.hash_key.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, sortkey_count_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.hash_key = new com.xiaomi.infra.pegasus.base.blob(); + struct.hash_key.read(iprot); + struct.setHash_keyIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class sortkey_count_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("sortkey_count_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new sortkey_count_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new sortkey_count_resultTupleSchemeFactory(); + + public count_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, count_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(sortkey_count_result.class, metaDataMap); + } + + public sortkey_count_result() { + } + + public sortkey_count_result( + count_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public sortkey_count_result(sortkey_count_result other) { + if (other.isSetSuccess()) { + this.success = new count_response(other.success); + } + } + + public sortkey_count_result deepCopy() { + return new sortkey_count_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public count_response getSuccess() { + return this.success; + } + + public sortkey_count_result setSuccess(count_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((count_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof sortkey_count_result) + return this.equals((sortkey_count_result)that); + return false; + } + + public boolean equals(sortkey_count_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(sortkey_count_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("sortkey_count_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class sortkey_count_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public sortkey_count_resultStandardScheme getScheme() { + return new sortkey_count_resultStandardScheme(); + } + } + + private static class sortkey_count_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, sortkey_count_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new count_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, sortkey_count_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class sortkey_count_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public sortkey_count_resultTupleScheme getScheme() { + return new sortkey_count_resultTupleScheme(); + } + } + + private static class sortkey_count_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, sortkey_count_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, sortkey_count_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new count_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class ttl_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("ttl_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new ttl_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new ttl_argsTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.blob key; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + KEY((short)1, "key"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // KEY + return KEY; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(ttl_args.class, metaDataMap); + } + + public ttl_args() { + } + + public ttl_args( + com.xiaomi.infra.pegasus.base.blob key) + { + this(); + this.key = key; + } + + /** + * Performs a deep copy on other. + */ + public ttl_args(ttl_args other) { + if (other.isSetKey()) { + this.key = new com.xiaomi.infra.pegasus.base.blob(other.key); + } + } + + public ttl_args deepCopy() { + return new ttl_args(this); + } + + @Override + public void clear() { + this.key = null; + } + + public com.xiaomi.infra.pegasus.base.blob getKey() { + return this.key; + } + + public ttl_args setKey(com.xiaomi.infra.pegasus.base.blob key) { + this.key = key; + return this; + } + + public void unsetKey() { + this.key = null; + } + + /** Returns true if field key is set (has been assigned a value) and false otherwise */ + public boolean isSetKey() { + return this.key != null; + } + + public void setKeyIsSet(boolean value) { + if (!value) { + this.key = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case KEY: + if (value == null) { + unsetKey(); + } else { + setKey((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case KEY: + return getKey(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case KEY: + return isSetKey(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof ttl_args) + return this.equals((ttl_args)that); + return false; + } + + public boolean equals(ttl_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_key = true && this.isSetKey(); + boolean that_present_key = true && that.isSetKey(); + if (this_present_key || that_present_key) { + if (!(this_present_key && that_present_key)) + return false; + if (!this.key.equals(that.key)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetKey()) ? 131071 : 524287); + if (isSetKey()) + hashCode = hashCode * 8191 + key.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(ttl_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetKey()).compareTo(other.isSetKey()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetKey()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.key, other.key); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("ttl_args("); + boolean first = true; + + sb.append("key:"); + if (this.key == null) { + sb.append("null"); + } else { + sb.append(this.key); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (key != null) { + key.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class ttl_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public ttl_argsStandardScheme getScheme() { + return new ttl_argsStandardScheme(); + } + } + + private static class ttl_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, ttl_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.key = new com.xiaomi.infra.pegasus.base.blob(); + struct.key.read(iprot); + struct.setKeyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, ttl_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.key != null) { + oprot.writeFieldBegin(KEY_FIELD_DESC); + struct.key.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class ttl_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public ttl_argsTupleScheme getScheme() { + return new ttl_argsTupleScheme(); + } + } + + private static class ttl_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, ttl_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetKey()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetKey()) { + struct.key.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, ttl_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.key = new com.xiaomi.infra.pegasus.base.blob(); + struct.key.read(iprot); + struct.setKeyIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class ttl_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("ttl_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new ttl_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new ttl_resultTupleSchemeFactory(); + + public ttl_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, ttl_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(ttl_result.class, metaDataMap); + } + + public ttl_result() { + } + + public ttl_result( + ttl_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public ttl_result(ttl_result other) { + if (other.isSetSuccess()) { + this.success = new ttl_response(other.success); + } + } + + public ttl_result deepCopy() { + return new ttl_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public ttl_response getSuccess() { + return this.success; + } + + public ttl_result setSuccess(ttl_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((ttl_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof ttl_result) + return this.equals((ttl_result)that); + return false; + } + + public boolean equals(ttl_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(ttl_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("ttl_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class ttl_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public ttl_resultStandardScheme getScheme() { + return new ttl_resultStandardScheme(); + } + } + + private static class ttl_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, ttl_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new ttl_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, ttl_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class ttl_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public ttl_resultTupleScheme getScheme() { + return new ttl_resultTupleScheme(); + } + } + + private static class ttl_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, ttl_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, ttl_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new ttl_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class get_scanner_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("get_scanner_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField REQUEST_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("request", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new get_scanner_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new get_scanner_argsTupleSchemeFactory(); + + public get_scanner_request request; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + REQUEST((short)1, "request"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // REQUEST + return REQUEST; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.REQUEST, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("request", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, get_scanner_request.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(get_scanner_args.class, metaDataMap); + } + + public get_scanner_args() { + } + + public get_scanner_args( + get_scanner_request request) + { + this(); + this.request = request; + } + + /** + * Performs a deep copy on other. + */ + public get_scanner_args(get_scanner_args other) { + if (other.isSetRequest()) { + this.request = new get_scanner_request(other.request); + } + } + + public get_scanner_args deepCopy() { + return new get_scanner_args(this); + } + + @Override + public void clear() { + this.request = null; + } + + public get_scanner_request getRequest() { + return this.request; + } + + public get_scanner_args setRequest(get_scanner_request request) { + this.request = request; + return this; + } + + public void unsetRequest() { + this.request = null; + } + + /** Returns true if field request is set (has been assigned a value) and false otherwise */ + public boolean isSetRequest() { + return this.request != null; + } + + public void setRequestIsSet(boolean value) { + if (!value) { + this.request = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case REQUEST: + if (value == null) { + unsetRequest(); + } else { + setRequest((get_scanner_request)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case REQUEST: + return getRequest(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case REQUEST: + return isSetRequest(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof get_scanner_args) + return this.equals((get_scanner_args)that); + return false; + } + + public boolean equals(get_scanner_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_request = true && this.isSetRequest(); + boolean that_present_request = true && that.isSetRequest(); + if (this_present_request || that_present_request) { + if (!(this_present_request && that_present_request)) + return false; + if (!this.request.equals(that.request)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetRequest()) ? 131071 : 524287); + if (isSetRequest()) + hashCode = hashCode * 8191 + request.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(get_scanner_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetRequest()).compareTo(other.isSetRequest()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetRequest()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.request, other.request); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("get_scanner_args("); + boolean first = true; + + sb.append("request:"); + if (this.request == null) { + sb.append("null"); + } else { + sb.append(this.request); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (request != null) { + request.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class get_scanner_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public get_scanner_argsStandardScheme getScheme() { + return new get_scanner_argsStandardScheme(); + } + } + + private static class get_scanner_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, get_scanner_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // REQUEST + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.request = new get_scanner_request(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, get_scanner_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.request != null) { + oprot.writeFieldBegin(REQUEST_FIELD_DESC); + struct.request.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class get_scanner_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public get_scanner_argsTupleScheme getScheme() { + return new get_scanner_argsTupleScheme(); + } + } + + private static class get_scanner_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, get_scanner_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetRequest()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetRequest()) { + struct.request.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, get_scanner_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.request = new get_scanner_request(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class get_scanner_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("get_scanner_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new get_scanner_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new get_scanner_resultTupleSchemeFactory(); + + public scan_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, scan_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(get_scanner_result.class, metaDataMap); + } + + public get_scanner_result() { + } + + public get_scanner_result( + scan_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public get_scanner_result(get_scanner_result other) { + if (other.isSetSuccess()) { + this.success = new scan_response(other.success); + } + } + + public get_scanner_result deepCopy() { + return new get_scanner_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public scan_response getSuccess() { + return this.success; + } + + public get_scanner_result setSuccess(scan_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((scan_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof get_scanner_result) + return this.equals((get_scanner_result)that); + return false; + } + + public boolean equals(get_scanner_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(get_scanner_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("get_scanner_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class get_scanner_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public get_scanner_resultStandardScheme getScheme() { + return new get_scanner_resultStandardScheme(); + } + } + + private static class get_scanner_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, get_scanner_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new scan_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, get_scanner_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class get_scanner_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public get_scanner_resultTupleScheme getScheme() { + return new get_scanner_resultTupleScheme(); + } + } + + private static class get_scanner_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, get_scanner_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, get_scanner_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new scan_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class scan_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("scan_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField REQUEST_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("request", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new scan_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new scan_argsTupleSchemeFactory(); + + public scan_request request; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + REQUEST((short)1, "request"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // REQUEST + return REQUEST; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.REQUEST, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("request", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, scan_request.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(scan_args.class, metaDataMap); + } + + public scan_args() { + } + + public scan_args( + scan_request request) + { + this(); + this.request = request; + } + + /** + * Performs a deep copy on other. + */ + public scan_args(scan_args other) { + if (other.isSetRequest()) { + this.request = new scan_request(other.request); + } + } + + public scan_args deepCopy() { + return new scan_args(this); + } + + @Override + public void clear() { + this.request = null; + } + + public scan_request getRequest() { + return this.request; + } + + public scan_args setRequest(scan_request request) { + this.request = request; + return this; + } + + public void unsetRequest() { + this.request = null; + } + + /** Returns true if field request is set (has been assigned a value) and false otherwise */ + public boolean isSetRequest() { + return this.request != null; + } + + public void setRequestIsSet(boolean value) { + if (!value) { + this.request = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case REQUEST: + if (value == null) { + unsetRequest(); + } else { + setRequest((scan_request)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case REQUEST: + return getRequest(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case REQUEST: + return isSetRequest(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof scan_args) + return this.equals((scan_args)that); + return false; + } + + public boolean equals(scan_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_request = true && this.isSetRequest(); + boolean that_present_request = true && that.isSetRequest(); + if (this_present_request || that_present_request) { + if (!(this_present_request && that_present_request)) + return false; + if (!this.request.equals(that.request)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetRequest()) ? 131071 : 524287); + if (isSetRequest()) + hashCode = hashCode * 8191 + request.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(scan_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetRequest()).compareTo(other.isSetRequest()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetRequest()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.request, other.request); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("scan_args("); + boolean first = true; + + sb.append("request:"); + if (this.request == null) { + sb.append("null"); + } else { + sb.append(this.request); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (request != null) { + request.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class scan_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public scan_argsStandardScheme getScheme() { + return new scan_argsStandardScheme(); + } + } + + private static class scan_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, scan_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // REQUEST + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.request = new scan_request(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, scan_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.request != null) { + oprot.writeFieldBegin(REQUEST_FIELD_DESC); + struct.request.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class scan_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public scan_argsTupleScheme getScheme() { + return new scan_argsTupleScheme(); + } + } + + private static class scan_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, scan_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetRequest()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetRequest()) { + struct.request.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, scan_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.request = new scan_request(); + struct.request.read(iprot); + struct.setRequestIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class scan_result implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("scan_result"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SUCCESS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("success", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)0); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new scan_resultStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new scan_resultTupleSchemeFactory(); + + public scan_response success; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + SUCCESS((short)0, "success"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 0: // SUCCESS + return SUCCESS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.SUCCESS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("success", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, scan_response.class))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(scan_result.class, metaDataMap); + } + + public scan_result() { + } + + public scan_result( + scan_response success) + { + this(); + this.success = success; + } + + /** + * Performs a deep copy on other. + */ + public scan_result(scan_result other) { + if (other.isSetSuccess()) { + this.success = new scan_response(other.success); + } + } + + public scan_result deepCopy() { + return new scan_result(this); + } + + @Override + public void clear() { + this.success = null; + } + + public scan_response getSuccess() { + return this.success; + } + + public scan_result setSuccess(scan_response success) { + this.success = success; + return this; + } + + public void unsetSuccess() { + this.success = null; + } + + /** Returns true if field success is set (has been assigned a value) and false otherwise */ + public boolean isSetSuccess() { + return this.success != null; + } + + public void setSuccessIsSet(boolean value) { + if (!value) { + this.success = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case SUCCESS: + if (value == null) { + unsetSuccess(); + } else { + setSuccess((scan_response)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case SUCCESS: + return getSuccess(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case SUCCESS: + return isSetSuccess(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof scan_result) + return this.equals((scan_result)that); + return false; + } + + public boolean equals(scan_result that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_success = true && this.isSetSuccess(); + boolean that_present_success = true && that.isSetSuccess(); + if (this_present_success || that_present_success) { + if (!(this_present_success && that_present_success)) + return false; + if (!this.success.equals(that.success)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetSuccess()) ? 131071 : 524287); + if (isSetSuccess()) + hashCode = hashCode * 8191 + success.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(scan_result other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSuccess()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.success, other.success); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("scan_result("); + boolean first = true; + + sb.append("success:"); + if (this.success == null) { + sb.append("null"); + } else { + sb.append(this.success); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (success != null) { + success.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class scan_resultStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public scan_resultStandardScheme getScheme() { + return new scan_resultStandardScheme(); + } + } + + private static class scan_resultStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, scan_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 0: // SUCCESS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.success = new scan_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, scan_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.success != null) { + oprot.writeFieldBegin(SUCCESS_FIELD_DESC); + struct.success.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class scan_resultTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public scan_resultTupleScheme getScheme() { + return new scan_resultTupleScheme(); + } + } + + private static class scan_resultTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, scan_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetSuccess()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetSuccess()) { + struct.success.write(oprot); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, scan_result struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.success = new scan_response(); + struct.success.read(iprot); + struct.setSuccessIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + + public static class clear_scanner_args implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("clear_scanner_args"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField CONTEXT_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("context_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I64, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new clear_scanner_argsStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new clear_scanner_argsTupleSchemeFactory(); + + public long context_id; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + CONTEXT_ID((short)1, "context_id"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // CONTEXT_ID + return CONTEXT_ID; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __CONTEXT_ID_ISSET_ID = 0; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.CONTEXT_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("context_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I64))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(clear_scanner_args.class, metaDataMap); + } + + public clear_scanner_args() { + } + + public clear_scanner_args( + long context_id) + { + this(); + this.context_id = context_id; + setContext_idIsSet(true); + } + + /** + * Performs a deep copy on other. + */ + public clear_scanner_args(clear_scanner_args other) { + __isset_bitfield = other.__isset_bitfield; + this.context_id = other.context_id; + } + + public clear_scanner_args deepCopy() { + return new clear_scanner_args(this); + } + + @Override + public void clear() { + setContext_idIsSet(false); + this.context_id = 0; + } + + public long getContext_id() { + return this.context_id; + } + + public clear_scanner_args setContext_id(long context_id) { + this.context_id = context_id; + setContext_idIsSet(true); + return this; + } + + public void unsetContext_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __CONTEXT_ID_ISSET_ID); + } + + /** Returns true if field context_id is set (has been assigned a value) and false otherwise */ + public boolean isSetContext_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __CONTEXT_ID_ISSET_ID); + } + + public void setContext_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __CONTEXT_ID_ISSET_ID, value); + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case CONTEXT_ID: + if (value == null) { + unsetContext_id(); + } else { + setContext_id((java.lang.Long)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case CONTEXT_ID: + return getContext_id(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case CONTEXT_ID: + return isSetContext_id(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof clear_scanner_args) + return this.equals((clear_scanner_args)that); + return false; + } + + public boolean equals(clear_scanner_args that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_context_id = true; + boolean that_present_context_id = true; + if (this_present_context_id || that_present_context_id) { + if (!(this_present_context_id && that_present_context_id)) + return false; + if (this.context_id != that.context_id) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + com.xiaomi.infra.pegasus.thrift.TBaseHelper.hashCode(context_id); + + return hashCode; + } + + @Override + public int compareTo(clear_scanner_args other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetContext_id()).compareTo(other.isSetContext_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetContext_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.context_id, other.context_id); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("clear_scanner_args("); + boolean first = true; + + sb.append("context_id:"); + sb.append(this.context_id); + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class clear_scanner_argsStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public clear_scanner_argsStandardScheme getScheme() { + return new clear_scanner_argsStandardScheme(); + } + } + + private static class clear_scanner_argsStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, clear_scanner_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // CONTEXT_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I64) { + struct.context_id = iprot.readI64(); + struct.setContext_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, clear_scanner_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldBegin(CONTEXT_ID_FIELD_DESC); + oprot.writeI64(struct.context_id); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class clear_scanner_argsTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public clear_scanner_argsTupleScheme getScheme() { + return new clear_scanner_argsTupleScheme(); + } + } + + private static class clear_scanner_argsTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, clear_scanner_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetContext_id()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetContext_id()) { + oprot.writeI64(struct.context_id); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, clear_scanner_args struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.context_id = iprot.readI64(); + struct.setContext_idIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/scan_request.java b/src/main/java/com/xiaomi/infra/pegasus/apps/scan_request.java new file mode 100644 index 00000000..b4fdfcd4 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/scan_request.java @@ -0,0 +1,371 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class scan_request implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("scan_request"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField CONTEXT_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("context_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I64, (short)1); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new scan_requestStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new scan_requestTupleSchemeFactory(); + + public long context_id; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + CONTEXT_ID((short)1, "context_id"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // CONTEXT_ID + return CONTEXT_ID; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __CONTEXT_ID_ISSET_ID = 0; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.CONTEXT_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("context_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I64))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(scan_request.class, metaDataMap); + } + + public scan_request() { + } + + public scan_request( + long context_id) + { + this(); + this.context_id = context_id; + setContext_idIsSet(true); + } + + /** + * Performs a deep copy on other. + */ + public scan_request(scan_request other) { + __isset_bitfield = other.__isset_bitfield; + this.context_id = other.context_id; + } + + public scan_request deepCopy() { + return new scan_request(this); + } + + @Override + public void clear() { + setContext_idIsSet(false); + this.context_id = 0; + } + + public long getContext_id() { + return this.context_id; + } + + public scan_request setContext_id(long context_id) { + this.context_id = context_id; + setContext_idIsSet(true); + return this; + } + + public void unsetContext_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __CONTEXT_ID_ISSET_ID); + } + + /** Returns true if field context_id is set (has been assigned a value) and false otherwise */ + public boolean isSetContext_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __CONTEXT_ID_ISSET_ID); + } + + public void setContext_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __CONTEXT_ID_ISSET_ID, value); + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case CONTEXT_ID: + if (value == null) { + unsetContext_id(); + } else { + setContext_id((java.lang.Long)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case CONTEXT_ID: + return getContext_id(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case CONTEXT_ID: + return isSetContext_id(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof scan_request) + return this.equals((scan_request)that); + return false; + } + + public boolean equals(scan_request that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_context_id = true; + boolean that_present_context_id = true; + if (this_present_context_id || that_present_context_id) { + if (!(this_present_context_id && that_present_context_id)) + return false; + if (this.context_id != that.context_id) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + com.xiaomi.infra.pegasus.thrift.TBaseHelper.hashCode(context_id); + + return hashCode; + } + + @Override + public int compareTo(scan_request other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetContext_id()).compareTo(other.isSetContext_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetContext_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.context_id, other.context_id); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("scan_request("); + boolean first = true; + + sb.append("context_id:"); + sb.append(this.context_id); + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class scan_requestStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public scan_requestStandardScheme getScheme() { + return new scan_requestStandardScheme(); + } + } + + private static class scan_requestStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, scan_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // CONTEXT_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I64) { + struct.context_id = iprot.readI64(); + struct.setContext_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, scan_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldBegin(CONTEXT_ID_FIELD_DESC); + oprot.writeI64(struct.context_id); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class scan_requestTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public scan_requestTupleScheme getScheme() { + return new scan_requestTupleScheme(); + } + } + + private static class scan_requestTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, scan_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetContext_id()) { + optionals.set(0); + } + oprot.writeBitSet(optionals, 1); + if (struct.isSetContext_id()) { + oprot.writeI64(struct.context_id); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, scan_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(1); + if (incoming.get(0)) { + struct.context_id = iprot.readI64(); + struct.setContext_idIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/scan_response.java b/src/main/java/com/xiaomi/infra/pegasus/apps/scan_response.java new file mode 100644 index 00000000..8b96eddb --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/scan_response.java @@ -0,0 +1,921 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class scan_response implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("scan_response"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField ERROR_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("error", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField KVS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("kvs", com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField CONTEXT_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("context_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I64, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField APP_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("app_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PARTITION_INDEX_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("partition_index", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)5); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SERVER_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("server", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING, (short)6); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new scan_responseStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new scan_responseTupleSchemeFactory(); + + public int error; // required + public java.util.List kvs; // required + public long context_id; // required + public int app_id; // required + public int partition_index; // required + public java.lang.String server; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + ERROR((short)1, "error"), + KVS((short)2, "kvs"), + CONTEXT_ID((short)3, "context_id"), + APP_ID((short)4, "app_id"), + PARTITION_INDEX((short)5, "partition_index"), + SERVER((short)6, "server"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // ERROR + return ERROR; + case 2: // KVS + return KVS; + case 3: // CONTEXT_ID + return CONTEXT_ID; + case 4: // APP_ID + return APP_ID; + case 5: // PARTITION_INDEX + return PARTITION_INDEX; + case 6: // SERVER + return SERVER; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __ERROR_ISSET_ID = 0; + private static final int __CONTEXT_ID_ISSET_ID = 1; + private static final int __APP_ID_ISSET_ID = 2; + private static final int __PARTITION_INDEX_ISSET_ID = 3; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.ERROR, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("error", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.KVS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("kvs", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.ListMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, key_value.class)))); + tmpMap.put(_Fields.CONTEXT_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("context_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I64))); + tmpMap.put(_Fields.APP_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("app_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.PARTITION_INDEX, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("partition_index", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.SERVER, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("server", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(scan_response.class, metaDataMap); + } + + public scan_response() { + } + + public scan_response( + int error, + java.util.List kvs, + long context_id, + int app_id, + int partition_index, + java.lang.String server) + { + this(); + this.error = error; + setErrorIsSet(true); + this.kvs = kvs; + this.context_id = context_id; + setContext_idIsSet(true); + this.app_id = app_id; + setApp_idIsSet(true); + this.partition_index = partition_index; + setPartition_indexIsSet(true); + this.server = server; + } + + /** + * Performs a deep copy on other. + */ + public scan_response(scan_response other) { + __isset_bitfield = other.__isset_bitfield; + this.error = other.error; + if (other.isSetKvs()) { + java.util.List __this__kvs = new java.util.ArrayList(other.kvs.size()); + for (key_value other_element : other.kvs) { + __this__kvs.add(new key_value(other_element)); + } + this.kvs = __this__kvs; + } + this.context_id = other.context_id; + this.app_id = other.app_id; + this.partition_index = other.partition_index; + if (other.isSetServer()) { + this.server = other.server; + } + } + + public scan_response deepCopy() { + return new scan_response(this); + } + + @Override + public void clear() { + setErrorIsSet(false); + this.error = 0; + this.kvs = null; + setContext_idIsSet(false); + this.context_id = 0; + setApp_idIsSet(false); + this.app_id = 0; + setPartition_indexIsSet(false); + this.partition_index = 0; + this.server = null; + } + + public int getError() { + return this.error; + } + + public scan_response setError(int error) { + this.error = error; + setErrorIsSet(true); + return this; + } + + public void unsetError() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + /** Returns true if field error is set (has been assigned a value) and false otherwise */ + public boolean isSetError() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + public void setErrorIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __ERROR_ISSET_ID, value); + } + + public int getKvsSize() { + return (this.kvs == null) ? 0 : this.kvs.size(); + } + + public java.util.Iterator getKvsIterator() { + return (this.kvs == null) ? null : this.kvs.iterator(); + } + + public void addToKvs(key_value elem) { + if (this.kvs == null) { + this.kvs = new java.util.ArrayList(); + } + this.kvs.add(elem); + } + + public java.util.List getKvs() { + return this.kvs; + } + + public scan_response setKvs(java.util.List kvs) { + this.kvs = kvs; + return this; + } + + public void unsetKvs() { + this.kvs = null; + } + + /** Returns true if field kvs is set (has been assigned a value) and false otherwise */ + public boolean isSetKvs() { + return this.kvs != null; + } + + public void setKvsIsSet(boolean value) { + if (!value) { + this.kvs = null; + } + } + + public long getContext_id() { + return this.context_id; + } + + public scan_response setContext_id(long context_id) { + this.context_id = context_id; + setContext_idIsSet(true); + return this; + } + + public void unsetContext_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __CONTEXT_ID_ISSET_ID); + } + + /** Returns true if field context_id is set (has been assigned a value) and false otherwise */ + public boolean isSetContext_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __CONTEXT_ID_ISSET_ID); + } + + public void setContext_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __CONTEXT_ID_ISSET_ID, value); + } + + public int getApp_id() { + return this.app_id; + } + + public scan_response setApp_id(int app_id) { + this.app_id = app_id; + setApp_idIsSet(true); + return this; + } + + public void unsetApp_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + /** Returns true if field app_id is set (has been assigned a value) and false otherwise */ + public boolean isSetApp_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + public void setApp_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __APP_ID_ISSET_ID, value); + } + + public int getPartition_index() { + return this.partition_index; + } + + public scan_response setPartition_index(int partition_index) { + this.partition_index = partition_index; + setPartition_indexIsSet(true); + return this; + } + + public void unsetPartition_index() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + /** Returns true if field partition_index is set (has been assigned a value) and false otherwise */ + public boolean isSetPartition_index() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + public void setPartition_indexIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID, value); + } + + public java.lang.String getServer() { + return this.server; + } + + public scan_response setServer(java.lang.String server) { + this.server = server; + return this; + } + + public void unsetServer() { + this.server = null; + } + + /** Returns true if field server is set (has been assigned a value) and false otherwise */ + public boolean isSetServer() { + return this.server != null; + } + + public void setServerIsSet(boolean value) { + if (!value) { + this.server = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case ERROR: + if (value == null) { + unsetError(); + } else { + setError((java.lang.Integer)value); + } + break; + + case KVS: + if (value == null) { + unsetKvs(); + } else { + setKvs((java.util.List)value); + } + break; + + case CONTEXT_ID: + if (value == null) { + unsetContext_id(); + } else { + setContext_id((java.lang.Long)value); + } + break; + + case APP_ID: + if (value == null) { + unsetApp_id(); + } else { + setApp_id((java.lang.Integer)value); + } + break; + + case PARTITION_INDEX: + if (value == null) { + unsetPartition_index(); + } else { + setPartition_index((java.lang.Integer)value); + } + break; + + case SERVER: + if (value == null) { + unsetServer(); + } else { + setServer((java.lang.String)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case ERROR: + return getError(); + + case KVS: + return getKvs(); + + case CONTEXT_ID: + return getContext_id(); + + case APP_ID: + return getApp_id(); + + case PARTITION_INDEX: + return getPartition_index(); + + case SERVER: + return getServer(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case ERROR: + return isSetError(); + case KVS: + return isSetKvs(); + case CONTEXT_ID: + return isSetContext_id(); + case APP_ID: + return isSetApp_id(); + case PARTITION_INDEX: + return isSetPartition_index(); + case SERVER: + return isSetServer(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof scan_response) + return this.equals((scan_response)that); + return false; + } + + public boolean equals(scan_response that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_error = true; + boolean that_present_error = true; + if (this_present_error || that_present_error) { + if (!(this_present_error && that_present_error)) + return false; + if (this.error != that.error) + return false; + } + + boolean this_present_kvs = true && this.isSetKvs(); + boolean that_present_kvs = true && that.isSetKvs(); + if (this_present_kvs || that_present_kvs) { + if (!(this_present_kvs && that_present_kvs)) + return false; + if (!this.kvs.equals(that.kvs)) + return false; + } + + boolean this_present_context_id = true; + boolean that_present_context_id = true; + if (this_present_context_id || that_present_context_id) { + if (!(this_present_context_id && that_present_context_id)) + return false; + if (this.context_id != that.context_id) + return false; + } + + boolean this_present_app_id = true; + boolean that_present_app_id = true; + if (this_present_app_id || that_present_app_id) { + if (!(this_present_app_id && that_present_app_id)) + return false; + if (this.app_id != that.app_id) + return false; + } + + boolean this_present_partition_index = true; + boolean that_present_partition_index = true; + if (this_present_partition_index || that_present_partition_index) { + if (!(this_present_partition_index && that_present_partition_index)) + return false; + if (this.partition_index != that.partition_index) + return false; + } + + boolean this_present_server = true && this.isSetServer(); + boolean that_present_server = true && that.isSetServer(); + if (this_present_server || that_present_server) { + if (!(this_present_server && that_present_server)) + return false; + if (!this.server.equals(that.server)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + error; + + hashCode = hashCode * 8191 + ((isSetKvs()) ? 131071 : 524287); + if (isSetKvs()) + hashCode = hashCode * 8191 + kvs.hashCode(); + + hashCode = hashCode * 8191 + com.xiaomi.infra.pegasus.thrift.TBaseHelper.hashCode(context_id); + + hashCode = hashCode * 8191 + app_id; + + hashCode = hashCode * 8191 + partition_index; + + hashCode = hashCode * 8191 + ((isSetServer()) ? 131071 : 524287); + if (isSetServer()) + hashCode = hashCode * 8191 + server.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(scan_response other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetError()).compareTo(other.isSetError()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetError()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.error, other.error); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetKvs()).compareTo(other.isSetKvs()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetKvs()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.kvs, other.kvs); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetContext_id()).compareTo(other.isSetContext_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetContext_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.context_id, other.context_id); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetApp_id()).compareTo(other.isSetApp_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetApp_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.app_id, other.app_id); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPartition_index()).compareTo(other.isSetPartition_index()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPartition_index()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.partition_index, other.partition_index); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetServer()).compareTo(other.isSetServer()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetServer()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.server, other.server); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("scan_response("); + boolean first = true; + + sb.append("error:"); + sb.append(this.error); + first = false; + if (!first) sb.append(", "); + sb.append("kvs:"); + if (this.kvs == null) { + sb.append("null"); + } else { + sb.append(this.kvs); + } + first = false; + if (!first) sb.append(", "); + sb.append("context_id:"); + sb.append(this.context_id); + first = false; + if (!first) sb.append(", "); + sb.append("app_id:"); + sb.append(this.app_id); + first = false; + if (!first) sb.append(", "); + sb.append("partition_index:"); + sb.append(this.partition_index); + first = false; + if (!first) sb.append(", "); + sb.append("server:"); + if (this.server == null) { + sb.append("null"); + } else { + sb.append(this.server); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class scan_responseStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public scan_responseStandardScheme getScheme() { + return new scan_responseStandardScheme(); + } + } + + private static class scan_responseStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, scan_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // ERROR + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // KVS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list32 = iprot.readListBegin(); + struct.kvs = new java.util.ArrayList(_list32.size); + key_value _elem33; + for (int _i34 = 0; _i34 < _list32.size; ++_i34) + { + _elem33 = new key_value(); + _elem33.read(iprot); + struct.kvs.add(_elem33); + } + iprot.readListEnd(); + } + struct.setKvsIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // CONTEXT_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I64) { + struct.context_id = iprot.readI64(); + struct.setContext_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // APP_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 5: // PARTITION_INDEX + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 6: // SERVER + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, scan_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldBegin(ERROR_FIELD_DESC); + oprot.writeI32(struct.error); + oprot.writeFieldEnd(); + if (struct.kvs != null) { + oprot.writeFieldBegin(KVS_FIELD_DESC); + { + oprot.writeListBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, struct.kvs.size())); + for (key_value _iter35 : struct.kvs) + { + _iter35.write(oprot); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(CONTEXT_ID_FIELD_DESC); + oprot.writeI64(struct.context_id); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(APP_ID_FIELD_DESC); + oprot.writeI32(struct.app_id); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(PARTITION_INDEX_FIELD_DESC); + oprot.writeI32(struct.partition_index); + oprot.writeFieldEnd(); + if (struct.server != null) { + oprot.writeFieldBegin(SERVER_FIELD_DESC); + oprot.writeString(struct.server); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class scan_responseTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public scan_responseTupleScheme getScheme() { + return new scan_responseTupleScheme(); + } + } + + private static class scan_responseTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, scan_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetError()) { + optionals.set(0); + } + if (struct.isSetKvs()) { + optionals.set(1); + } + if (struct.isSetContext_id()) { + optionals.set(2); + } + if (struct.isSetApp_id()) { + optionals.set(3); + } + if (struct.isSetPartition_index()) { + optionals.set(4); + } + if (struct.isSetServer()) { + optionals.set(5); + } + oprot.writeBitSet(optionals, 6); + if (struct.isSetError()) { + oprot.writeI32(struct.error); + } + if (struct.isSetKvs()) { + { + oprot.writeI32(struct.kvs.size()); + for (key_value _iter36 : struct.kvs) + { + _iter36.write(oprot); + } + } + } + if (struct.isSetContext_id()) { + oprot.writeI64(struct.context_id); + } + if (struct.isSetApp_id()) { + oprot.writeI32(struct.app_id); + } + if (struct.isSetPartition_index()) { + oprot.writeI32(struct.partition_index); + } + if (struct.isSetServer()) { + oprot.writeString(struct.server); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, scan_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(6); + if (incoming.get(0)) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } + if (incoming.get(1)) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list37 = new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, iprot.readI32()); + struct.kvs = new java.util.ArrayList(_list37.size); + key_value _elem38; + for (int _i39 = 0; _i39 < _list37.size; ++_i39) + { + _elem38 = new key_value(); + _elem38.read(iprot); + struct.kvs.add(_elem38); + } + } + struct.setKvsIsSet(true); + } + if (incoming.get(2)) { + struct.context_id = iprot.readI64(); + struct.setContext_idIsSet(true); + } + if (incoming.get(3)) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } + if (incoming.get(4)) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } + if (incoming.get(5)) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/ttl_response.java b/src/main/java/com/xiaomi/infra/pegasus/apps/ttl_response.java new file mode 100644 index 00000000..6a1e522e --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/ttl_response.java @@ -0,0 +1,763 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class ttl_response implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("ttl_response"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField ERROR_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("error", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField TTL_SECONDS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("ttl_seconds", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField APP_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("app_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PARTITION_INDEX_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("partition_index", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SERVER_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("server", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING, (short)6); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new ttl_responseStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new ttl_responseTupleSchemeFactory(); + + public int error; // required + public int ttl_seconds; // required + public int app_id; // required + public int partition_index; // required + public java.lang.String server; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + ERROR((short)1, "error"), + TTL_SECONDS((short)2, "ttl_seconds"), + APP_ID((short)3, "app_id"), + PARTITION_INDEX((short)4, "partition_index"), + SERVER((short)6, "server"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // ERROR + return ERROR; + case 2: // TTL_SECONDS + return TTL_SECONDS; + case 3: // APP_ID + return APP_ID; + case 4: // PARTITION_INDEX + return PARTITION_INDEX; + case 6: // SERVER + return SERVER; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __ERROR_ISSET_ID = 0; + private static final int __TTL_SECONDS_ISSET_ID = 1; + private static final int __APP_ID_ISSET_ID = 2; + private static final int __PARTITION_INDEX_ISSET_ID = 3; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.ERROR, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("error", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.TTL_SECONDS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("ttl_seconds", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.APP_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("app_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.PARTITION_INDEX, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("partition_index", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.SERVER, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("server", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(ttl_response.class, metaDataMap); + } + + public ttl_response() { + } + + public ttl_response( + int error, + int ttl_seconds, + int app_id, + int partition_index, + java.lang.String server) + { + this(); + this.error = error; + setErrorIsSet(true); + this.ttl_seconds = ttl_seconds; + setTtl_secondsIsSet(true); + this.app_id = app_id; + setApp_idIsSet(true); + this.partition_index = partition_index; + setPartition_indexIsSet(true); + this.server = server; + } + + /** + * Performs a deep copy on other. + */ + public ttl_response(ttl_response other) { + __isset_bitfield = other.__isset_bitfield; + this.error = other.error; + this.ttl_seconds = other.ttl_seconds; + this.app_id = other.app_id; + this.partition_index = other.partition_index; + if (other.isSetServer()) { + this.server = other.server; + } + } + + public ttl_response deepCopy() { + return new ttl_response(this); + } + + @Override + public void clear() { + setErrorIsSet(false); + this.error = 0; + setTtl_secondsIsSet(false); + this.ttl_seconds = 0; + setApp_idIsSet(false); + this.app_id = 0; + setPartition_indexIsSet(false); + this.partition_index = 0; + this.server = null; + } + + public int getError() { + return this.error; + } + + public ttl_response setError(int error) { + this.error = error; + setErrorIsSet(true); + return this; + } + + public void unsetError() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + /** Returns true if field error is set (has been assigned a value) and false otherwise */ + public boolean isSetError() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + public void setErrorIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __ERROR_ISSET_ID, value); + } + + public int getTtl_seconds() { + return this.ttl_seconds; + } + + public ttl_response setTtl_seconds(int ttl_seconds) { + this.ttl_seconds = ttl_seconds; + setTtl_secondsIsSet(true); + return this; + } + + public void unsetTtl_seconds() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __TTL_SECONDS_ISSET_ID); + } + + /** Returns true if field ttl_seconds is set (has been assigned a value) and false otherwise */ + public boolean isSetTtl_seconds() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __TTL_SECONDS_ISSET_ID); + } + + public void setTtl_secondsIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __TTL_SECONDS_ISSET_ID, value); + } + + public int getApp_id() { + return this.app_id; + } + + public ttl_response setApp_id(int app_id) { + this.app_id = app_id; + setApp_idIsSet(true); + return this; + } + + public void unsetApp_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + /** Returns true if field app_id is set (has been assigned a value) and false otherwise */ + public boolean isSetApp_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + public void setApp_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __APP_ID_ISSET_ID, value); + } + + public int getPartition_index() { + return this.partition_index; + } + + public ttl_response setPartition_index(int partition_index) { + this.partition_index = partition_index; + setPartition_indexIsSet(true); + return this; + } + + public void unsetPartition_index() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + /** Returns true if field partition_index is set (has been assigned a value) and false otherwise */ + public boolean isSetPartition_index() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + public void setPartition_indexIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID, value); + } + + public java.lang.String getServer() { + return this.server; + } + + public ttl_response setServer(java.lang.String server) { + this.server = server; + return this; + } + + public void unsetServer() { + this.server = null; + } + + /** Returns true if field server is set (has been assigned a value) and false otherwise */ + public boolean isSetServer() { + return this.server != null; + } + + public void setServerIsSet(boolean value) { + if (!value) { + this.server = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case ERROR: + if (value == null) { + unsetError(); + } else { + setError((java.lang.Integer)value); + } + break; + + case TTL_SECONDS: + if (value == null) { + unsetTtl_seconds(); + } else { + setTtl_seconds((java.lang.Integer)value); + } + break; + + case APP_ID: + if (value == null) { + unsetApp_id(); + } else { + setApp_id((java.lang.Integer)value); + } + break; + + case PARTITION_INDEX: + if (value == null) { + unsetPartition_index(); + } else { + setPartition_index((java.lang.Integer)value); + } + break; + + case SERVER: + if (value == null) { + unsetServer(); + } else { + setServer((java.lang.String)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case ERROR: + return getError(); + + case TTL_SECONDS: + return getTtl_seconds(); + + case APP_ID: + return getApp_id(); + + case PARTITION_INDEX: + return getPartition_index(); + + case SERVER: + return getServer(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case ERROR: + return isSetError(); + case TTL_SECONDS: + return isSetTtl_seconds(); + case APP_ID: + return isSetApp_id(); + case PARTITION_INDEX: + return isSetPartition_index(); + case SERVER: + return isSetServer(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof ttl_response) + return this.equals((ttl_response)that); + return false; + } + + public boolean equals(ttl_response that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_error = true; + boolean that_present_error = true; + if (this_present_error || that_present_error) { + if (!(this_present_error && that_present_error)) + return false; + if (this.error != that.error) + return false; + } + + boolean this_present_ttl_seconds = true; + boolean that_present_ttl_seconds = true; + if (this_present_ttl_seconds || that_present_ttl_seconds) { + if (!(this_present_ttl_seconds && that_present_ttl_seconds)) + return false; + if (this.ttl_seconds != that.ttl_seconds) + return false; + } + + boolean this_present_app_id = true; + boolean that_present_app_id = true; + if (this_present_app_id || that_present_app_id) { + if (!(this_present_app_id && that_present_app_id)) + return false; + if (this.app_id != that.app_id) + return false; + } + + boolean this_present_partition_index = true; + boolean that_present_partition_index = true; + if (this_present_partition_index || that_present_partition_index) { + if (!(this_present_partition_index && that_present_partition_index)) + return false; + if (this.partition_index != that.partition_index) + return false; + } + + boolean this_present_server = true && this.isSetServer(); + boolean that_present_server = true && that.isSetServer(); + if (this_present_server || that_present_server) { + if (!(this_present_server && that_present_server)) + return false; + if (!this.server.equals(that.server)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + error; + + hashCode = hashCode * 8191 + ttl_seconds; + + hashCode = hashCode * 8191 + app_id; + + hashCode = hashCode * 8191 + partition_index; + + hashCode = hashCode * 8191 + ((isSetServer()) ? 131071 : 524287); + if (isSetServer()) + hashCode = hashCode * 8191 + server.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(ttl_response other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetError()).compareTo(other.isSetError()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetError()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.error, other.error); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetTtl_seconds()).compareTo(other.isSetTtl_seconds()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetTtl_seconds()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.ttl_seconds, other.ttl_seconds); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetApp_id()).compareTo(other.isSetApp_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetApp_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.app_id, other.app_id); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPartition_index()).compareTo(other.isSetPartition_index()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPartition_index()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.partition_index, other.partition_index); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetServer()).compareTo(other.isSetServer()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetServer()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.server, other.server); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("ttl_response("); + boolean first = true; + + sb.append("error:"); + sb.append(this.error); + first = false; + if (!first) sb.append(", "); + sb.append("ttl_seconds:"); + sb.append(this.ttl_seconds); + first = false; + if (!first) sb.append(", "); + sb.append("app_id:"); + sb.append(this.app_id); + first = false; + if (!first) sb.append(", "); + sb.append("partition_index:"); + sb.append(this.partition_index); + first = false; + if (!first) sb.append(", "); + sb.append("server:"); + if (this.server == null) { + sb.append("null"); + } else { + sb.append(this.server); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class ttl_responseStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public ttl_responseStandardScheme getScheme() { + return new ttl_responseStandardScheme(); + } + } + + private static class ttl_responseStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, ttl_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // ERROR + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // TTL_SECONDS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.ttl_seconds = iprot.readI32(); + struct.setTtl_secondsIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // APP_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // PARTITION_INDEX + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 6: // SERVER + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, ttl_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldBegin(ERROR_FIELD_DESC); + oprot.writeI32(struct.error); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(TTL_SECONDS_FIELD_DESC); + oprot.writeI32(struct.ttl_seconds); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(APP_ID_FIELD_DESC); + oprot.writeI32(struct.app_id); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(PARTITION_INDEX_FIELD_DESC); + oprot.writeI32(struct.partition_index); + oprot.writeFieldEnd(); + if (struct.server != null) { + oprot.writeFieldBegin(SERVER_FIELD_DESC); + oprot.writeString(struct.server); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class ttl_responseTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public ttl_responseTupleScheme getScheme() { + return new ttl_responseTupleScheme(); + } + } + + private static class ttl_responseTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, ttl_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetError()) { + optionals.set(0); + } + if (struct.isSetTtl_seconds()) { + optionals.set(1); + } + if (struct.isSetApp_id()) { + optionals.set(2); + } + if (struct.isSetPartition_index()) { + optionals.set(3); + } + if (struct.isSetServer()) { + optionals.set(4); + } + oprot.writeBitSet(optionals, 5); + if (struct.isSetError()) { + oprot.writeI32(struct.error); + } + if (struct.isSetTtl_seconds()) { + oprot.writeI32(struct.ttl_seconds); + } + if (struct.isSetApp_id()) { + oprot.writeI32(struct.app_id); + } + if (struct.isSetPartition_index()) { + oprot.writeI32(struct.partition_index); + } + if (struct.isSetServer()) { + oprot.writeString(struct.server); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, ttl_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(5); + if (incoming.get(0)) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } + if (incoming.get(1)) { + struct.ttl_seconds = iprot.readI32(); + struct.setTtl_secondsIsSet(true); + } + if (incoming.get(2)) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } + if (incoming.get(3)) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } + if (incoming.get(4)) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/update_request.java b/src/main/java/com/xiaomi/infra/pegasus/apps/update_request.java new file mode 100644 index 00000000..97a0c714 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/update_request.java @@ -0,0 +1,589 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class update_request implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("update_request"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField KEY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("key", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField VALUE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("value", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField EXPIRE_TS_SECONDS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("expire_ts_seconds", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new update_requestStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new update_requestTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.blob key; // required + public com.xiaomi.infra.pegasus.base.blob value; // required + public int expire_ts_seconds; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + KEY((short)1, "key"), + VALUE((short)2, "value"), + EXPIRE_TS_SECONDS((short)3, "expire_ts_seconds"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // KEY + return KEY; + case 2: // VALUE + return VALUE; + case 3: // EXPIRE_TS_SECONDS + return EXPIRE_TS_SECONDS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __EXPIRE_TS_SECONDS_ISSET_ID = 0; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.KEY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("key", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.VALUE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("value", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.blob.class))); + tmpMap.put(_Fields.EXPIRE_TS_SECONDS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("expire_ts_seconds", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(update_request.class, metaDataMap); + } + + public update_request() { + } + + public update_request( + com.xiaomi.infra.pegasus.base.blob key, + com.xiaomi.infra.pegasus.base.blob value, + int expire_ts_seconds) + { + this(); + this.key = key; + this.value = value; + this.expire_ts_seconds = expire_ts_seconds; + setExpire_ts_secondsIsSet(true); + } + + /** + * Performs a deep copy on other. + */ + public update_request(update_request other) { + __isset_bitfield = other.__isset_bitfield; + if (other.isSetKey()) { + this.key = new com.xiaomi.infra.pegasus.base.blob(other.key); + } + if (other.isSetValue()) { + this.value = new com.xiaomi.infra.pegasus.base.blob(other.value); + } + this.expire_ts_seconds = other.expire_ts_seconds; + } + + public update_request deepCopy() { + return new update_request(this); + } + + @Override + public void clear() { + this.key = null; + this.value = null; + setExpire_ts_secondsIsSet(false); + this.expire_ts_seconds = 0; + } + + public com.xiaomi.infra.pegasus.base.blob getKey() { + return this.key; + } + + public update_request setKey(com.xiaomi.infra.pegasus.base.blob key) { + this.key = key; + return this; + } + + public void unsetKey() { + this.key = null; + } + + /** Returns true if field key is set (has been assigned a value) and false otherwise */ + public boolean isSetKey() { + return this.key != null; + } + + public void setKeyIsSet(boolean value) { + if (!value) { + this.key = null; + } + } + + public com.xiaomi.infra.pegasus.base.blob getValue() { + return this.value; + } + + public update_request setValue(com.xiaomi.infra.pegasus.base.blob value) { + this.value = value; + return this; + } + + public void unsetValue() { + this.value = null; + } + + /** Returns true if field value is set (has been assigned a value) and false otherwise */ + public boolean isSetValue() { + return this.value != null; + } + + public void setValueIsSet(boolean value) { + if (!value) { + this.value = null; + } + } + + public int getExpire_ts_seconds() { + return this.expire_ts_seconds; + } + + public update_request setExpire_ts_seconds(int expire_ts_seconds) { + this.expire_ts_seconds = expire_ts_seconds; + setExpire_ts_secondsIsSet(true); + return this; + } + + public void unsetExpire_ts_seconds() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __EXPIRE_TS_SECONDS_ISSET_ID); + } + + /** Returns true if field expire_ts_seconds is set (has been assigned a value) and false otherwise */ + public boolean isSetExpire_ts_seconds() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __EXPIRE_TS_SECONDS_ISSET_ID); + } + + public void setExpire_ts_secondsIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __EXPIRE_TS_SECONDS_ISSET_ID, value); + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case KEY: + if (value == null) { + unsetKey(); + } else { + setKey((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case VALUE: + if (value == null) { + unsetValue(); + } else { + setValue((com.xiaomi.infra.pegasus.base.blob)value); + } + break; + + case EXPIRE_TS_SECONDS: + if (value == null) { + unsetExpire_ts_seconds(); + } else { + setExpire_ts_seconds((java.lang.Integer)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case KEY: + return getKey(); + + case VALUE: + return getValue(); + + case EXPIRE_TS_SECONDS: + return getExpire_ts_seconds(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case KEY: + return isSetKey(); + case VALUE: + return isSetValue(); + case EXPIRE_TS_SECONDS: + return isSetExpire_ts_seconds(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof update_request) + return this.equals((update_request)that); + return false; + } + + public boolean equals(update_request that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_key = true && this.isSetKey(); + boolean that_present_key = true && that.isSetKey(); + if (this_present_key || that_present_key) { + if (!(this_present_key && that_present_key)) + return false; + if (!this.key.equals(that.key)) + return false; + } + + boolean this_present_value = true && this.isSetValue(); + boolean that_present_value = true && that.isSetValue(); + if (this_present_value || that_present_value) { + if (!(this_present_value && that_present_value)) + return false; + if (!this.value.equals(that.value)) + return false; + } + + boolean this_present_expire_ts_seconds = true; + boolean that_present_expire_ts_seconds = true; + if (this_present_expire_ts_seconds || that_present_expire_ts_seconds) { + if (!(this_present_expire_ts_seconds && that_present_expire_ts_seconds)) + return false; + if (this.expire_ts_seconds != that.expire_ts_seconds) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetKey()) ? 131071 : 524287); + if (isSetKey()) + hashCode = hashCode * 8191 + key.hashCode(); + + hashCode = hashCode * 8191 + ((isSetValue()) ? 131071 : 524287); + if (isSetValue()) + hashCode = hashCode * 8191 + value.hashCode(); + + hashCode = hashCode * 8191 + expire_ts_seconds; + + return hashCode; + } + + @Override + public int compareTo(update_request other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetKey()).compareTo(other.isSetKey()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetKey()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.key, other.key); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetValue()).compareTo(other.isSetValue()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetValue()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.value, other.value); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetExpire_ts_seconds()).compareTo(other.isSetExpire_ts_seconds()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetExpire_ts_seconds()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.expire_ts_seconds, other.expire_ts_seconds); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("update_request("); + boolean first = true; + + sb.append("key:"); + if (this.key == null) { + sb.append("null"); + } else { + sb.append(this.key); + } + first = false; + if (!first) sb.append(", "); + sb.append("value:"); + if (this.value == null) { + sb.append("null"); + } else { + sb.append(this.value); + } + first = false; + if (!first) sb.append(", "); + sb.append("expire_ts_seconds:"); + sb.append(this.expire_ts_seconds); + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (key != null) { + key.validate(); + } + if (value != null) { + value.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class update_requestStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public update_requestStandardScheme getScheme() { + return new update_requestStandardScheme(); + } + } + + private static class update_requestStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, update_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // KEY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.key = new com.xiaomi.infra.pegasus.base.blob(); + struct.key.read(iprot); + struct.setKeyIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // VALUE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.value = new com.xiaomi.infra.pegasus.base.blob(); + struct.value.read(iprot); + struct.setValueIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // EXPIRE_TS_SECONDS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.expire_ts_seconds = iprot.readI32(); + struct.setExpire_ts_secondsIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, update_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.key != null) { + oprot.writeFieldBegin(KEY_FIELD_DESC); + struct.key.write(oprot); + oprot.writeFieldEnd(); + } + if (struct.value != null) { + oprot.writeFieldBegin(VALUE_FIELD_DESC); + struct.value.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(EXPIRE_TS_SECONDS_FIELD_DESC); + oprot.writeI32(struct.expire_ts_seconds); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class update_requestTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public update_requestTupleScheme getScheme() { + return new update_requestTupleScheme(); + } + } + + private static class update_requestTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, update_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetKey()) { + optionals.set(0); + } + if (struct.isSetValue()) { + optionals.set(1); + } + if (struct.isSetExpire_ts_seconds()) { + optionals.set(2); + } + oprot.writeBitSet(optionals, 3); + if (struct.isSetKey()) { + struct.key.write(oprot); + } + if (struct.isSetValue()) { + struct.value.write(oprot); + } + if (struct.isSetExpire_ts_seconds()) { + oprot.writeI32(struct.expire_ts_seconds); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, update_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(3); + if (incoming.get(0)) { + struct.key = new com.xiaomi.infra.pegasus.base.blob(); + struct.key.read(iprot); + struct.setKeyIsSet(true); + } + if (incoming.get(1)) { + struct.value = new com.xiaomi.infra.pegasus.base.blob(); + struct.value.read(iprot); + struct.setValueIsSet(true); + } + if (incoming.get(2)) { + struct.expire_ts_seconds = iprot.readI32(); + struct.setExpire_ts_secondsIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/apps/update_response.java b/src/main/java/com/xiaomi/infra/pegasus/apps/update_response.java new file mode 100644 index 00000000..d0452d93 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/apps/update_response.java @@ -0,0 +1,763 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.apps; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class update_response implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("update_response"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField ERROR_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("error", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField APP_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("app_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PARTITION_INDEX_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("partition_index", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField DECREE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("decree", com.xiaomi.infra.pegasus.thrift.protocol.TType.I64, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SERVER_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("server", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING, (short)5); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new update_responseStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new update_responseTupleSchemeFactory(); + + public int error; // required + public int app_id; // required + public int partition_index; // required + public long decree; // required + public java.lang.String server; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + ERROR((short)1, "error"), + APP_ID((short)2, "app_id"), + PARTITION_INDEX((short)3, "partition_index"), + DECREE((short)4, "decree"), + SERVER((short)5, "server"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // ERROR + return ERROR; + case 2: // APP_ID + return APP_ID; + case 3: // PARTITION_INDEX + return PARTITION_INDEX; + case 4: // DECREE + return DECREE; + case 5: // SERVER + return SERVER; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __ERROR_ISSET_ID = 0; + private static final int __APP_ID_ISSET_ID = 1; + private static final int __PARTITION_INDEX_ISSET_ID = 2; + private static final int __DECREE_ISSET_ID = 3; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.ERROR, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("error", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.APP_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("app_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.PARTITION_INDEX, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("partition_index", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.DECREE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("decree", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I64))); + tmpMap.put(_Fields.SERVER, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("server", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(update_response.class, metaDataMap); + } + + public update_response() { + } + + public update_response( + int error, + int app_id, + int partition_index, + long decree, + java.lang.String server) + { + this(); + this.error = error; + setErrorIsSet(true); + this.app_id = app_id; + setApp_idIsSet(true); + this.partition_index = partition_index; + setPartition_indexIsSet(true); + this.decree = decree; + setDecreeIsSet(true); + this.server = server; + } + + /** + * Performs a deep copy on other. + */ + public update_response(update_response other) { + __isset_bitfield = other.__isset_bitfield; + this.error = other.error; + this.app_id = other.app_id; + this.partition_index = other.partition_index; + this.decree = other.decree; + if (other.isSetServer()) { + this.server = other.server; + } + } + + public update_response deepCopy() { + return new update_response(this); + } + + @Override + public void clear() { + setErrorIsSet(false); + this.error = 0; + setApp_idIsSet(false); + this.app_id = 0; + setPartition_indexIsSet(false); + this.partition_index = 0; + setDecreeIsSet(false); + this.decree = 0; + this.server = null; + } + + public int getError() { + return this.error; + } + + public update_response setError(int error) { + this.error = error; + setErrorIsSet(true); + return this; + } + + public void unsetError() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + /** Returns true if field error is set (has been assigned a value) and false otherwise */ + public boolean isSetError() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __ERROR_ISSET_ID); + } + + public void setErrorIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __ERROR_ISSET_ID, value); + } + + public int getApp_id() { + return this.app_id; + } + + public update_response setApp_id(int app_id) { + this.app_id = app_id; + setApp_idIsSet(true); + return this; + } + + public void unsetApp_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + /** Returns true if field app_id is set (has been assigned a value) and false otherwise */ + public boolean isSetApp_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + public void setApp_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __APP_ID_ISSET_ID, value); + } + + public int getPartition_index() { + return this.partition_index; + } + + public update_response setPartition_index(int partition_index) { + this.partition_index = partition_index; + setPartition_indexIsSet(true); + return this; + } + + public void unsetPartition_index() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + /** Returns true if field partition_index is set (has been assigned a value) and false otherwise */ + public boolean isSetPartition_index() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID); + } + + public void setPartition_indexIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __PARTITION_INDEX_ISSET_ID, value); + } + + public long getDecree() { + return this.decree; + } + + public update_response setDecree(long decree) { + this.decree = decree; + setDecreeIsSet(true); + return this; + } + + public void unsetDecree() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __DECREE_ISSET_ID); + } + + /** Returns true if field decree is set (has been assigned a value) and false otherwise */ + public boolean isSetDecree() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __DECREE_ISSET_ID); + } + + public void setDecreeIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __DECREE_ISSET_ID, value); + } + + public java.lang.String getServer() { + return this.server; + } + + public update_response setServer(java.lang.String server) { + this.server = server; + return this; + } + + public void unsetServer() { + this.server = null; + } + + /** Returns true if field server is set (has been assigned a value) and false otherwise */ + public boolean isSetServer() { + return this.server != null; + } + + public void setServerIsSet(boolean value) { + if (!value) { + this.server = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case ERROR: + if (value == null) { + unsetError(); + } else { + setError((java.lang.Integer)value); + } + break; + + case APP_ID: + if (value == null) { + unsetApp_id(); + } else { + setApp_id((java.lang.Integer)value); + } + break; + + case PARTITION_INDEX: + if (value == null) { + unsetPartition_index(); + } else { + setPartition_index((java.lang.Integer)value); + } + break; + + case DECREE: + if (value == null) { + unsetDecree(); + } else { + setDecree((java.lang.Long)value); + } + break; + + case SERVER: + if (value == null) { + unsetServer(); + } else { + setServer((java.lang.String)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case ERROR: + return getError(); + + case APP_ID: + return getApp_id(); + + case PARTITION_INDEX: + return getPartition_index(); + + case DECREE: + return getDecree(); + + case SERVER: + return getServer(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case ERROR: + return isSetError(); + case APP_ID: + return isSetApp_id(); + case PARTITION_INDEX: + return isSetPartition_index(); + case DECREE: + return isSetDecree(); + case SERVER: + return isSetServer(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof update_response) + return this.equals((update_response)that); + return false; + } + + public boolean equals(update_response that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_error = true; + boolean that_present_error = true; + if (this_present_error || that_present_error) { + if (!(this_present_error && that_present_error)) + return false; + if (this.error != that.error) + return false; + } + + boolean this_present_app_id = true; + boolean that_present_app_id = true; + if (this_present_app_id || that_present_app_id) { + if (!(this_present_app_id && that_present_app_id)) + return false; + if (this.app_id != that.app_id) + return false; + } + + boolean this_present_partition_index = true; + boolean that_present_partition_index = true; + if (this_present_partition_index || that_present_partition_index) { + if (!(this_present_partition_index && that_present_partition_index)) + return false; + if (this.partition_index != that.partition_index) + return false; + } + + boolean this_present_decree = true; + boolean that_present_decree = true; + if (this_present_decree || that_present_decree) { + if (!(this_present_decree && that_present_decree)) + return false; + if (this.decree != that.decree) + return false; + } + + boolean this_present_server = true && this.isSetServer(); + boolean that_present_server = true && that.isSetServer(); + if (this_present_server || that_present_server) { + if (!(this_present_server && that_present_server)) + return false; + if (!this.server.equals(that.server)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + error; + + hashCode = hashCode * 8191 + app_id; + + hashCode = hashCode * 8191 + partition_index; + + hashCode = hashCode * 8191 + com.xiaomi.infra.pegasus.thrift.TBaseHelper.hashCode(decree); + + hashCode = hashCode * 8191 + ((isSetServer()) ? 131071 : 524287); + if (isSetServer()) + hashCode = hashCode * 8191 + server.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(update_response other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetError()).compareTo(other.isSetError()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetError()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.error, other.error); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetApp_id()).compareTo(other.isSetApp_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetApp_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.app_id, other.app_id); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPartition_index()).compareTo(other.isSetPartition_index()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPartition_index()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.partition_index, other.partition_index); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetDecree()).compareTo(other.isSetDecree()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetDecree()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.decree, other.decree); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetServer()).compareTo(other.isSetServer()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetServer()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.server, other.server); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("update_response("); + boolean first = true; + + sb.append("error:"); + sb.append(this.error); + first = false; + if (!first) sb.append(", "); + sb.append("app_id:"); + sb.append(this.app_id); + first = false; + if (!first) sb.append(", "); + sb.append("partition_index:"); + sb.append(this.partition_index); + first = false; + if (!first) sb.append(", "); + sb.append("decree:"); + sb.append(this.decree); + first = false; + if (!first) sb.append(", "); + sb.append("server:"); + if (this.server == null) { + sb.append("null"); + } else { + sb.append(this.server); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class update_responseStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public update_responseStandardScheme getScheme() { + return new update_responseStandardScheme(); + } + } + + private static class update_responseStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, update_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // ERROR + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // APP_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // PARTITION_INDEX + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // DECREE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I64) { + struct.decree = iprot.readI64(); + struct.setDecreeIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 5: // SERVER + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, update_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + oprot.writeFieldBegin(ERROR_FIELD_DESC); + oprot.writeI32(struct.error); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(APP_ID_FIELD_DESC); + oprot.writeI32(struct.app_id); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(PARTITION_INDEX_FIELD_DESC); + oprot.writeI32(struct.partition_index); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(DECREE_FIELD_DESC); + oprot.writeI64(struct.decree); + oprot.writeFieldEnd(); + if (struct.server != null) { + oprot.writeFieldBegin(SERVER_FIELD_DESC); + oprot.writeString(struct.server); + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class update_responseTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public update_responseTupleScheme getScheme() { + return new update_responseTupleScheme(); + } + } + + private static class update_responseTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, update_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetError()) { + optionals.set(0); + } + if (struct.isSetApp_id()) { + optionals.set(1); + } + if (struct.isSetPartition_index()) { + optionals.set(2); + } + if (struct.isSetDecree()) { + optionals.set(3); + } + if (struct.isSetServer()) { + optionals.set(4); + } + oprot.writeBitSet(optionals, 5); + if (struct.isSetError()) { + oprot.writeI32(struct.error); + } + if (struct.isSetApp_id()) { + oprot.writeI32(struct.app_id); + } + if (struct.isSetPartition_index()) { + oprot.writeI32(struct.partition_index); + } + if (struct.isSetDecree()) { + oprot.writeI64(struct.decree); + } + if (struct.isSetServer()) { + oprot.writeString(struct.server); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, update_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(5); + if (incoming.get(0)) { + struct.error = iprot.readI32(); + struct.setErrorIsSet(true); + } + if (incoming.get(1)) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } + if (incoming.get(2)) { + struct.partition_index = iprot.readI32(); + struct.setPartition_indexIsSet(true); + } + if (incoming.get(3)) { + struct.decree = iprot.readI64(); + struct.setDecreeIsSet(true); + } + if (incoming.get(4)) { + struct.server = iprot.readString(); + struct.setServerIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/base/blob.java b/src/main/java/com/xiaomi/infra/pegasus/base/blob.java new file mode 100644 index 00000000..899acb39 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/base/blob.java @@ -0,0 +1,203 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +package com.xiaomi.infra.pegasus.base; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.EnumMap; +import java.util.Set; +import java.util.HashSet; +import java.util.EnumSet; +import java.util.Collections; +import java.util.BitSet; +import java.nio.ByteBuffer; +import java.util.Arrays; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.xiaomi.infra.pegasus.thrift.*; +import com.xiaomi.infra.pegasus.thrift.async.*; +import com.xiaomi.infra.pegasus.thrift.meta_data.*; +import com.xiaomi.infra.pegasus.thrift.transport.*; +import com.xiaomi.infra.pegasus.thrift.protocol.*; + +public class blob implements TBase, java.io.Serializable, Cloneable { + private static final TStruct STRUCT_DESC = new TStruct("blob"); + public byte[] data; + + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements TFieldIdEnum { +; + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + public static final Map<_Fields, FieldMetaData> metaDataMap; + static { + Map<_Fields, FieldMetaData> tmpMap = new EnumMap<_Fields, FieldMetaData>(_Fields.class); + metaDataMap = Collections.unmodifiableMap(tmpMap); + FieldMetaData.addStructMetaDataMap(blob.class, metaDataMap); + } + + public blob() { + this.data = null; + } + + public blob(byte[] data) { + this.data = data; + } + /** + * Performs a deep copy on other. + */ + public blob(blob other) { + this.data = other.data; + } + + public blob deepCopy() { + return new blob(this); + } + + @Override + public void clear() { + this.data = null; + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof blob) + return this.equals((blob)that); + return false; + } + + public boolean equals(blob that) { + if (that == null) + return false; + return this.data.equals(that.data); + } + + @Override + public int hashCode() { + return data.hashCode(); + } + + public int compareTo(blob other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(TProtocol iprot) throws TException { + ByteBuffer buffer = iprot.readBinary(); + data = new byte[buffer.remaining()]; + buffer.get(data); + // check for required fields of primitive type, which can't be checked in the validate method + validate(); + } + + public void write(TProtocol oprot) throws TException { + validate(); + + ByteBuffer buf = ByteBuffer.wrap(data); + oprot.writeBinary(buf); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("blob("); + sb.append(data); + sb.append(")"); + return sb.toString(); + } + + public void validate() throws TException { + // check for required fields + } + +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/base/error_code.java b/src/main/java/com/xiaomi/infra/pegasus/base/error_code.java new file mode 100644 index 00000000..e0311cf1 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/base/error_code.java @@ -0,0 +1,286 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +package com.xiaomi.infra.pegasus.base; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.EnumMap; +import java.util.Set; +import java.util.HashSet; +import java.util.EnumSet; +import java.util.Collections; +import java.util.BitSet; +import java.nio.ByteBuffer; +import java.util.Arrays; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.xiaomi.infra.pegasus.thrift.*; +import com.xiaomi.infra.pegasus.thrift.async.*; +import com.xiaomi.infra.pegasus.thrift.meta_data.*; +import com.xiaomi.infra.pegasus.thrift.transport.*; +import com.xiaomi.infra.pegasus.thrift.protocol.*; + +public class error_code implements TBase, java.io.Serializable, Cloneable { + private static final TStruct STRUCT_DESC = new TStruct("error_code"); + public enum error_types { + // ERROR_CODE copy from rDSN + ERR_OK, + ERR_UNKNOWN, + ERR_REPLICATION_FAILURE, + ERR_APP_EXIST, + ERR_APP_NOT_EXIST, + ERR_BUSY_CREATING, + ERR_BUSY_DROPPING, + ERR_EXPIRED, + ERR_LOCK_ALREADY_EXIST, + ERR_HOLD_BY_OTHERS, + ERR_RECURSIVE_LOCK, + ERR_NO_OWNER, + ERR_NODE_ALREADY_EXIST, + ERR_INCONSISTENT_STATE, + ERR_ARRAY_INDEX_OUT_OF_RANGE, + ERR_SERVICE_NOT_FOUND, + ERR_SERVICE_ALREADY_RUNNING, + ERR_IO_PENDING, + ERR_TIMEOUT, + ERR_SERVICE_NOT_ACTIVE, + ERR_BUSY, + ERR_NETWORK_INIT_FAILED, + ERR_FORWARD_TO_OTHERS, + ERR_OBJECT_NOT_FOUND, + ERR_HANDLER_NOT_FOUND, + ERR_LEARN_FILE_FAILED, + ERR_GET_LEARN_STATE_FAILED, + ERR_INVALID_VERSION, + ERR_INVALID_PARAMETERS, + ERR_CAPACITY_EXCEEDED, + ERR_INVALID_STATE, + ERR_INACTIVE_STATE, + ERR_NOT_ENOUGH_MEMBER, + ERR_FILE_OPERATION_FAILED, + ERR_HANDLE_EOF, + ERR_WRONG_CHECKSUM, + ERR_INVALID_DATA, + ERR_INVALID_HANDLE, + ERR_INCOMPLETE_DATA, + ERR_VERSION_OUTDATED, + ERR_PATH_NOT_FOUND, + ERR_PATH_ALREADY_EXIST, + ERR_ADDRESS_ALREADY_USED, + ERR_STATE_FREEZED, + ERR_LOCAL_APP_FAILURE, + ERR_BIND_IOCP_FAILED, + ERR_NETWORK_START_FAILED, + ERR_NOT_IMPLEMENTED, + ERR_CHECKPOINT_FAILED, + ERR_WRONG_TIMING, + ERR_NO_NEED_OPERATE, + ERR_CORRUPTION, + ERR_TRY_AGAIN, + ERR_CLUSTER_NOT_FOUND, + ERR_CLUSTER_ALREADY_EXIST, + ERR_ZOOKEEPER_OPERATION, + ERR_K8S_CLUSTER_NOT_FOUND, + ERR_K8S_KUBECTL_NOT_FOUND, + ERR_K8S_DEPLOY_FAILED, + ERR_K8S_UNDEPLOY_FAILED, + ERR_RESOURCE_NOT_ENOUGH, + ERR_WIN_DEPLOY_FAILED, + ERR_WIN_UNDEPLOY_FAILED, + ERR_DOCKER_DAEMON_NOT_FOUND, + ERR_DOCKER_BINARY_NOT_FOUND, + ERR_DOCKER_DEPLOY_FAILED, + ERR_DOCKER_UNDEPLOY_FAILED, + + //ERROR_CODE defined by client + ERR_NO_PRIMARY, + ERR_NO_REPLICA, + ERR_NO_META_SERVER, + ERR_READ_TABLE_FAILED, + ERR_SESSION_RESET, + ERR_META_RESET + }; + public error_types errno; + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements TFieldIdEnum { +; + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + public static final Map<_Fields, FieldMetaData> metaDataMap; + static { + Map<_Fields, FieldMetaData> tmpMap = new EnumMap<_Fields, FieldMetaData>(_Fields.class); + metaDataMap = Collections.unmodifiableMap(tmpMap); + FieldMetaData.addStructMetaDataMap(error_code.class, metaDataMap); + } + + public error_code() { + errno = error_types.ERR_UNKNOWN; + } + + public error_code(error_types err_enum_type) { + errno = err_enum_type; + } + + public void set_error_type(error_types err_enum_type) { + errno = err_enum_type; + } + + public error_code(String message) { + errno = error_types.valueOf(message); + } + + /** + * Performs a deep copy on other. + */ + public error_code(error_code other) { + this.errno = other.errno; + } + + public error_code deepCopy() { + return new error_code(this); + } + + @Override + public void clear() { + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof error_code) + return this.equals((error_code) that); + return false; + } + + public boolean equals(error_code that) { + if (that == null) + return false; + return this.errno.equals(that.errno); + } + + @Override + public int hashCode() { + return this.errno.hashCode(); + } + + public int compareTo(error_code other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + return this.errno.compareTo(other.errno); + } + + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(TProtocol iprot) throws TException { + String err_message = iprot.readString(); + errno = error_types.valueOf(err_message); + // check for required fields of primitive type, which can't be checked in the validate method + validate(); + } + + public void write(TProtocol oprot) throws TException { + validate(); + oprot.writeString(String.valueOf(errno)); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("error_code("); + sb.append(String.valueOf(errno)); + sb.append(")"); + return sb.toString(); + } + + public void validate() throws TException { + // check for required fields + } + +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/base/gpid.java b/src/main/java/com/xiaomi/infra/pegasus/base/gpid.java new file mode 100644 index 00000000..3b50c5f4 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/base/gpid.java @@ -0,0 +1,229 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +package com.xiaomi.infra.pegasus.base; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.EnumMap; +import java.util.Set; +import java.util.HashSet; +import java.util.EnumSet; +import java.util.Collections; +import java.util.BitSet; +import java.nio.ByteBuffer; +import java.util.Arrays; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.xiaomi.infra.pegasus.thrift.*; +import com.xiaomi.infra.pegasus.thrift.async.*; +import com.xiaomi.infra.pegasus.thrift.meta_data.*; +import com.xiaomi.infra.pegasus.thrift.transport.*; +import com.xiaomi.infra.pegasus.thrift.protocol.*; + +public class gpid implements TBase, java.io.Serializable, Cloneable { + private static final TStruct STRUCT_DESC = new TStruct("gpid"); + + //well, the higher 32-bit is pidx, the lower 32-bit app-id + public long value; + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements TFieldIdEnum { +; + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + public static final Map<_Fields, FieldMetaData> metaDataMap; + static { + Map<_Fields, FieldMetaData> tmpMap = new EnumMap<_Fields, FieldMetaData>(_Fields.class); + metaDataMap = Collections.unmodifiableMap(tmpMap); + FieldMetaData.addStructMetaDataMap(gpid.class, metaDataMap); + } + + public gpid() { + value = 0; + } + + public gpid(int app_id, int pidx) + { + value = (((long)pidx) << 32) + app_id; + } + + public int get_app_id() + { + return (int)(value & 0x00000000ffffffffl); + } + + public int get_pidx() + { + return (int)(value >>> 32); + } + + public void set_pidx(int pidx) + { + value = (((long)pidx) << 32) + (value & 0x00000000ffffffffl); + } + + public void set_app_id(int appid) + { + value = (value & 0xffffffff00000000l) + appid; + } + /** + * Performs a deep copy on other. + */ + public gpid(gpid other) { + value = other.value; + } + + public gpid deepCopy() { + return new gpid(this); + } + + @Override + public void clear() { + value = 0; + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof gpid) + return this.equals((gpid)that); + return false; + } + + public boolean equals(gpid that) { + if (that == null) + return false; + return value == that.value; + } + + @Override + public int hashCode() { + return get_app_id() ^ get_pidx(); + } + + public long gpid_hash() { + long result = get_app_id(); + return (result<<32) + get_pidx(); + } + + public int compareTo(gpid other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + if (value < other.value) + return -1; + return value > other.value ? 1: 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(TProtocol iprot) throws TException { + value = iprot.readI64(); + // check for required fields of primitive type, which can't be checked in the validate method + validate(); + } + + public void write(TProtocol oprot) throws TException { + oprot.writeI64(value); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("gpid("); + sb.append(get_app_id()); + sb.append("."); + sb.append(get_pidx()); + sb.append(")"); + return sb.toString(); + } + + public void validate() throws TException { + // check for required fields + } + +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/base/rpc_address.java b/src/main/java/com/xiaomi/infra/pegasus/base/rpc_address.java new file mode 100644 index 00000000..cfc161d3 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/base/rpc_address.java @@ -0,0 +1,244 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +package com.xiaomi.infra.pegasus.base; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.EnumMap; +import java.util.Set; +import java.util.HashSet; +import java.util.EnumSet; +import java.util.Collections; +import java.util.BitSet; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.util.Arrays; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.xiaomi.infra.pegasus.thrift.*; +import com.xiaomi.infra.pegasus.thrift.async.*; +import com.xiaomi.infra.pegasus.thrift.meta_data.*; +import com.xiaomi.infra.pegasus.thrift.transport.*; +import com.xiaomi.infra.pegasus.thrift.protocol.*; + +public class rpc_address implements TBase, java.io.Serializable, Cloneable { + private static final TStruct STRUCT_DESC = new TStruct("rpc_address"); + + public long address; + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements TFieldIdEnum { +; + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + public static final Map<_Fields, FieldMetaData> metaDataMap; + static { + Map<_Fields, FieldMetaData> tmpMap = new EnumMap<_Fields, FieldMetaData>(_Fields.class); + metaDataMap = Collections.unmodifiableMap(tmpMap); + FieldMetaData.addStructMetaDataMap(rpc_address.class, metaDataMap); + } + + public rpc_address() { + this.address = 0; + } + + public boolean isInvalid() { + return this.address == 0; + } + public String get_ip() throws UnknownHostException { + byte[] byte_array = new byte[]{ + (byte) (0xff & (address >> 56)), + (byte) (0xff & (address >> 48)), + (byte) (0xff & (address >> 40)), + (byte) (0xff & (address >> 32)) + }; + return InetAddress.getByAddress(byte_array).getHostAddress(); + } + public int get_port() { + return (int)(0xffff & (address >> 16)); + } + + // get rpc_address from the format xx.xx.xx.xx:abcd + public boolean fromString(String ipPort) { + String[] pairs = ipPort.split(":"); + + int ip; + if (pairs.length != 2) { + return false; + } + + try { + byte[] byteArray = InetAddress.getByName(pairs[0]).getAddress(); + ip = ((int)(byteArray[0] & 0xff) << 24) | + ((int)(byteArray[1] & 0xff) << 16) | + ((int)(byteArray[2] & 0xff) << 8) | + ((int)(byteArray[3] & 0xff)); + } catch (UnknownHostException e) { + return false; + } + + Integer port = Integer.valueOf(pairs[1]); + address = ((long)ip << 32) + ((long)port << 16) + 1; + return true; + } + /** + * Performs a deep copy on other. + */ + public rpc_address(rpc_address other) { + this.address = other.address; + } + + public rpc_address deepCopy() { + return new rpc_address(this); + } + + @Override + public void clear() { + this.address = 0; + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof rpc_address) + return this.equals((rpc_address)that); + return false; + } + + public boolean equals(rpc_address that) { + if (that == null) + return false; + return this.address == that.address; + } + + @Override + public int hashCode() { + return (int)(address ^ (address >>> 32)); + } + + public int compareTo(rpc_address other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(TProtocol iprot) throws TException { + address = iprot.readI64(); + // check for required fields of primitive type, which can't be checked in the validate method + validate(); + } + + public void write(TProtocol oprot) throws TException { + validate(); + oprot.writeI64(address); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("rpc_address("); + try { + sb.append(get_ip()); + } catch (UnknownHostException e) { + sb.append("invalid_addr"); + } + sb.append(":"); + sb.append(String.valueOf(get_port())); + sb.append(")"); + return sb.toString(); + } + + public void validate() throws TException { + // check for required fields + } + +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/base/task_code.java b/src/main/java/com/xiaomi/infra/pegasus/base/task_code.java new file mode 100644 index 00000000..1eb0a3ba --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/base/task_code.java @@ -0,0 +1,196 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + */ +package com.xiaomi.infra.pegasus.base; + +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.EnumMap; +import java.util.Set; +import java.util.HashSet; +import java.util.EnumSet; +import java.util.Collections; +import java.util.BitSet; +import java.nio.ByteBuffer; +import java.util.Arrays; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.xiaomi.infra.pegasus.thrift.*; +import com.xiaomi.infra.pegasus.thrift.async.*; +import com.xiaomi.infra.pegasus.thrift.meta_data.*; +import com.xiaomi.infra.pegasus.thrift.transport.*; +import com.xiaomi.infra.pegasus.thrift.protocol.*; + +public class task_code implements TBase, java.io.Serializable, Cloneable { + private static final TStruct STRUCT_DESC = new TStruct("task_code"); + public String task_message; + + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements TFieldIdEnum { +; + + private static final Map byName = new HashMap(); + + static { + for (_Fields field : EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(String name) { + return byName.get(name); + } + + private final short _thriftId; + private final String _fieldName; + + _Fields(short thriftId, String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public String getFieldName() { + return _fieldName; + } + } + public static final Map<_Fields, FieldMetaData> metaDataMap; + static { + Map<_Fields, FieldMetaData> tmpMap = new EnumMap<_Fields, FieldMetaData>(_Fields.class); + metaDataMap = Collections.unmodifiableMap(tmpMap); + FieldMetaData.addStructMetaDataMap(task_code.class, metaDataMap); + } + + public task_code() { + } + public task_code(String message) { + this.task_message = message; + } + /** + * Performs a deep copy on other. + */ + public task_code(task_code other) { + this.task_message = other.task_message; + } + + public task_code deepCopy() { + return new task_code(this); + } + + @Override + public void clear() { + } + + public void setFieldValue(_Fields field, Object value) { + switch (field) { + } + } + + public Object getFieldValue(_Fields field) { + switch (field) { + } + throw new IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new IllegalArgumentException(); + } + + switch (field) { + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + if (that instanceof task_code) + return this.equals((task_code) that); + return false; + } + + public boolean equals(task_code that) { + if (that == null) + return false; + return task_message.equals(that.task_message); + } + + @Override + public int hashCode() { + return task_message.hashCode(); + } + + public int compareTo(task_code other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + return task_message.compareTo(other.task_message); + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(TProtocol iprot) throws TException { + this.task_message = iprot.readString(); + // check for required fields of primitive type, which can't be checked in the validate method + validate(); + } + + public void write(TProtocol oprot) throws TException { + validate(); + oprot.writeString(task_message); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("task_code("); + sb.append(task_message); + sb.append(")"); + return sb.toString(); + } + + public void validate() throws TException { + // check for required fields + } + +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/FilterType.java b/src/main/java/com/xiaomi/infra/pegasus/client/FilterType.java new file mode 100644 index 00000000..7a851795 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/FilterType.java @@ -0,0 +1,26 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +/** + * @author qinzuoyan + * + * Filter type. + */ +public enum FilterType { + FT_NO_FILTER(0), + FT_MATCH_ANYWHERE(1), // match filter string at any position + FT_MATCH_PREFIX(2), // match filter string at prefix + FT_MATCH_POSTFIX(3); // match filter string at postfix + + private final int value; + + private FilterType(int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/HashKeyData.java b/src/main/java/com/xiaomi/infra/pegasus/client/HashKeyData.java new file mode 100644 index 00000000..3cb9450b --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/HashKeyData.java @@ -0,0 +1,36 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.*; + +/** + * @author qinzuoyan + * + * Store data under the same hashKey. + */ +public class HashKeyData { + public byte[] hashKey = null; + public List> values = null; // List{sortKey, value} + + public HashKeyData() { + } + + public HashKeyData(byte[] hashKey) { + this.hashKey = hashKey; + } + + public HashKeyData(byte[] hashKey, List> values) { + this.hashKey = hashKey; + this.values = values; + } + + public void addData(byte[] sortKey, byte[] value) { + if (values == null) + values = new ArrayList>(); + values.add(Pair.of(sortKey, value)); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/MultiGetOptions.java b/src/main/java/com/xiaomi/infra/pegasus/client/MultiGetOptions.java new file mode 100644 index 00000000..dddfd731 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/MultiGetOptions.java @@ -0,0 +1,26 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +/** + * @author qinzuoyan + * + * Multi-get options. + */ +public class MultiGetOptions { + public boolean startInclusive = true; // if the startSortKey is included + public boolean stopInclusive = false; // if the stopSortKey is included + public FilterType sortKeyFilterType = FilterType.FT_NO_FILTER; // filter type for sort key + public byte[] sortKeyFilterPattern = null; // filter pattern for sort key + public boolean noValue = false; // only fetch hash_key and sort_key, but not fetch value + public MultiGetOptions() {} + + public MultiGetOptions(MultiGetOptions o) { + startInclusive = o.startInclusive; + stopInclusive = o.stopInclusive; + sortKeyFilterType = o.sortKeyFilterType; + sortKeyFilterPattern = o.sortKeyFilterPattern; + noValue = o.noValue; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/PConfigUtil.java b/src/main/java/com/xiaomi/infra/pegasus/client/PConfigUtil.java new file mode 100644 index 00000000..f44224a4 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/PConfigUtil.java @@ -0,0 +1,114 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.I0Itec.zkclient.ZkClient; +import org.I0Itec.zkclient.serialize.BytesPushThroughSerializer; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.Properties; + +/** + * @author qinzuoyan + * + * This class encapsulates tools for loading configuration. + */ +public class PConfigUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(PConfigUtil.class); + + public static final String ZK_PREFIX = "zk://"; + public static final String LOCAL_FILE_PREFIX = "file://"; + public static final String RESOURCE_PREFIX = "resource://"; + public static final String SLASH = "/"; + public static final int ZK_SESSION_TIMEOUT = 30000; + public static final int ZK_CONNECTION_TIMEOUT = 30000; + + public static final String PEGASUS_BUSINESS_ROOT_NODE = "/databases/pegasus"; + + public static boolean isZkPath(String path) { + return path.startsWith(ZK_PREFIX); + } + + public static boolean isLocalFile(String path) { + return path.startsWith(LOCAL_FILE_PREFIX); + } + + public static boolean isResource(String path) { + return path.startsWith(RESOURCE_PREFIX); + } + + // zkServers should be "host1:port1,host2:port2,host3:port3" + // return as "zk://{zkServers}/databases/pegasus/{businessName}" + public static String getBusinessConfigZkUri(String zkServers, String businessName) throws PException { + return ZK_PREFIX + zkServers + getBusinessConfigZkPath(businessName); + } + + // load client configuration from configPath, which could be local file path or zk path or resource path. + public static Properties loadConfiguration(String configPath) throws PException { + try { + Properties config = new Properties(); + if (PConfigUtil.isZkPath(configPath)) { + config.load(new ByteArrayInputStream(PConfigUtil.loadConfigFromZK(configPath))); + } else if (PConfigUtil.isLocalFile(configPath)) { + config.load(new BufferedInputStream(new FileInputStream( + configPath.substring(PConfigUtil.LOCAL_FILE_PREFIX.length())))); + } else if (PConfigUtil.isResource(configPath)) { + InputStream stream = PegasusClient.class.getResourceAsStream( + configPath.substring(PConfigUtil.RESOURCE_PREFIX.length())); + if (stream == null) { + throw new PException("config resource not found: " + configPath); + } + config.load(stream); + } else { + throw new PException("configPath format error, " + + "should be local file format as 'file:///path/to/config', " + + "or zookeeper path format as 'zk://host1:port1,host2:port2,host3:port3/path/to/config', " + + "or java resource format as 'resource:///path/to/config', " + + "but actual configPath is " + configPath); + } + return config; + } catch (Throwable e) { + if (e instanceof PException) { + throw (PException)e; + } else { + throw new PException(e); + } + } + } + + public static byte[] loadConfigFromZK(String zkUri) throws PException { + Pair zkServerAndPath = getZkServerAndPath(zkUri); + String server = zkServerAndPath.getKey(); + String path = zkServerAndPath.getValue(); + LOGGER.info("Pegasus load client information from zkServer=" + server + ", zkPath=" + path); + ZkClient client = new ZkClient(server, ZK_SESSION_TIMEOUT, ZK_CONNECTION_TIMEOUT, + new BytesPushThroughSerializer()); + return client.readData(path); + } + + protected static String getBusinessConfigZkPath(String businessName) { + return PEGASUS_BUSINESS_ROOT_NODE + SLASH + businessName; + } + + // a simple function to get server and path from zkUri: zk://server/path + // where server is formatted as 'host1:port1,host2:port2,host3:port3' + protected static Pair getZkServerAndPath(String zkUri) throws PException { + try { + // skip "zk://" + String tempZkUri = zkUri.substring(5); + int firstSlashIndex = tempZkUri.indexOf("/"); + String server = tempZkUri.substring(0, firstSlashIndex); + String path = tempZkUri.substring(firstSlashIndex); + return Pair.of(server, path); + } catch (Exception e) { + throw new PException(e); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/PException.java b/src/main/java/com/xiaomi/infra/pegasus/client/PException.java new file mode 100644 index 00000000..52ad6a3f --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/PException.java @@ -0,0 +1,29 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +/** + * @author qinzuoyan + * + * Pegasus exception. + */ +public class PException extends Exception { + private static final long serialVersionUID = 4436491238550521203L; + + public PException() { + super(); + } + + public PException(String message, Throwable cause) { + super(message, cause); + } + + public PException(String message) { + super(message); + } + + public PException(Throwable cause) { + super(cause); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/PegasusCli.java b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusCli.java new file mode 100644 index 00000000..c710151f --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusCli.java @@ -0,0 +1,252 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @author qinzuoyan + * + * This class provides a client tool to access pegasus data. + */ +public class PegasusCli { + public static void usage() { + System.out.println(); + System.out.println("USAGE: PegasusCli ..."); + System.out.println(); + System.out.println(" should be:"); + System.out.println(" - zookeeper path : zk://host1:port1,host2:port2,host3:port3/path/to/config"); + System.out.println(" - local file path : file:///path/to/config"); + System.out.println(" - java resource : resource:///path/to/config"); + System.out.println(); + System.out.println(" should be:"); + System.out.println(" - get "); + System.out.println(" - set [ttl_seconds]"); + System.out.println(" - del "); + System.out.println(" - multi_get [sort_key...]"); + System.out.println(" - multi_get_sort_keys "); + System.out.println(" - multi_set [sort_key value...]"); + System.out.println(" - multi_del [sort_key...]"); + System.out.println(" - scan [start_sort_key] [stop_sort_key] [max_count]"); + System.out.println(" - scan_all [max_count]"); + System.out.println(); + System.out.println(" For example:"); + System.out.println(" PegasusCli file://./pegasus.properties temp get hash_key sort_key"); + System.out.println(" PegasusCli file://./pegasus.properties temp scan hash_key '' '' 100"); + System.out.println(); + } + + public static void main(String args[]) { + if (args.length < 3) { + System.out.println("ERROR: invalid parameter count"); + usage(); + return; + } + String configPath = args[0]; + String appName = args[1]; + String opName = args[2]; + args = Arrays.copyOfRange(args, 3, args.length); + byte[] hashKey = null; + byte[] sortKey = null; + byte[] value = null; + int ttl_seconds = 0; + List sortKeys = new ArrayList(); + List> sortKeyValuePairs = new ArrayList>(); + byte[] startSortKey = null; + byte[] stopSortKey = null; + int maxCount = Integer.MAX_VALUE; + if (opName.equals("get") || opName.equals("del")) { + if (args.length != 2) { + System.out.println("ERROR: invalid parameter count"); + usage(); + return; + } + hashKey = args[0].getBytes(); + sortKey = args[1].getBytes(); + } + else if (opName.equals("set")) { + if (args.length != 3 && args.length != 4) { + System.out.println("ERROR: invalid parameter count"); + usage(); + return; + } + hashKey = args[0].getBytes(); + sortKey = args[1].getBytes(); + value = args[2].getBytes(); + if (args.length > 3) { + ttl_seconds = Integer.parseInt(args[3]); + } + } + else if (opName.equals("multi_get")) { + if (args.length < 1) { + System.out.println("ERROR: invalid parameter count"); + usage(); + return; + } + hashKey = args[0].getBytes(); + for (int i = 1; i < args.length; ++i) { + sortKeys.add(args[i].getBytes()); + } + } + else if (opName.equals("multi_get_sort_keys")) { + if (args.length != 1) { + System.out.println("ERROR: invalid parameter count"); + usage(); + return; + } + hashKey = args[0].getBytes(); + } + else if (opName.equals("multi_set")) { + if (args.length < 1 || args.length % 2 != 1) { + System.out.println("ERROR: invalid parameter count"); + usage(); + return; + } + hashKey = args[0].getBytes(); + for (int i = 1; i < args.length; i+=2) { + sortKeyValuePairs.add(Pair.of(args[i].getBytes(), args[i+1].getBytes())); + } + } + else if (opName.equals("multi_del")) { + if (args.length < 2) { + System.out.println("ERROR: invalid parameter count"); + usage(); + return; + } + hashKey = args[0].getBytes(); + for (int i = 1; i < args.length; ++i) { + sortKeys.add(args[i].getBytes()); + } + } + else if (opName.equals("scan")) { + if (args.length < 1 || args.length > 4) { + System.out.println("ERROR: invalid parameter count"); + usage(); + return; + } + hashKey = args[0].getBytes(); + if (args.length > 1) { + startSortKey = args[1].getBytes(); + } + if (args.length > 2) { + stopSortKey = args[2].getBytes(); + } + if (args.length > 3) { + maxCount = Integer.parseInt(args[3]); + } + } + else if (opName.equals("scan_all")) { + if (args.length > 1) { + System.out.println("ERROR: invalid parameter count"); + usage(); + return; + } + if (args.length > 0) { + maxCount = Integer.parseInt(args[0]); + } + } + else { + System.out.println("ERROR: invalid op-name: " + opName); + usage(); + return; + } + try { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(configPath); + if (opName.equals("get")) { + value = client.get(appName, hashKey, sortKey); + if (value == null) { + System.out.println("Not found"); + } + else { + System.out.printf("\"%s\"\n", new String(value)); + System.out.println(); + System.out.println("OK"); + } + } + else if (opName.equals("set")) { + client.set(appName, hashKey, sortKey, value, ttl_seconds); + System.out.println("OK"); + } + else if (opName.equals("del")) { + client.del(appName, hashKey, sortKey); + System.out.println("OK"); + } + else if (opName.equals("multi_get")) { + boolean ret = client.multiGet(appName, hashKey, sortKeys, -1, -1, sortKeyValuePairs); + for (Pair p : sortKeyValuePairs) { + System.out.printf("\"%s\":\"%s\"\t\"%s\"\n", new String(hashKey), + new String(p.getKey()), new String(p.getValue())); + } + if (sortKeyValuePairs.size() > 0) + System.out.println(); + System.out.printf("%d key-value pairs got, fetch %s.\n", + sortKeyValuePairs.size(), ret ? "completed" : "not completed"); + } + else if (opName.equals("multi_get_sort_keys")) { + boolean ret = client.multiGetSortKeys(appName, hashKey, -1, -1, sortKeys); + for (byte[] k : sortKeys) { + System.out.printf("\"%s\"\n", new String(k)); + } + if (sortKeys.size() > 0) + System.out.println(); + System.out.printf("%d sort keys got, fetch %s.\n", + sortKeys.size(), ret ? "completed" : "not completed"); + } + else if (opName.equals("multi_set")) { + client.multiSet(appName, hashKey, sortKeyValuePairs); + System.out.println("OK"); + } + else if (opName.equals("multi_del")) { + client.multiDel(appName, hashKey, sortKeys); + System.out.println("OK"); + } + else if (opName.equals("scan")) { + PegasusScannerInterface scanner = client.getScanner(appName, hashKey, + startSortKey, stopSortKey, new ScanOptions()); + int count = 0; + Pair, byte[]> p; + while (count < maxCount && (p = scanner.next()) != null) { + System.out.printf("\"%s\":\"%s\"\t\"%s\"\n", new String(p.getKey().getKey()), + new String(p.getKey().getValue()), new String(p.getValue())); + count++; + } + if (count > 0) + System.out.println(); + System.out.printf("%d key-value pairs got.\n", count); + } + else if (opName.equals("scan_all")) { + List scanners = client.getUnorderedScanners(appName, 1, new ScanOptions()); + int count = 0; + if (scanners.size() > 0) { + PegasusScannerInterface scanner = scanners.get(0); + Pair, byte[]> p; + while (count < maxCount && (p = scanner.next()) != null) { + System.out.printf("\"%s\":\"%s\"\t\"%s\"\n", new String(p.getKey().getKey()), + new String(p.getKey().getValue()), new String(p.getValue())); + count++; + } + } + if (count > 0) + System.out.println(); + System.out.printf("%d key-value pairs got.\n", count); + } + } + catch (PException e) { + e.printStackTrace(); + } + finally { + try { + PegasusClientFactory.closeSingletonClient(); + } + catch (PException e) { + e.printStackTrace(); + } + } + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/PegasusClient.java b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusClient.java new file mode 100644 index 00000000..67849ab5 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusClient.java @@ -0,0 +1,414 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import com.xiaomi.infra.pegasus.rpc.Cluster; +import com.xiaomi.infra.pegasus.rpc.KeyHasher; +import com.xiaomi.infra.pegasus.tools.tools; + +import org.apache.commons.lang3.Validate; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.ByteBuffer; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author qinzuoyan + * + * Implementation of {@link PegasusClientInterface}. + */ +public class PegasusClient implements PegasusClientInterface { + private static final Logger LOGGER = LoggerFactory.getLogger(PegasusClient.class); + + private final Properties config; + private final Cluster cluster; + private final ConcurrentHashMap tableMap; + private final Object tableMapLock; + + private static class PegasusHasher implements KeyHasher { + @Override + public long hash(byte[] key) { + Validate.isTrue(key != null && key.length >= 2); + ByteBuffer buf = ByteBuffer.wrap(key); + int hashKeyLen = 0xFFFF & buf.getShort(); + Validate.isTrue(hashKeyLen != 0xFFFF && (2 + hashKeyLen <= key.length)); + return hashKeyLen == 0 ? tools.dsn_crc64(key, 2, key.length - 2) : + tools.dsn_crc64(key, 2, hashKeyLen); + } + } + + private PegasusTable getTable(String tableName) throws PException { + PegasusTable table = tableMap.get(tableName); + if (table == null) { + synchronized (tableMapLock) { + table = tableMap.get(tableName); + if (table == null) { + try { + table = new PegasusTable(this, cluster.openTable(tableName, new PegasusHasher())); + } catch (Throwable e) { + throw new PException(e); + } + tableMap.put(tableName, table); + } + } + } + return table; + } + + // pegasus client configuration keys + public static final String[] PEGASUS_CLIENT_CONFIG_KEYS = new String[] { + Cluster.PEGASUS_META_SERVERS_KEY, + Cluster.PEGASUS_OPERATION_TIMEOUT_KEY, + Cluster.PEGASUS_ASYNC_WORKERS_KEY, + Cluster.PEGASUS_ENABLE_PERF_COUNTER_KEY, + Cluster.PEGASUS_PERF_COUNTER_TAGS_KEY + }; + + // configPath could be: + // - zk path: zk://host1:port1,host2:port2,host3:port3/path/to/config + // - local file path: file:///path/to/config + // - resource path: resource:///path/to/config + public PegasusClient(String configPath) throws PException { + this(PConfigUtil.loadConfiguration(configPath)); + } + + public PegasusClient(Properties config) throws PException { + this.config = config; + this.cluster = Cluster.createCluster(config); + this.tableMap = new ConcurrentHashMap(); + this.tableMapLock = new Object(); + LOGGER.info(getConfigurationString()); + } + + // generate rocksdb key. + public static byte[] generateKey(byte[] hashKey, byte[] sortKey) { + int hashKeyLen = (hashKey == null ? 0 : hashKey.length); + Validate.isTrue(hashKeyLen < 0xFFFF, + "length of hash key must be less than UINT16_MAX"); + int sortKeyLen = (sortKey == null ? 0 : sortKey.length); + // default byte order of ByteBuffer is BIG_ENDIAN + ByteBuffer buf = ByteBuffer.allocate(2 + hashKeyLen + sortKeyLen); + buf.putShort((short)hashKeyLen); + if (hashKeyLen > 0) { + buf.put(hashKey); + } + if (sortKeyLen > 0) { + buf.put(sortKey); + } + return buf.array(); + } + + // generate the adjacent next rocksdb key according to hash key. + public static byte[] generateNextBytes(byte[] hashKey) { + int hashKeyLen = hashKey == null ? 0 : hashKey.length; + Validate.isTrue(hashKeyLen < 0xFFFF, + "length of hash key must be less than UINT16_MAX"); + ByteBuffer buf = ByteBuffer.allocate(2 + hashKeyLen); + buf.putShort((short)hashKeyLen); + if (hashKeyLen > 0) { + buf.put(hashKey); + } + byte[] array = buf.array(); + int i = array.length - 1; + for (; i >= 0; i--) { + // 0xFF will look like -1 + if (array[i] != -1) { + array[i]++; + break; + } + } + return Arrays.copyOf(array, i + 1); + } + + // generate the adjacent next rocksdb key according to hash key and sort key. + public static byte[] generateNextBytes(byte[] hashKey, byte[] sortKey) { + byte[] array = generateKey(hashKey, sortKey); + int i = array.length - 1; + for (; i >= 0; i--) { + // 0xFF will look like -1 + if (array[i] != -1) { + array[i]++; + break; + } + } + return Arrays.copyOf(array, i + 1); + } + + public static Pair restoreKey(byte[] key) { + Validate.isTrue(key != null && key.length >= 2); + ByteBuffer buf = ByteBuffer.wrap(key); + int hashKeyLen = 0xFFFF & buf.getShort(); + Validate.isTrue(hashKeyLen != 0xFFFF && (2 + hashKeyLen <= key.length)); + return new ImmutablePair( + Arrays.copyOfRange(key, 2, 2 + hashKeyLen), + Arrays.copyOfRange(key, 2 + hashKeyLen, key.length) + ); + } + + public static int bytesCompare(byte[] left, byte[] right) { + int len = Math.min(left.length, right.length); + for (int i = 0; i < len; i++) { + int ret = (0xFF & left[i]) - (0xFF & right[i]); + if (ret != 0) + return ret; + } + return left.length - right.length; + } + + public String getConfigurationString() { + String configString = "PegasusClient Configuration:\n"; + if (this.config == null) { + return configString; + } + for (int i = 0; i < PEGASUS_CLIENT_CONFIG_KEYS.length; ++i) { + configString += (PEGASUS_CLIENT_CONFIG_KEYS[i] + "=" + + this.config.getProperty(PEGASUS_CLIENT_CONFIG_KEYS[i], "") + "\n"); + } + return configString; + } + + @Override + public void close() { + cluster.close(); + } + + @Override + public PegasusTableInterface openTable(String tableName) throws PException { + return getTable(tableName); + } + + @Override + public Properties getConfiguration() { + return config; + } + + @Override + public boolean exist(String tableName, byte[] hashKey, byte[] sortKey) throws PException { + PegasusTable tb = getTable(tableName); + return tb.exist(hashKey, sortKey, 0); + } + + @Override + public long sortKeyCount(String tableName, byte[] hashKey) throws PException { + PegasusTable tb = getTable(tableName); + return tb.sortKeyCount(hashKey, 0); + } + + @Override + public byte[] get(String tableName, byte[] hashKey, byte[] sortKey) throws PException { + PegasusTable tb = getTable(tableName); + return tb.get(hashKey, sortKey, 0); + } + + @Override + public void batchGet(String tableName, List> keys, List values) throws PException { + PegasusTable tb = getTable(tableName); + tb.batchGet(keys, values, 0); + } + + @Override + public int batchGet2(String tableName, List> keys, + List> values) throws PException { + PegasusTable tb = getTable(tableName); + return tb.batchGet2(keys, values, 0); + } + + @Override + public boolean multiGet(String tableName, byte[] hashKey, List sortKeys, int maxFetchCount, int maxFetchSize, + List> values) throws PException { + if (values == null) { + throw new PException("Invalid parameter: values should not be null"); + } + PegasusTable tb = getTable(tableName); + PegasusTableInterface.MultiGetResult res = tb.multiGet(hashKey, sortKeys, maxFetchCount, maxFetchSize, 0); + for (Pair kv : res.values) { + values.add(kv); + } + return res.allFetched; + } + + @Override + public boolean multiGet(String tableName, byte[] hashKey, List sortKeys, + List> values) throws PException { + return multiGet(tableName, hashKey, sortKeys, 100, 1000000, values); + } + + @Override + public boolean multiGet(String tableName, byte[] hashKey, + byte[] startSortKey, byte[] stopSortKey, MultiGetOptions options, + int maxFetchCount, int maxFetchSize, + List> values) throws PException { + if (values == null) { + throw new PException("Invalid parameter: values should not be null"); + } + PegasusTable tb = getTable(tableName); + PegasusTableInterface.MultiGetResult res = tb.multiGet( + hashKey, startSortKey, stopSortKey, options, maxFetchCount, maxFetchSize, 0); + for (Pair kv : res.values) { + values.add(kv); + } + return res.allFetched; + } + + @Override + public boolean multiGet(String tableName, byte[] hashKey, + byte[] startSortKey, byte[] stopSortKey, MultiGetOptions options, + List> values) throws PException { + return multiGet(tableName, hashKey, startSortKey, stopSortKey, options, 100, 1000000, values); + } + + @Override + public void batchMultiGet(String tableName, List>> keys, + List values) throws PException { + PegasusTable tb = getTable(tableName); + tb.batchMultiGet(keys, values, 0); + } + + @Override + public int batchMultiGet2(String tableName, List>> keys, + List> results) throws PException { + PegasusTable tb = getTable(tableName); + return tb.batchMultiGet2(keys, results, 0); + } + + @Override + public boolean multiGetSortKeys(String tableName, byte[] hashKey, int maxFetchCount, int maxFetchSize, + List sortKeys) throws PException { + if (sortKeys == null) { + throw new PException("Invalid parameter: sortKeys should not be null"); + } + PegasusTable table = getTable(tableName); + PegasusTableInterface.MultiGetSortKeysResult result = table.multiGetSortKeys(hashKey, maxFetchCount, maxFetchSize, 0); + for (byte[] key: result.keys) { + sortKeys.add(key); + } + return result.allFetched; + } + + @Override + public boolean multiGetSortKeys(String tableName, byte[] hashKey, List sortKeys) throws PException { + return multiGetSortKeys(tableName, hashKey, 100, 1000000, sortKeys); + } + + @Override + public void set(String tableName, byte[] hashKey, byte[] sortKey, byte[] value, int ttl_seconds) throws PException { + PegasusTable tb = getTable(tableName); + tb.set(hashKey, sortKey, value, ttl_seconds, 0); + } + + @Override + public void set(String tableName, byte[] hashKey, byte[] sortKey, byte[] value) throws PException { + set(tableName, hashKey, sortKey, value, 0); + } + + @Override + public void batchSet(String tableName, List items) throws PException { + PegasusTable tb = getTable(tableName); + tb.batchSet(items, 0); + } + + @Override + public int batchSet2(String tableName, List items, List results) throws PException { + PegasusTable tb = getTable(tableName); + return tb.batchSet2(items, results, 0); + } + + @Override + public void multiSet(String tableName, byte[] hashKey, List> values, int ttl_seconds) throws PException { + PegasusTable tb = getTable(tableName); + tb.multiSet(hashKey, values, ttl_seconds, 0); + } + + @Override + public void multiSet(String tableName, byte[] hashKey, List> values) throws PException { + multiSet(tableName, hashKey, values, 0); + } + + @Override + public void batchMultiSet(String tableName, List items, int ttl_seconds) throws PException { + PegasusTable tb = getTable(tableName); + tb.batchMultiSet(items, ttl_seconds, 0); + } + + @Override + public void batchMultiSet(String tableName, List items) throws PException { + batchMultiSet(tableName, items, 0); + } + + @Override + public int batchMultiSet2(String tableName, List items, + int ttl_seconds, List results) throws PException { + PegasusTable tb = getTable(tableName); + return tb.batchMultiSet2(items, ttl_seconds, results, 0); + } + + @Override + public int batchMultiSet2(String tableName, List items, + List results) throws PException { + return batchMultiSet2(tableName, items, 0, results); + } + + @Override + public void del(String tableName, byte[] hashKey, byte[] sortKey) throws PException { + PegasusTable tb = getTable(tableName); + tb.del(hashKey, sortKey, 0); + } + + @Override + public void batchDel(String tableName, List> keys) throws PException { + PegasusTable tb = getTable(tableName); + tb.batchDel(keys, 0); + } + + @Override + public int batchDel2(String tableName, List> keys, + List results) throws PException { + PegasusTable tb = getTable(tableName); + return tb.batchDel2(keys, results, 0); + } + + @Override + public void multiDel(String tableName, byte[] hashKey, List sortKeys) throws PException { + PegasusTable tb = getTable(tableName); + tb.multiDel(hashKey, sortKeys, 0); + } + + @Override + public void batchMultiDel(String tableName, List>> keys) throws PException { + PegasusTable tb = getTable(tableName); + tb.batchMultiDel(keys, 0); + } + + @Override + public int batchMultiDel2(String tableName, List>> keys, + List results) throws PException { + PegasusTable tb = getTable(tableName); + return tb.batchMultiDel2(keys, results, 0); + } + + @Override + public int ttl(String tableName, byte[] hashKey, byte[] sortKey) throws PException { + PegasusTable tb = getTable(tableName); + return tb.ttl(hashKey, sortKey, 0); + } + + @Override + public PegasusScannerInterface getScanner(String tableName, byte[] hashKey, + byte[] startSortKey, byte[] stopSortKey, ScanOptions options) + throws PException { + PegasusTable tb = getTable(tableName); + return tb.getScanner(hashKey, startSortKey, stopSortKey, options); + } + + @Override + public List getUnorderedScanners(String tableName, + int maxSplitCount, ScanOptions options) throws PException { + PegasusTable tb = getTable(tableName); + return tb.getUnorderedScanners(maxSplitCount, options); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/PegasusClientFactory.java b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusClientFactory.java new file mode 100644 index 00000000..2565f9b9 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusClientFactory.java @@ -0,0 +1,70 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author qinzuoyan + * + * This class provides interfaces to create an instance of {@link PegasusClientInterface}. + */ +public class PegasusClientFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(PegasusClientFactory.class); + + private static volatile PegasusClient singletonClient = null; + private static String singletonClientConfigPath = null; + private static Object singletonClientLock = new Object(); + + // Create a client instance. + // After used, should call client.close() to release resource. + public static PegasusClientInterface createClient(String configPath) throws PException { + return new PegasusClient(configPath); + } + + // Get the singleton client instance with default config path of "resource:///pegasus.properties". + public static PegasusClientInterface getSingletonClient() throws PException { + return getSingletonClient("resource:///pegasus.properties"); + } + + // Get the singleton client instance. + // After used, should call PegasusClientFactory.closeSingletonClient() to release resource. + // + // configPath could be: + // - zookeeper path : zk://host1:port1,host2:port2,host3:port3/path/to/config + // - local file path : file:///path/to/config + // - java resource : resource:///path/to/config + public static PegasusClientInterface getSingletonClient(String configPath) throws PException { + synchronized (singletonClientLock) { + if (singletonClient == null) { + try { + singletonClient = new PegasusClient(configPath); + singletonClientConfigPath = configPath; + LOGGER.info("Create Singleton PegasusClient with config path \"" + configPath + "\""); + } catch (Throwable e) { + throw new PException("Create Singleton PegasusClient Failed", e); + } + } + else if (!singletonClientConfigPath.equals(configPath)){ + LOGGER.error("Singleton PegasusClient Config Path Conflict: \"" + + configPath + "\" VS \"" + singletonClientConfigPath + "\""); + throw new PException("Singleton PegasusClient Config Path Conflict"); + } + return singletonClient; + } + } + + // Close the singleton client instance. + public static void closeSingletonClient() throws PException { + synchronized (singletonClientLock) { + if (singletonClient != null) { + LOGGER.info("Close Singleton PegasusClient with config path \"" + singletonClientConfigPath + "\""); + singletonClient.close(); + singletonClient = null; + singletonClientConfigPath = null; + } + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/PegasusClientInterface.java b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusClientInterface.java new file mode 100644 index 00000000..2e9f6836 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusClientInterface.java @@ -0,0 +1,425 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import io.netty.util.concurrent.Future; +import org.apache.commons.lang3.tuple.Pair; + +import java.util.*; + +/** + * @author qinzuoyan + * + * This class provides interfaces to access data of a specified cluster. + */ +public interface PegasusClientInterface { + /** + * Get pegasus configuration for client. + * @return config + */ + public Properties getConfiguration(); + + /** + * Close the client. The client can not be used again after closed. + */ + public void close(); + + /** + * Open a table. Please notice that pegasus support two kinds of API: + * 1. the client-interface way, which is provided in this class. + * 2. the table-interface way, which is provided by {@link PegasusTableInterface}. + * With the client-interface, you don't need to create PegasusTableInterface by openTable, so + * you can access the pegasus cluster conveniently. However, the client-interface's api also has + * some restrictions: + * 1. we don't provide async methods in client-interface. + * 2. the timeout in client-interface isn't as accurate as the table-interface. + * 3. the client-interface may throw an exception when open table fails. It means that + * you may need to handle this exception in every data access operation, which is annoying. + * 4. You can't specify a per-operation timeout. + * So we recommend you to use the table-interface. + * + * @param tableName the table should be exist on the server, which is created before by + * the system administrator + * @return the table handler + * @throws PException + */ + public PegasusTableInterface openTable(String tableName) throws PException; + + /** + * Check value exist by key from the cluster + * @param tableName TableHandler name + * @param hashKey used to decide which partition the key may exist. + * @param sortKey all keys under the same hashKey will be sorted by sortKey + * + * @return true if exist, false if not exist + * @throws PException + */ + public boolean exist(String tableName, byte[] hashKey, byte[] sortKey) throws PException; + + /** + * @param tableName TableHandler name + * @param hashKey used to decide which partition the key may exist. + * @return the count result for the hashKey + * @throws PException + */ + public long sortKeyCount(String tableName, byte[] hashKey) throws PException; + + /** + * Get value. + * @param tableName TableHandler name + * @param hashKey used to decide which partition to get this k-v, + * if null or length == 0, means no hash key. + * @param sortKey all the k-v under hashKey will be sorted by sortKey, + * if null or length == 0, means no sort key. + * @return value; null if not found + * @throws PException + */ + public byte[] get(String tableName, byte[] hashKey, byte[] sortKey) throws PException; + + /** + * Batch get values of different keys. + * Will terminate immediately if any error occurs. + * @param tableName table name + * @param keys hashKey and sortKey pair list. + * @param values output values; should be created by caller; if succeed, the size of values will + * be same with keys; the value of keys[i] is stored in values[i]; if the value of + * keys[i] is not found, then values[i] will be set to null. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchGet(String tableName, List> keys, + List values) throws PException; + + /** + * Batch get values of different keys. + * Will wait for all requests done even if some error occurs. + * @param tableName table name + * @param keys hashKey and sortKey pair list. + * @param results output results; should be created by caller; after call done, the size of results will + * be same with keys; the results[i] is a Pair: + * - if Pair.left != null : means query keys[i] failed, Pair.left is the exception. + * - if Pair.left == null : means query keys[i] succeed, Pair.right is the result value. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchGet2(String tableName, List> keys, + List> results) throws PException; + + /** + * Get multiple values under the same hash key. + * @param tableName table name + * @param hashKey used to decide which partition to put this k-v, + * should not be null or empty. + * @param sortKeys all the k-v under hashKey will be sorted by sortKey, + * if null or empty, means fetch all sortKeys under the hashKey. + * @param maxFetchCount max count of k-v pairs to be fetched. + * max_fetch_count <= 0 means no limit. default value is 100. + * @param maxFetchSize max size of k-v pairs to be fetched. + * max_fetch_size <= 0 means no limit. default value is 1000000. + * @param values output values; if sortKey is not found, then it will not appear in values. + * the returned sortKey is just the same one in incoming sortKeys. + * @return true if all data is fetched; false if only partial data is fetched. + * @throws PException + */ + public boolean multiGet(String tableName, byte[] hashKey, List sortKeys, + int maxFetchCount, int maxFetchSize, + List> values) throws PException; + public boolean multiGet(String tableName, byte[] hashKey, List sortKeys, + List> values) throws PException; + + /** + * Get multiple key-values under the same hashKey with sortKey range limited. + * @param tableName table name + * @param hashKey used to decide which partition the key may exist + * should not be null or empty. + * @param startSortKey the start sort key. + * null means "". + * @param stopSortKey the stop sort key. + * null or "" means fetch to the last sort key. + * @param options multi-get options. + * @param maxFetchCount max count of kv pairs to be fetched + * maxFetchCount <= 0 means no limit. default value is 100 + * @param maxFetchSize max size of kv pairs to be fetched. + * maxFetchSize <= 0 means no limit. default value is 1000000. + * @param values output values; if sortKey is not found, then it will not appear in values. + * the returned sortKey is just the same one in incoming sortKeys. + * @return true if all data is fetched; false if only partial data is fetched. + * @throws PException + */ + public boolean multiGet(String tableName, byte[] hashKey, + byte[] startSortKey, byte[] stopSortKey, MultiGetOptions options, + int maxFetchCount, int maxFetchSize, + List> values) throws PException; + public boolean multiGet(String tableName, byte[] hashKey, + byte[] startSortKey, byte[] stopSortKey, MultiGetOptions options, + List> values) throws PException; + + /** + * Batch get multiple values under the same hash key. + * Will terminate immediately if any error occurs. + * @param tableName table name + * @param keys List{hashKey,List{sortKey}}; if List{sortKey} is null or empty, means fetch all + * sortKeys under the hashKey. + * @param values output values; should be created by caller; if succeed, the size of values will + * be same with keys; the data for keys[i] is stored in values[i]. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchMultiGet(String tableName, List>> keys, + List values) throws PException; + + /** + * Batch get multiple values under the same hash key. + * Will wait for all requests done even if some error occurs. + * @param tableName table name + * @param keys List{hashKey,List{sortKey}}; if List{sortKey} is null or empty, means fetch all + * sortKeys under the hashKey. + * @param results output results; should be created by caller; after call done, the size of results will + * be same with keys; the results[i] is a Pair: + * - if Pair.left != null : means query keys[i] failed, Pair.left is the exception. + * - if Pair.left == null : means query keys[i] succeed, Pair.right is the result value. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchMultiGet2(String tableName, List>> keys, + List> results) throws PException; + + /** + * Get multiple sort keys under the same hash key. + * @param tableName table name + * @param hashKey used to decide which partition to put this k-v, + * should not be null or empty. + * @param maxFetchCount max count of k-v pairs to be fetched. + * max_fetch_count <= 0 means no limit. default value is 100. + * @param maxFetchSize max size of k-v pairs to be fetched. + * max_fetch_size <= 0 means no limit. default value is 1000000. + * @param sortKeys output sort keys. + * @return true if all data is fetched; false if only partial data is fetched. + * @throws PException + */ + public boolean multiGetSortKeys(String tableName, byte[] hashKey, + int maxFetchCount, int maxFetchSize, + List sortKeys) throws PException; + public boolean multiGetSortKeys(String tableName, byte[] hashKey, + List sortKeys) throws PException; + + /** + * Set value. + * @param tableName TableHandler name + * @param hashKey used to decide which partition to put this k-v, + * if null or length == 0, means no hash key. + * @param sortKey all the k-v under hashKey will be sorted by sortKey, + * if null or length == 0, means no sort key. + * @param value should not be null + * @param ttl_seconds time to live in seconds, + * 0 means no ttl. default value is 0. + * @throws PException + */ + public void set(String tableName, byte[] hashKey, byte[] sortKey, + byte[] value, int ttl_seconds) throws PException; + public void set(String tableName, byte[] hashKey, byte[] sortKey, + byte[] value) throws PException; + + /** + * Batch set lots of values. + * Will terminate immediately if any error occurs. + * @param tableName TableHandler name + * @param items list of items. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchSet(String tableName, List items) throws PException; + + /** + * Batch set lots of values. + * Will wait for all requests done even if some error occurs. + * @param tableName table name + * @param items list of items. + * @param results output results; should be created by caller; after call done, the size of results will + * be same with items; the results[i] is a PException: + * - if results[i] != null : means set items[i] failed, results[i] is the exception. + * - if results[i] == null : means set items[i] succeed. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchSet2(String tableName, List items, List results) throws PException; + + /** + * Set multiple value under the same hash key. + * @param tableName table name + * @param hashKey used to decide which partition to put this k-v, + * should not be null or empty. + * @param values all pairs to be set, + * should not be null or empty. + * @param ttl_seconds time to live in seconds, + * 0 means no ttl. default value is 0. + * @throws PException + */ + public void multiSet(String tableName, byte[] hashKey, + List> values, int ttl_seconds) throws PException; + public void multiSet(String tableName, byte[] hashKey, + List> values) throws PException; + + /** + * Batch set multiple value under the same hash key. + * Will terminate immediately if any error occurs. + * @param tableName TableHandler name + * @param items list of items. + * @param ttl_seconds time to live in seconds, + * 0 means no ttl. default value is 0. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchMultiSet(String tableName, List items, int ttl_seconds) throws PException; + public void batchMultiSet(String tableName, List items) throws PException; + + /** + * Batch set multiple value under the same hash key. + * Will wait for all requests done even if some error occurs. + * @param tableName table name + * @param items list of items. + * @param ttl_seconds time to live in seconds, + * 0 means no ttl. default value is 0. + * @param results output results; should be created by caller; after call done, the size of results will + * be same with items; the results[i] is a PException: + * - if results[i] != null : means set items[i] failed, results[i] is the exception. + * - if results[i] == null : means set items[i] succeed. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchMultiSet2(String tableName, List items, + int ttl_seconds, List results) throws PException; + public int batchMultiSet2(String tableName, List items, + List results) throws PException; + + /** + * Delete value. + * @param tableName TableHandler name + * @param hashKey used to decide which partition to put this k-v, + * if null or length == 0, means no hash key. + * @param sortKey all the k-v under hashKey will be sorted by sortKey, + * if null or length == 0, means no sort key. + * @throws PException + */ + public void del(String tableName, byte[] hashKey, byte[] sortKey) throws PException; + + /** + * Batch delete values of different keys. + * Will terminate immediately if any error occurs. + * @param tableName table name + * @param keys hashKey and sortKey pair list. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchDel(String tableName, List> keys) throws PException; + + /** + * Batch delete values of different keys. + * Will wait for all requests done even if some error occurs. + * @param tableName table name + * @param keys hashKey and sortKey pair list. + * @param results output results; should be created by caller; after call done, the size of results will + * be same with keys; the results[i] is a PException: + * - if results[i] != null : means del keys[i] failed, results[i] is the exception. + * - if results[i] == null : means del keys[i] succeed. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchDel2(String tableName, List> keys, + List results) throws PException; + + /** + * Delete specified sort keys under the same hash key. + * @param tableName table name + * @param hashKey used to decide which partition to put this k-v, + * should not be null or empty. + * @param sortKeys specify sort keys to be deleted. + * should not be empty. + * @throws PException + */ + public void multiDel(String tableName, byte[] hashKey, List sortKeys) throws PException; + + /** + * Batch delete specified sort keys under the same hash key. + * Will terminate immediately if any error occurs. + * @param tableName table name + * @param keys List{hashKey,List{sortKey}} + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchMultiDel(String tableName, List>> keys) throws PException; + + /** + * Batch delete specified sort keys under the same hash key. + * Will wait for all requests done even if some error occurs. + * @param tableName table name + * @param keys List{hashKey,List{sortKey}} + * @param results output results; should be created by caller; after call done, the size of results will + * be same with keys; the results[i] is a PException: + * - if results[i] != null : means del keys[i] failed, results[i] is the exception. + * - if results[i] == null : means del keys[i] succeed. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchMultiDel2(String tableName, List>> keys, + List results) throws PException; + + /** + * Get ttl time. + * @param tableName TableHandler name + * @param hashKey used to decide which partition to put this k-v, + * if null or length == 0, means no hash key. + * @param sortKey all the k-v under hashKey will be sorted by sortKey, + * if null or length == 0, means no sort key. + * @return ttl time in seconds; -1 if no ttl set; -2 if not exist. + * @throws PException + */ + public int ttl(String tableName, byte[] hashKey, byte[] sortKey) throws PException; + + /** + * Get Scanner for {startSortKey, stopSortKey} within hashKey + * @param tableName TableHandler name + * @param hashKey used to decide which partition to put this k-v, + * @param startSortKey start sort key scan from + * if null or length == 0, means start from begin + * @param stopSortKey stop sort key scan to + * if null or length == 0, means stop to end + * @param options scan options like endpoint inclusive/exclusive + * @return scanner + * @throws PException + */ + public PegasusScannerInterface getScanner(String tableName, byte[] hashKey, + byte[] startSortKey, byte[] stopSortKey, ScanOptions options) + throws PException; + + /** + * Get Scanners for all data in database + * @param tableName TableHandler name + * @param maxSplitCount how many scanner expected + * @param options scan options like batchSize + * @return scanners, count of which would be no more than maxSplitCount + * @throws PException + */ + public List getUnorderedScanners( + String tableName, int maxSplitCount, ScanOptions options) + throws PException; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/PegasusScanner.java b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusScanner.java new file mode 100644 index 00000000..e357f46b --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusScanner.java @@ -0,0 +1,272 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import com.xiaomi.infra.pegasus.rpc.ReplicationException; +import com.xiaomi.infra.pegasus.apps.*; +import com.xiaomi.infra.pegasus.rpc.Table; +import com.xiaomi.infra.pegasus.base.blob; +import com.xiaomi.infra.pegasus.base.gpid; +import com.xiaomi.infra.pegasus.base.error_code; +import com.xiaomi.infra.pegasus.operator.client_operator; +import com.xiaomi.infra.pegasus.operator.rrdb_clear_scanner_operator; +import com.xiaomi.infra.pegasus.operator.rrdb_get_scanner_operator; +import com.xiaomi.infra.pegasus.operator.rrdb_scan_operator; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import io.netty.util.concurrent.*; +import org.slf4j.Logger; + +/** + * @author shenyuannan + * + * Implementation of {@link PegasusScannerInterface}. + */ +public class PegasusScanner implements PegasusScannerInterface { + private static final blob min = new blob(new byte[]{0, 0}); + private static final blob max = new blob(new byte[]{-1, -1}); + private static final int CONTEXT_ID_VALID_MIN = 0; + private static final int CONTEXT_ID_COMPLETED = -1; + private static final int CONTEXT_ID_NOT_EXIST = -2; + + public PegasusScanner(Table table, gpid[] splitHash, ScanOptions options) { + this(table, splitHash, options, min, max); + options.startInclusive = true; + options.stopInclusive = false; + } + + public PegasusScanner(Table table, gpid[] splitHash, ScanOptions options, + blob startKey, blob stopKey) { + _table = table; + _split_gpid = splitHash == null ? new gpid[0] : splitHash; + _options = options; + _startKey = startKey; + _stopKey = stopKey; + _p = -1; + _context = CONTEXT_ID_COMPLETED; + _hash_p = _split_gpid.length; + _kvs = new ArrayList(); + _promises = new LinkedList, byte[]>>>(); + _rpcRunning = false; + _encounterError = false; + } + + public Pair, byte[]> next() throws PException { + try { + return asyncNext().get(_options.timeoutMillis, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + public Future, byte[]>> asyncNext() { + final DefaultPromise, byte[]>> promise = _table.newPromise(); + synchronized (_promisesLock) { + if (_promises.isEmpty()) { + _promises.add(promise); + asyncNextInternal(); + } + else { + // rpc is running, callback will be executed in the callback of rpc + _promises.add(promise); + } + } + return promise; + } + + @Override + public void close() { + if (_context >= CONTEXT_ID_VALID_MIN) { + try { + rrdb_clear_scanner_operator op = new rrdb_clear_scanner_operator(_gpid, _table.getTableName(), _context); + _table.operate(op, 0); + } catch (Throwable e) { + // ignore + } + _context = CONTEXT_ID_COMPLETED; + } + _hash_p = 0; + } + + private void asyncStartScan() { + if (_rpcRunning) { + logger.error("scan rpc already be running, encounter logic error, we just abandon this scan, " + + "tableName({}), appId({})", _table.getTableName(), _table.getAppID()); + _encounterError = true; + _cause = new PException("scan internal error, rpc is already started"); + return; + } + _rpcRunning = true; + get_scanner_request request = new get_scanner_request(); + if (_kvs.isEmpty()) { + request.start_key = _startKey; + request.start_inclusive = _options.startInclusive; + } else { + request.start_key = _kvs.get(_kvs.size() - 1).key; + request.start_inclusive = false; + } + request.stop_key = _stopKey; + request.stop_inclusive = _options.stopInclusive; + request.batch_size = _options.batchSize; + request.no_value = _options.noValue; + request.hash_key_filter_type = filter_type.findByValue(_options.hashKeyFilterType.getValue()); + request.hash_key_filter_pattern = + (_options.hashKeyFilterPattern == null ?null : new blob(_options.hashKeyFilterPattern)); + request.sort_key_filter_type = filter_type.findByValue(_options.sortKeyFilterType.getValue()); + request.sort_key_filter_pattern = + (_options.sortKeyFilterPattern == null ?null : new blob(_options.sortKeyFilterPattern)); + + rrdb_get_scanner_operator op = new rrdb_get_scanner_operator(_gpid, _table.getTableName(), request); + Table.ClientOPCallback callback = new Table.ClientOPCallback() { + @Override + public void onCompletion(client_operator clientOP) throws Throwable { + rrdb_get_scanner_operator op = (rrdb_get_scanner_operator)(clientOP); + scan_response response = op.get_response(); + synchronized (_promisesLock) { + onRecvRpcResponse(op.rpc_error, response); + asyncNextInternal(); + } + } + }; + _table.asyncOperate(op, callback, _options.timeoutMillis); + } + + private void asyncNextBatch() { + if (_rpcRunning) { + logger.error("scan rpc already be running, encounter logic error, we just abandon this scan, " + + "tableName({}), appId({})", _table.getTableName(), _table.getAppID()); + _encounterError = true; + _cause = new PException("scan internal error, rpc is already started"); + return; + } + _rpcRunning = true; + scan_request request = new scan_request(_context); + rrdb_scan_operator op = new rrdb_scan_operator(_gpid, _table.getTableName(), request); + Table.ClientOPCallback callback = new Table.ClientOPCallback() { + @Override + public void onCompletion(client_operator clientOP) throws Throwable { + rrdb_scan_operator op = (rrdb_scan_operator)(clientOP); + scan_response response = op.get_response(); + synchronized (_promisesLock) { + onRecvRpcResponse(op.rpc_error, response); + asyncNextInternal(); + } + } + }; + _table.asyncOperate(op, callback, _options.timeoutMillis); + } + + private void onRecvRpcResponse(error_code err, scan_response response) { + if (!_rpcRunning) { + logger.error("scan rpc haven't been started, encounter logic error, we just abandon this scan, " + + "tableName({}), appId({})", _table.getTableName(), _table.getAppID()); + _encounterError = true; + _cause = new PException("scan internal error, rpc haven't been started"); + return; + } + _rpcRunning = false; + + if (err.errno == error_code.error_types.ERR_OK) { + if (response.error == 0) { // ERR_OK + _kvs = response.kvs; + _p = -1; + _context = response.context_id; + } + else if (response.error == 1) { // rocksDB error kNotFound, that scan context has been removed + _context = CONTEXT_ID_NOT_EXIST; + } + else { // rpc succeed, but operation encounter some error in server side + _encounterError = true; + _cause = new PException("rocksDB error: " + response.error); + } + } + else { // rpc failed + _encounterError = true; + _cause = new PException("scan failed with error: " + err.errno); + } + } + + private void asyncNextInternal() { + if (_encounterError) { + for (DefaultPromise, byte[]>> p : _promises) { + p.setFailure(_cause); + } + _promises.clear(); + // we don't reset the flag, just abandon this scan operation + // _encounterError = false; + return; + } + while (!_promises.isEmpty()) { + while (++_p >= _kvs.size()) { + if (_context == CONTEXT_ID_COMPLETED) { + // reach the end of one partition + if (_hash_p <= 0) { + for (DefaultPromise, byte[]>> p : _promises) { + p.setSuccess(null); + } + _promises.clear(); + return ; + } else { + _gpid = _split_gpid[--_hash_p]; + splitReset(); + } + } else if (_context == CONTEXT_ID_NOT_EXIST) { + // no valid context_id found + asyncStartScan(); + return; + } else { + asyncNextBatch(); + return; + } + } + DefaultPromise, byte[]>> p = _promises.getFirst(); + p.setSuccess(new ImmutablePair, byte[]>( + PegasusClient.restoreKey(_kvs.get(_p).key.data), + _kvs.get(_p).value.data)); + _promises.removeFirst(); + } + } + + private void splitReset() { + _kvs.clear(); + _p = -1; + _context = CONTEXT_ID_NOT_EXIST; + } + + private Table _table; + private blob _startKey; + private blob _stopKey; + private ScanOptions _options; + private gpid[] _split_gpid; + private int _hash_p; + + private gpid _gpid; + private List _kvs; + private int _p; + + private long _context; + + final private Object _promisesLock = new Object(); + private Deque, byte[]>>> _promises; + private boolean _rpcRunning; + // mark whether scan operation encounter error + private boolean _encounterError; + Throwable _cause; + + private static final Logger logger = org.slf4j.LoggerFactory.getLogger(PegasusScanner.class); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/PegasusScannerInterface.java b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusScannerInterface.java new file mode 100644 index 00000000..eb074bc4 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusScannerInterface.java @@ -0,0 +1,36 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.concurrent.Future; +/** + * @author shenyuannan + * + * This class provides interfaces to scan data of a specified table. + */ +public interface PegasusScannerInterface { + /** + * Get the next item. + * @return item like <, value>; null returned if scan completed. + * @throws PException + */ + public Pair, byte[]> next() throws PException; + + /** + * Get the next item asynchronously. + * @return A future for current op. + * + * Future return: + * On success: if scan haven't reach the end then return the kv-pair, else return null. + * On failure: a throwable, which is an instance of PException. + */ + public Future, byte[]>> asyncNext(); + + /** + * Close the scanner. Should be called when scan completed. + */ + public void close(); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/PegasusTable.java b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusTable.java new file mode 100644 index 00000000..764a4a2f --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusTable.java @@ -0,0 +1,1166 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import com.xiaomi.infra.pegasus.rpc.ReplicationException; +import com.xiaomi.infra.pegasus.rpc.Table; +import com.xiaomi.infra.pegasus.apps.*; + +import com.xiaomi.infra.pegasus.base.blob; +import com.xiaomi.infra.pegasus.base.error_code; +import com.xiaomi.infra.pegasus.base.gpid; + +import com.xiaomi.infra.pegasus.operator.*; +import com.xiaomi.infra.pegasus.tools.tools; + +import io.netty.util.concurrent.*; +import org.apache.commons.lang3.Validate; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +/** + * @author sunweijie + * + * Implementation of {@link PegasusTableInterface}. + */ +public class PegasusTable implements PegasusTableInterface { + private PegasusClient client; + private Table table; + private int defaultTimeout; + + public PegasusTable(PegasusClient client, Table table) { + this.client = client; + this.table = table; + this.defaultTimeout = table.getDefaultTimeout(); + } + + @Override + public Future asyncExist(byte[] hashKey, byte[] sortKey, int timeout) { + final DefaultPromise promise = table.newPromise(); + asyncTTL(hashKey, sortKey, timeout).addListener( + new TTLListener() { + @Override + public void operationComplete(Future future) throws Exception { + if (future.isSuccess()) { + promise.setSuccess(future.get()!=-2); + } + else { + promise.setFailure(future.cause()); + } + } + } + ); + return promise; + } + + @Override + public Future asyncSortKeyCount(byte[] hashKey, int timeout) { + final DefaultPromise promise = table.newPromise(); + if (hashKey == null || hashKey.length == 0) { + promise.setFailure(new PException("Invalid parameter: hashKey should not be null or empty")); + return promise; + } + if (hashKey.length >= 0xFFFF) { + promise.setFailure(new PException("Invalid parameter: hashKey length should be less than UINT16_MAX")); + return promise; + } + + blob hashKeyRequest = new blob(hashKey); + gpid pid = table.getHashKeyGpid(hashKey); + rrdb_sortkey_count_operator op = new rrdb_sortkey_count_operator(pid, table.getTableName(), hashKeyRequest); + Table.ClientOPCallback callback = new Table.ClientOPCallback() { + @Override + public void onCompletion(client_operator clientOP) { + rrdb_sortkey_count_operator op = (rrdb_sortkey_count_operator) clientOP; + if (op.rpc_error.errno != error_code.error_types.ERR_OK) { + promise.setFailure(new PException(new ReplicationException(op.rpc_error.errno))); + } + else if (op.get_response().error != 0) { + promise.setFailure(new PException("rocksdb error: " + op.get_response().error)); + } + else { + promise.setSuccess(op.get_response().count); + } + } + }; + + table.asyncOperate(op, callback, timeout); + return promise; + } + + @Override + public Future asyncGet(byte[] hashKey, byte[] sortKey, int timeout/*ms*/) { + final DefaultPromise promise = table.newPromise(); + blob request = new blob(PegasusClient.generateKey(hashKey, sortKey)); + gpid gpid = table.getGpid(request.data); + rrdb_get_operator op = new rrdb_get_operator(gpid, table.getTableName(), request); + Table.ClientOPCallback callback = new Table.ClientOPCallback() { + @Override + public void onCompletion(client_operator clientOP) { + rrdb_get_operator gop = (rrdb_get_operator) clientOP; + if (gop.rpc_error.errno != error_code.error_types.ERR_OK) { + promise.setFailure(new PException(new ReplicationException(gop.rpc_error.errno))); + } + else if (gop.get_response().error == 1) {//rocksdb::kNotFound + promise.setSuccess(null); + } + else if (gop.get_response().error != 0) { + promise.setFailure(new PException("rocksdb error: " + gop.get_response().error)); + } + else { + promise.setSuccess(gop.get_response().value.data); + } + } + }; + + table.asyncOperate(op, callback, timeout); + return promise; + } + + @Override + public Future asyncSet(byte[] hashKey, byte[] sortKey, byte[] value, int ttlSeconds, int timeout/*ms*/) { + final DefaultPromise promise = table.newPromise(); + if (value == null) { + promise.setFailure(new PException("Invalid parameter: value should not be null")); + return promise; + } + + blob k = new blob(PegasusClient.generateKey(hashKey, sortKey)); + blob v = new blob(value); + int expireSeconds = (ttlSeconds == 0 ? 0 : ttlSeconds + (int) tools.epoch_now()); + update_request req = new update_request(k, v, expireSeconds); + + gpid gpid = table.getGpid(k.data); + rrdb_put_operator op = new rrdb_put_operator(gpid, table.getTableName(), req); + table.asyncOperate( + op, + new Table.ClientOPCallback() { + @Override + public void onCompletion(client_operator clientOP) { + rrdb_put_operator gop = (rrdb_put_operator) clientOP; + if (gop.rpc_error.errno != error_code.error_types.ERR_OK) { + promise.setFailure(new PException(new ReplicationException(gop.rpc_error.errno))); + } + else if (gop.get_response().error != 0) { + promise.setFailure(new PException("rocksdb error: " + gop.get_response().error)); + } + else { + promise.setSuccess(null); + } + } + }, timeout); + return promise; + } + + @Override + public Future asyncSet(byte[] hashKey, byte[] sortKey, byte[] value, int timeout) { + return asyncSet(hashKey, sortKey, value, 0, timeout); + } + + private Future asyncMultiGet(byte[] hashKey, List sortKeys, + int maxFetchCount, int maxFetchSize, boolean noValue, int timeout) { + final DefaultPromise promise = table.newPromise(); + if (hashKey == null || hashKey.length == 0) { + promise.setFailure(new PException("Invalid parameter: hashKey should not be null or empty")); + return promise; + } + if (hashKey.length >= 0xFFFF) { + promise.setFailure(new PException("Invalid parameter: hashKey length should be less than UINT16_MAX")); + return promise; + } + + blob hashKeyBlob = new blob(hashKey); + List sortKeyBlobs = new ArrayList(); + Map setKeyMap = null; + + if (sortKeys != null && sortKeys.size() > 0) { + setKeyMap = new TreeMap(); + for (int i = 0; i < sortKeys.size(); i++) { + byte[] sortKey = sortKeys.get(i); + if (sortKey == null) { + promise.setFailure(new PException("Invalid parameter: sortKeys["+i+"] should not be null")); + return promise; + } + setKeyMap.put(ByteBuffer.wrap(sortKey), sortKey); + } + for (Map.Entry entry: setKeyMap.entrySet()) { + sortKeyBlobs.add(new blob(entry.getValue())); + } + } + + multi_get_request request = new multi_get_request( + hashKeyBlob, sortKeyBlobs, maxFetchCount, maxFetchSize, noValue, + null, null, true, false, filter_type.FT_NO_FILTER, null); + gpid gpid = table.getHashKeyGpid(request.hash_key.data); + rrdb_multi_get_operator op = new rrdb_multi_get_operator(gpid, table.getTableName(), request); + final Map finalSetKeyMap = setKeyMap; + + table.asyncOperate( + op, + new Table.ClientOPCallback() { + @Override + public void onCompletion(client_operator clientOP) { + rrdb_multi_get_operator gop = (rrdb_multi_get_operator) clientOP; + if (gop.rpc_error.errno != error_code.error_types.ERR_OK) { + promise.setFailure(new PException(new ReplicationException(gop.rpc_error.errno))); + } + else if (gop.get_response().error != 0 && gop.get_response().error != 7) { + // rocksdb::Status::kOk && rocksdb::Status::kIncomplete + promise.setFailure(new PException("rocksdb error: " + gop.get_response().error)); + } + else { + MultiGetResult result = new MultiGetResult(); + result.allFetched = (gop.get_response().error == 0); + result.values = new ArrayList>(gop.get_response().kvs.size()); + if (finalSetKeyMap == null) { + for (key_value kv : gop.get_response().kvs) { + result.values.add(new ImmutablePair(kv.key.data, kv.value.data)); + } + } + else { + for (key_value kv : gop.get_response().kvs) { + byte[] sortKey = finalSetKeyMap.get(ByteBuffer.wrap(kv.key.data)); + if (sortKey != null) { + result.values.add(new ImmutablePair(sortKey, kv.value.data)); + } + } + } + promise.setSuccess(result); + } + } + }, timeout); + return promise; + } + + @Override + public Future asyncMultiGet(byte[] hashKey, List sortKeys, + int maxFetchCount, int maxFetchSize, int timeout) { + return asyncMultiGet(hashKey, sortKeys, maxFetchCount, maxFetchSize, false, timeout); + } + + @Override + public Future asyncMultiGet(byte[] hashKey, List sortKeys, int timeout) { + return asyncMultiGet(hashKey, sortKeys, 100, 1000000, false, timeout); + } + + @Override + public Future asyncMultiGet(byte[] hashKey, byte[] startSortKey, byte[] stopSortKey, + MultiGetOptions options, int maxFetchCount, int maxFetchSize, + int timeout/*ms*/) { + final DefaultPromise promise = table.newPromise(); + if (hashKey == null || hashKey.length == 0) { + promise.setFailure(new PException("Invalid parameter: hashKey should not be null or empty")); + return promise; + } + if (hashKey.length >= 0xFFFF) { + promise.setFailure(new PException("Invalid parameter: hashKey length should be less than UINT16_MAX")); + return promise; + } + + blob hashKeyBlob = new blob(hashKey); + blob startSortKeyBlob = (startSortKey == null ? null : new blob(startSortKey)); + blob stopSortKeyBlob = (stopSortKey == null ? null : new blob(stopSortKey)); + blob sortKeyFilterPatternBlob = + (options.sortKeyFilterPattern == null ? null : new blob(options.sortKeyFilterPattern)); + + multi_get_request request = new multi_get_request( + hashKeyBlob, null, maxFetchCount, maxFetchSize, options.noValue, + startSortKeyBlob, stopSortKeyBlob, options.startInclusive, options.stopInclusive, + filter_type.findByValue(options.sortKeyFilterType.getValue()), sortKeyFilterPatternBlob); + gpid gpid = table.getHashKeyGpid(request.hash_key.data); + rrdb_multi_get_operator op = new rrdb_multi_get_operator(gpid, table.getTableName(), request); + + table.asyncOperate( + op, + new Table.ClientOPCallback() { + @Override + public void onCompletion(client_operator clientOP) { + rrdb_multi_get_operator gop = (rrdb_multi_get_operator) clientOP; + if (gop.rpc_error.errno != error_code.error_types.ERR_OK) { + promise.setFailure(new PException(new ReplicationException(gop.rpc_error.errno))); + } + else if (gop.get_response().error != 0 && gop.get_response().error != 7) { + // rocksdb::Status::kOk && rocksdb::Status::kIncomplete + promise.setFailure(new PException("rocksdb error: " + gop.get_response().error)); + } + else { + MultiGetResult result = new MultiGetResult(); + result.allFetched = (gop.get_response().error == 0); + result.values = new ArrayList>(gop.get_response().kvs.size()); + for (key_value kv : gop.get_response().kvs) { + result.values.add(new ImmutablePair(kv.key.data, kv.value.data)); + } + promise.setSuccess(result); + } + } + }, timeout); + return promise; + } + + @Override + public Future asyncMultiGet(byte[] hashKey, byte[] startSortKey, byte[] stopSortKey, + MultiGetOptions options, int timeout/*ms*/) { + return asyncMultiGet(hashKey, startSortKey, stopSortKey, options, 100, 1000000, timeout); + } + + @Override + public Future asyncMultiGetSortKeys(byte[] hashKey, + int maxFetchCount, int maxFetchSize, int timeout) { + final DefaultPromise promise = table.newPromise(); + asyncMultiGet(hashKey, null, maxFetchCount, maxFetchSize, true, timeout) + .addListener(new MultiGetListener() { + @Override + public void operationComplete(Future future) throws Exception { + if (future.isSuccess()) { + MultiGetResult result = future.getNow(); + MultiGetSortKeysResult sortkeyResult = new MultiGetSortKeysResult(); + sortkeyResult.allFetched = result.allFetched; + sortkeyResult.keys = new ArrayList(result.values.size()); + for (Pair kv: result.values) { + sortkeyResult.keys.add(kv.getLeft()); + } + + promise.setSuccess(sortkeyResult); + } + else { + promise.setFailure(future.cause()); + } + } + }); + + return promise; + } + + @Override + public Future asyncMultiGetSortKeys(byte[] hashKey, int timeout) { + return asyncMultiGetSortKeys(hashKey, 100, 1000000, timeout); + } + + @Override + public Future asyncMultiSet(byte[] hashKey, List> values, + int ttlSeconds, int timeout) { + final DefaultPromise promise = table.newPromise(); + if (hashKey == null || hashKey.length == 0) { + promise.setFailure(new PException("Invalid parameter: hashKey should not be null or empty")); + return promise; + } + if (hashKey.length >= 0xFFFF) { + promise.setFailure(new PException("Invalid parameter: hashKey length should be less than UINT16_MAX")); + return promise; + } + if (values == null || values.size() == 0) { + promise.setFailure(new PException("Invalid parameter: values should not be null or empty")); + return promise; + } + + blob hash_key_blob = new blob(hashKey); + List values_blob = new ArrayList(); + for (int i = 0; i < values.size(); i++) { + byte[] k = values.get(i).getKey(); + if (k == null) { + promise.setFailure(new PException("Invalid parameter: values["+i+"].key should not be null")); + return promise; + } + byte[] v = values.get(i).getValue(); + if (v == null) { + promise.setFailure(new PException("Invalid parameter: values["+i+"].value should not be null")); + return promise; + } + values_blob.add(new key_value(new blob(k), new blob(v))); + } + int expireTsSseconds = (ttlSeconds == 0 ? 0 : ttlSeconds + (int)tools.epoch_now()); + multi_put_request request = new multi_put_request(hash_key_blob, values_blob, expireTsSseconds); + + gpid gpid = table.getHashKeyGpid(hashKey); + rrdb_multi_put_operator op = new rrdb_multi_put_operator(gpid, table.getTableName(), request); + + table.asyncOperate(op, new Table.ClientOPCallback() { + @Override + public void onCompletion(client_operator clientOP) { + rrdb_multi_put_operator op2 = (rrdb_multi_put_operator) clientOP; + if (op2.rpc_error.errno != error_code.error_types.ERR_OK) { + promise.setFailure(new PException(new ReplicationException(op2.rpc_error.errno))); + } + else if (op2.get_response().error != 0) { + promise.setFailure(new PException("rocksdb error: " + op2.get_response().error)); + } + else { + promise.setSuccess(null); + } + } + }, timeout); + return promise; + } + + @Override + public Future asyncMultiSet(byte[] hashKey, List> values, int timeout) { + return asyncMultiSet(hashKey, values, 0, timeout); + } + + @Override + public Future asyncDel(byte[] hashKey, byte[] sortKey, int timeout) { + final DefaultPromise promise = table.newPromise(); + blob request = new blob(PegasusClient.generateKey(hashKey, sortKey)); + gpid gpid = table.getGpid(request.data); + rrdb_remove_operator op = new rrdb_remove_operator(gpid, table.getTableName(), request); + + table.asyncOperate(op, new Table.ClientOPCallback() { + @Override + public void onCompletion(client_operator clientOP) { + rrdb_remove_operator op2 = (rrdb_remove_operator) clientOP; + if (op2.rpc_error.errno != error_code.error_types.ERR_OK) { + promise.setFailure(new PException(new ReplicationException(op2.rpc_error.errno))); + } + else if (op2.get_response().error != 0) { + promise.setFailure(new PException("rocksdb error: " + op2.get_response().error)); + } + else { + promise.setSuccess(null); + } + } + }, timeout); + return promise; + } + + @Override + public Future asyncMultiDel(byte[] hashKey, final List sortKeys, int timeout) { + final DefaultPromise promise = table.newPromise(); + if (hashKey == null || hashKey.length == 0) { + promise.setFailure(new PException("Invalid parameter: hashKey should not be null or empty")); + return promise; + } + if (hashKey.length >= 0xFFFF) { + promise.setFailure(new PException("Invalid parameter: hashKey length should be less than UINT16_MAX")); + return promise; + } + if (sortKeys == null || sortKeys.isEmpty()) { + promise.setFailure(new PException("Invalid parameter: sortKeys size should be at lease 1")); + return promise; + } + + List sortKeyBlobs = new ArrayList(sortKeys.size()); + for (int i = 0; i < sortKeys.size(); i++) { + byte[] sortKey = sortKeys.get(i); + if (sortKey == null) { + promise.setFailure(new PException("Invalid parameter: sortKeys["+i+"] should not be null")); + return promise; + } + sortKeyBlobs.add(new blob(sortKey)); + } + multi_remove_request request = new multi_remove_request( + new blob(hashKey), + sortKeyBlobs, + 100 + ); + + gpid pid = table.getHashKeyGpid(hashKey); + rrdb_multi_remove_operator op = new rrdb_multi_remove_operator(pid, table.getTableName(), request); + + table.asyncOperate( + op, + new Table.ClientOPCallback() { + public void onCompletion(client_operator clientOP) { + rrdb_multi_remove_operator op2 = (rrdb_multi_remove_operator) clientOP; + if (op2.rpc_error.errno != error_code.error_types.ERR_OK) { + promise.setFailure(new PException(new ReplicationException(op2.rpc_error.errno))); + } + else if (op2.get_response().error != 0) { + promise.setFailure(new PException("rocksdb error: " + op2.get_response().error)); + } + else { + Validate.isTrue(op2.get_response().count == sortKeys.size()); + promise.setSuccess(null); + } + } + }, timeout); + return promise; + } + + @Override + public Future asyncTTL(byte[] hashKey, byte[] sortKey, int timeout) { + final DefaultPromise promise = table.newPromise(); + blob request = new blob(PegasusClient.generateKey(hashKey, sortKey)); + + gpid pid = table.getGpid(request.data); + rrdb_ttl_operator op = new rrdb_ttl_operator(pid, table.getTableName(), request); + + table.asyncOperate(op, new Table.ClientOPCallback() { + @Override + public void onCompletion(client_operator clientOP) { + rrdb_ttl_operator op2 = (rrdb_ttl_operator) clientOP; + if (op2.rpc_error.errno != error_code.error_types.ERR_OK) { + promise.setFailure(new PException(new ReplicationException(op2.rpc_error.errno))); + } + else if (op2.get_response().error != 0 && op2.get_response().error != 1) { + promise.setFailure(new PException("rocksdb error: " + op2.get_response().error)); + } + else { + promise.setSuccess( op2.get_response().error == 1 ? -2 : op2.get_response().ttl_seconds ); + } + } + }, timeout); + return promise; + } + + @Override + public boolean exist(byte[] hashKey, byte[] sortKey, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + return asyncExist(hashKey, sortKey, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public long sortKeyCount(byte[] hashKey, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + return asyncSortKeyCount(hashKey, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public byte[] get(byte[] hashKey, byte[] sortKey, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + return asyncGet(hashKey, sortKey, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public void batchGet(List> keys, List values, int timeout) throws PException { + if (keys == null || keys.size() == 0) { + throw new PException("Invalid parameter: keys should not be null or empty"); + } + if (values == null) { + throw new PException("Invalid parameter: values should not be null"); + } + values.clear(); + List> futures = new ArrayList>(); + for (Pair k : keys) { + values.add(null); + futures.add(asyncGet(k.getLeft(), k.getRight(), timeout)); + } + for (int i = 0; i < keys.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (fu.isSuccess()) { + values.set(i, fu.getNow()); + } else { + Throwable cause = fu.cause(); + throw new PException("Get value of keys[" + i + "] failed: " + cause.getMessage(), cause); + } + } + } + + @Override + public int batchGet2(List> keys, + List> results, int timeout) throws PException { + if (keys == null || keys.size() == 0) { + throw new PException("Invalid parameter: keys should not be null or empty"); + } + if (results == null) { + throw new PException("Invalid parameter: results should not be null"); + } + results.clear(); + List> futures = new ArrayList>(); + for (Pair k : keys) { + futures.add(asyncGet(k.getLeft(), k.getRight(), timeout)); + } + int count = 0; + PException nullEx = null; + byte[] nullBytes = null; + for (int i = 0; i < keys.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (fu.isSuccess()) { + results.add(Pair.of(nullEx, fu.getNow())); + count++; + } else { + Throwable cause = fu.cause(); + results.add(Pair.of( + new PException("Get value of keys[" + i + "] failed: " + cause.getMessage(), cause), + nullBytes + )); + } + } + return count; + } + + @Override + public MultiGetResult multiGet(byte[] hashKey, List sortKeys, + int maxFetchCount, int maxFetchSize, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + return asyncMultiGet(hashKey, sortKeys, maxFetchCount, maxFetchSize, timeout) + .get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public MultiGetResult multiGet(byte[] hashKey, List sortKeys, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + return asyncMultiGet(hashKey, sortKeys, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public MultiGetResult multiGet(byte[] hashKey, byte[] startSortKey, byte[] stopSortKey, + MultiGetOptions options, int maxFetchCount, int maxFetchSize, + int timeout/*ms*/) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + return asyncMultiGet(hashKey, startSortKey, stopSortKey, options, + maxFetchCount, maxFetchSize, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public MultiGetResult multiGet(byte[] hashKey, byte[] startSortKey, byte[] stopSortKey, + MultiGetOptions options, int timeout/*ms*/) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + return asyncMultiGet(hashKey, startSortKey, stopSortKey, options, + timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public void batchMultiGet(List>> keys, + List values, int timeout) throws PException { + if (keys == null || keys.size() == 0) { + throw new PException("Invalid parameter: keys should not be null or empty"); + } + if (values == null) { + throw new PException("Invalid parameter: values should not be null"); + } + values.clear(); + List> futures = new ArrayList>(); + for (Pair> k : keys) { + values.add(null); + futures.add(asyncMultiGet(k.getLeft(), k.getRight(), timeout)); + } + for (int i = 0; i < keys.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (fu.isSuccess()) { + values.set(i, new HashKeyData(keys.get(i).getLeft(), fu.getNow().values)); + } else { + Throwable cause = fu.cause(); + throw new PException("MultiGet values of keys[" + i + "] failed: " + cause.getMessage(), cause); + } + } + } + + @Override + public int batchMultiGet2(List>> keys, + List> results, int timeout) throws PException { + if (keys == null || keys.size() == 0) { + throw new PException("Invalid parameter: keys should not be null or empty"); + } + if (results == null) { + throw new PException("Invalid parameter: results should not be null"); + } + results.clear(); + List> futures = new ArrayList>(); + for (Pair> k : keys) { + futures.add(asyncMultiGet(k.getLeft(), k.getRight(), timeout)); + } + int count = 0; + PException nullEx = null; + HashKeyData nullData = null; + for (int i = 0; i < keys.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (fu.isSuccess()) { + results.add(Pair.of( + nullEx, + new HashKeyData(keys.get(i).getLeft(), fu.getNow().values) + )); + count++; + } else { + Throwable cause = fu.cause(); + results.add(Pair.of( + new PException("MultiGet value of keys[" + i + "] failed: " + cause.getMessage(), cause), + nullData + )); + } + } + return count; + } + + @Override + public MultiGetSortKeysResult multiGetSortKeys(byte[] hashKey, int maxFetchCount, int maxFetchSize, + int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + return asyncMultiGetSortKeys(hashKey, maxFetchCount, maxFetchSize, timeout) + .get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public MultiGetSortKeysResult multiGetSortKeys(byte[] hashKey, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + return asyncMultiGetSortKeys(hashKey, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public void set(byte[] hashKey, byte[] sortKey, byte[] value, int ttlSeconds, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + asyncSet(hashKey, sortKey, value, ttlSeconds, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public void set(byte[] hashKey, byte[] sortKey, byte[] value, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + asyncSet(hashKey, sortKey, value, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public void batchSet(List items, int timeout) throws PException { + if (items == null) { + throw new PException("Invalid parameter: items should not be null"); + } + List> futures = new ArrayList>(); + for (SetItem i : items) { + futures.add(asyncSet(i.hashKey, i.sortKey, i.value, i.ttlSeconds, timeout)); + } + for (int i = 0; i < items.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (!fu.isSuccess()) { + Throwable cause = fu.cause(); + throw new PException("Set value of items[" + i + "] failed: " + cause.getMessage(), cause); + } + } + } + + @Override + public int batchSet2(List items, List results, int timeout) throws PException { + if (items == null) { + throw new PException("Invalid parameter: items should not be null"); + } + if (results == null) { + throw new PException("Invalid parameter: results should not be null"); + } + results.clear(); + List> futures = new ArrayList>(); + for (SetItem i : items) { + futures.add(asyncSet(i.hashKey, i.sortKey, i.value, i.ttlSeconds, timeout)); + } + int count = 0; + PException nullEx = null; + for (int i = 0; i < items.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (fu.isSuccess()) { + results.add(nullEx); + count++; + } else { + Throwable cause = fu.cause(); + results.add(new PException("Set value of items[" + i + "] failed: " + cause.getMessage(), cause)); + } + } + return count; + } + + @Override + public void multiSet(byte[] hashKey, List> values, + int ttlSeconds, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + asyncMultiSet(hashKey, values, ttlSeconds, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public void multiSet(byte[] hashKey, List> values, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + asyncMultiSet(hashKey, values, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public void batchMultiSet(List items, int ttl_seconds, int timeout) throws PException { + if (items == null || items.size() == 0) { + throw new PException("Invalid parameter: items should not be null or empty"); + } + List> futures = new ArrayList>(); + for (HashKeyData item : items) { + futures.add(asyncMultiSet(item.hashKey, item.values, ttl_seconds, timeout)); + } + for (int i = 0; i < items.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (!fu.isSuccess()) { + Throwable cause = fu.cause(); + throw new PException("MultiSet values of items[" + i + "] failed: " + cause.getMessage(), cause); + } + } + } + + @Override + public int batchMultiSet2(List items, + int ttl_seconds, List results, int timeout) throws PException { + if (items == null) { + throw new PException("Invalid parameter: items should not be null"); + } + if (results == null) { + throw new PException("Invalid parameter: results should not be null"); + } + results.clear(); + List> futures = new ArrayList>(); + for (HashKeyData item : items) { + futures.add(asyncMultiSet(item.hashKey, item.values, ttl_seconds, timeout)); + } + int count = 0; + PException nullEx = null; + for (int i = 0; i < items.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (fu.isSuccess()) { + results.add(nullEx); + count++; + } else { + Throwable cause = fu.cause(); + results.add(new PException("MultiSet value of items[" + i + "] failed: " + cause.getMessage(), cause)); + } + } + return count; + + } + + @Override + public void del(byte[] hashKey, byte[] sortKey, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + asyncDel(hashKey, sortKey, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public void batchDel(List> keys, int timeout) throws PException { + if (keys == null || keys.size() == 0) { + throw new PException("Invalid parameter: keys should not be null or empty"); + } + List> futures = new ArrayList>(); + for (Pair k : keys) { + futures.add(asyncDel(k.getLeft(), k.getRight(), timeout)); + } + for (int i = 0; i < keys.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (!fu.isSuccess()) { + Throwable cause = fu.cause(); + throw new PException("Del value of keys[" + i + "] failed: " + cause.getMessage(), cause); + } + } + } + + @Override + public int batchDel2(List> keys, + List results, int timeout) throws PException { + if (keys == null) { + throw new PException("Invalid parameter: keys should not be null"); + } + if (results == null) { + throw new PException("Invalid parameter: results should not be null"); + } + results.clear(); + List> futures = new ArrayList>(); + for (Pair k : keys) { + futures.add(asyncDel(k.getLeft(), k.getRight(), timeout)); + } + int count = 0; + PException nullEx = null; + for (int i = 0; i < keys.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (fu.isSuccess()) { + results.add(nullEx); + count++; + } else { + Throwable cause = fu.cause(); + results.add(new PException("Del value of keys[" + i + "] failed: " + cause.getMessage(), cause)); + } + } + return count; + } + + @Override + public void multiDel(byte[] hashKey, List sortKeys, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + asyncMultiDel(hashKey, sortKeys, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public void batchMultiDel(List>> keys, int timeout) throws PException { + if (keys == null || keys.size() == 0) { + throw new PException("Invalid parameter: keys should not be null or empty"); + } + List> futures = new ArrayList>(); + for (Pair> k : keys) { + futures.add(asyncMultiDel(k.getLeft(), k.getRight(), timeout)); + } + for (int i = 0; i < keys.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (!fu.isSuccess()) { + Throwable cause = fu.cause(); + throw new PException("MultiDel values of keys[" + i + "] failed: " + cause.getMessage(), cause); + } + } + } + + @Override + public int batchMultiDel2(List>> keys, + List results, int timeout) throws PException { + if (keys == null) { + throw new PException("Invalid parameter: keys should not be null"); + } + if (results == null) { + throw new PException("Invalid parameter: results should not be null"); + } + results.clear(); + List> futures = new ArrayList>(); + for (Pair> k : keys) { + futures.add(asyncMultiDel(k.getLeft(), k.getRight(), timeout)); + } + int count = 0; + PException nullEx = null; + for (int i = 0; i < keys.size(); i++) { + Future fu = futures.get(i); + fu.awaitUninterruptibly(); + if (fu.isSuccess()) { + results.add(nullEx); + count++; + } else { + Throwable cause = fu.cause(); + results.add(new PException("MultiDel value of keys[" + i + "] failed: " + cause.getMessage(), cause)); + } + } + return count; + } + + @Override + public int ttl(byte[] hashKey, byte[] sortKey, int timeout) throws PException { + if (timeout <= 0) + timeout = defaultTimeout; + try { + return asyncTTL(hashKey, sortKey, timeout).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (TimeoutException e) { + throw new PException(new ReplicationException(error_code.error_types.ERR_TIMEOUT)); + } catch (ExecutionException e) { + throw new PException(e); + } + } + + @Override + public PegasusScannerInterface getScanner(byte[] hashKey, byte[] startSortKey, byte[] stopSortKey, + ScanOptions options) throws PException { + if (hashKey == null || hashKey.length == 0) { + throw new PException("Invalid parameter: hash key can't be empty"); + } + if (options.timeoutMillis <= 0) { + options.timeoutMillis = defaultTimeout; + } + + ScanOptions o = new ScanOptions(options); + + // generate key range by start_sort_key and stop_sort_key + byte[] start = PegasusClient.generateKey(hashKey, startSortKey); + byte[] stop; + if (stopSortKey == null || stopSortKey.length == 0) { + stop = PegasusClient.generateNextBytes(hashKey); + o.stopInclusive = false; + } else { + stop = PegasusClient.generateKey(hashKey, stopSortKey); + } + + // limit key range by prefix filter + if (o.sortKeyFilterType == FilterType.FT_MATCH_PREFIX + && o.sortKeyFilterPattern != null && o.sortKeyFilterPattern.length > 0) { + byte[] prefix_start = PegasusClient.generateKey(hashKey, o.sortKeyFilterPattern); + if (PegasusClient.bytesCompare(prefix_start, start) > 0) { + start = prefix_start; + o.startInclusive = true; + } + byte[] prefix_stop = PegasusClient.generateNextBytes(hashKey, o.sortKeyFilterPattern); + if (PegasusClient.bytesCompare(prefix_stop, stop) <= 0) { + stop = prefix_stop; + o.stopInclusive = false; + } + } + + // check if range is empty + int cmp = PegasusClient.bytesCompare(start, stop); + gpid[] v = cmp < 0 || cmp == 0 && o.startInclusive && o.stopInclusive ? + // (start < stop) or (start == stop and bounds are inclusive) + new gpid[]{ table.getGpid(start) } : + new gpid[0]; + + return new PegasusScanner(table, v, o, new blob(start), new blob(stop)); + } + + @Override + public List getUnorderedScanners(int maxSplitCount, + ScanOptions options) throws PException { + if (maxSplitCount <= 0) { + throw new PException("Invalid parameter: the max count of splits must be greater than 0"); + } + if (options.timeoutMillis <= 0) { + options.timeoutMillis = defaultTimeout; + } + + gpid[] all = table.getAllGpid(); + int count = all.length; + int split = count < maxSplitCount ? count : maxSplitCount; + List ret = new ArrayList(split); + + int size = count / split; + int more = count - size * split; + + //use default value for other fields in scan_options + ScanOptions opt = new ScanOptions(); + opt.timeoutMillis = options.timeoutMillis; + opt.batchSize = options.batchSize; + opt.noValue = options.noValue; + opt.sortKeyFilterType = options.sortKeyFilterType; + opt.sortKeyFilterPattern = options.sortKeyFilterPattern; + for (int i = 0; i < split; i++) { + int s = i < more ? size + 1 : size; + gpid[] v = new gpid[s]; + for (int j = 0; j < s; j++) + v[j] = all[--count]; + ret.add(new PegasusScanner(table, v, opt)); + } + return ret; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/PegasusTableInterface.java b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusTableInterface.java new file mode 100644 index 00000000..884f8bd9 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/PegasusTableInterface.java @@ -0,0 +1,801 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; +import org.apache.commons.lang3.tuple.Pair; +import java.util.List; + +/** + * @author sunweijie + * + * This class provides sync and async interfaces to access data of a specified table. + * + * All the async interfaces use Future mode. Notice that it's {@link io.netty.util.concurrent.Future}, + * but not {@link java.util.concurrent.Future}. You can wait the future to complete in a synchronous + * manner, or add completion callback in an asynchronous way. + * + * A synchronous example: + * + * PegasusTableInterface table; + * .... + * Future future = table.asyncExist(hashKey, sortKey, 0); + * future.await(); + * if (future.isSuccess()) { + * Boolean result = future.getNow(); + * } + * else { + * future.cause().printStackTrace(); + * } + * + * + * An asynchronous example: + * + * PegasusTableInterface table; + * .... + * table.asyncExist(hashKey, sortKey, 0).addListener( + * new ExistListener() { + * public void operationComplete(Future future) throws Exception { + * if (future.isSuccess()) { + * Boolean result = future.getNow(); + * } + * else { + * future.cause().printStackTrace(); + * } + * } + * } + * ).await(); + * + * Attention: when the future await() returns, it is guaranteed that the result data is ready and you can + * fetch it by getNow(), but it is not guaranteed that the operationComplete() of listener is already executed, + * because the callback is dispatched to an internal thread, so it depends on thread scheduling. + * + * Please refer to the netty document for the usage of Future. + */ +public interface PegasusTableInterface { + + ///< -------- Exist -------- + + public static interface ExistListener extends GenericFutureListener> { + /** + * This function will be called when listened asyncExist future is done. + * @param future the listened future + * @throws Exception + * + * Notice: User shouldn't do any operations that may block or time-consuming + */ + @Override + public void operationComplete(Future future) throws Exception; + } + + /** + * Check value existence for a specific (hashKey, sortKey) pair of current table, async version + * @param hashKey used to decide which partition the key may exist + * if null or length==0, means no hash key. + * @param sortKey all keys under the same hashKey will be sorted by sortKey + * if null or length==0, means no sort key. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return A future for current op. + * + * Future return: + * On success: true if exist, false if not exist + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * The api is thread safe. + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncExist(byte[] hashKey, byte[] sortKey, int timeout/*ms*/); + + ///< -------- SortKeyCount -------- + + public static interface SortKeyCountListener extends GenericFutureListener> { + /** + * This function will be called when listened asyncSortKeyCount future is done. + * @param future the listened future + * @throws Exception + * + * Notice: User shouldn't do any operations that may block or time-consuming + */ + @Override + public void operationComplete(Future future) throws Exception; + } + + /** + * Count the sortkeys for a specific hashKey, async version + * @param hashKey used to decide which partition the key may exist + * should not be null or empty + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return the future for current op + * + * Future return: + * On success: the count result for the hashKey + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * The api is thread safe. + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncSortKeyCount(byte[] hashKey, int timeout/*ms*/); + + ///< -------- Get -------- + + public static interface GetListener extends GenericFutureListener> { + /** + * This function will be called when listened asyncGet future is done. + * @param future the listened future + * @throws Exception + * + * Notice: User shouldn't do any operations that may block or time-consuming + */ + @Override + public void operationComplete(Future future) throws Exception; + } + + /** + * Get value for a specific (hashKey, sortKey) pair, async version + * @param hashKey used to decide which partition the key may exist + * if null or empty, means no hash key. + * @param sortKey all keys under the same hashKey will be sorted by sortKey + * if null or empty, means no sort key + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return the future for current op + * + * Future return: + * On success: the got value + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * The api is thread safe. + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncGet(byte[] hashKey, byte[] sortKey, int timeout/*ms*/); + + ///< -------- MultiGet -------- + + public static class MultiGetResult { + /** + * return value for multiGet + * @param allFetched true if all data on the server are fetched; false if only partial data are fetched. + * @param values the got values. If sortKey in the input sortKeys is not found, it won't be in values. + * The output values are ordered by the sortKey. + */ + public boolean allFetched; + public List> values; + } + + public static interface MultiGetListener extends GenericFutureListener> { + /** + * This function will be called when listened asyncMultiGet future is done. + * @param future the listened future + * @throws Exception + * + * Notice: User shouldn't do any operations that may block or time-consuming + */ + @Override + public void operationComplete(Future future) throws Exception; + } + + /** + * get multiple key-values under the same hashKey, async version + * @param hashKey used to decide which partition the key may exist + * should not be null or empty. + * @param sortKeys try to get values of sortKeys under the hashKey + * if null or empty, try to get all (sortKey,value) pairs under hashKey + * @param maxFetchCount max count of kv pairs to be fetched + * maxFetchCount <= 0 means no limit. default value is 100 + * @param maxFetchSize max size of kv pairs to be fetched. + * maxFetchSize <= 0 means no limit. default value is 1000000. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return the future for current op + * + * Future return: + * On success: An object of type MultiGetResult + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncMultiGet(byte[] hashKey, List sortKeys, + int maxFetchCount, int maxFetchSize, int timeout/*ms*/); + public Future asyncMultiGet(byte[] hashKey, List sortKeys, int timeout/*ms*/); + + /** + * get multiple key-values under the same hashKey with sortKey range limited, async version + * @param hashKey used to decide which partition the key may exist + * should not be null or empty. + * @param startSortKey the start sort key. + * null means "". + * @param stopSortKey the stop sort key. + * null or "" means fetch to the last sort key. + * @param options multi-get options. + * @param maxFetchCount max count of kv pairs to be fetched + * maxFetchCount <= 0 means no limit. default value is 100 + * @param maxFetchSize max size of kv pairs to be fetched. + * maxFetchSize <= 0 means no limit. default value is 1000000. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return the future for current op + * + * Future return: + * On success: An object of type MultiGetResult + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncMultiGet(byte[] hashKey, byte[] startSortKey, byte[] stopSortKey, + MultiGetOptions options, int maxFetchCount, int maxFetchSize, + int timeout/*ms*/); + public Future asyncMultiGet(byte[] hashKey, byte[] startSortKey, byte[] stopSortKey, + MultiGetOptions options, int timeout/*ms*/); + + ///< -------- MultiGetSortKeys -------- + + public static class MultiGetSortKeysResult { + /** + * return value for multiGetSortkeys + * @param allFetched true if all data on the server are fetched; false if only partial data are fetched. + * @param keys the got keys. + * The output keys are in order. + */ + public boolean allFetched; + public List keys; + }; + + public static interface MultiGetSortKeysListener extends GenericFutureListener> { + /** + * This function will be called when listened asyncMultiGetSortKeys future is done. + * @param future the listened future + * @throws Exception + * + * Notice: User shouldn't do any operations that may block or time-consuming + */ + @Override + public void operationComplete(Future future) throws Exception; + } + + /** + * get all the sortKeys for the same hashKey + * @param hashKey used to decide which partition the key may exist + * should not be null or empty. + * @param maxFetchCount max count of kv pairs to be fetched + * maxFetchCount <= 0 means no limit. default value is 100 + * @param maxFetchSize max size of kv pairs to be fetched. + * maxFetchSize <= 0 means no limit. default value is 1000000. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return the future for current op + * + * Future return: + * On success: An object of type MultiGetSortKeysResult + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncMultiGetSortKeys(byte[] hashKey, int maxFetchCount, int maxFetchSize, + int timeout/*ms*/); + public Future asyncMultiGetSortKeys(byte[] hashKey, int timeout/*ms*/); + + ///< -------- Set -------- + + public static interface SetListener extends GenericFutureListener> { + /** + * This function will be called when listened asyncSet future is done. + * @param future the listened future + * @throws Exception + * + * Notice: User shouldn't do any operations that may block or time-consuming + */ + @Override + public void operationComplete(Future future) throws Exception; + } + + /** + * Set value for a specific (hashKey, sortKey) pair, async version + * @param hashKey used to decide which partition the key may exist + * if null or empty, means no hash key. + * @param sortKey all keys under the same hashKey will be sorted by sortKey + * if null or empty, means no sort key + * @param value should not be null + * @param ttlSeconds time to live in seconds + * 0 means no ttl, default value is 0 + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return the future for current op + * + * Future return: + * On success: no return + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * The api is thread safe. + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncSet(byte[] hashKey, byte[] sortKey, byte[] value, int ttlSeconds, int timeout/*ms*/); + public Future asyncSet(byte[] hashKey, byte[] sortKey, byte[] value, int timeout/*ms*/); + + ///< -------- MultiGet -------- + + public static interface MultiSetListener extends GenericFutureListener> { + /** + * This function will be called when listened asyncMultiSet future is done. + * @param future the listened future + * @throws Exception + * + * Notice: User shouldn't do any operations that may block or time-consuming + */ + @Override + public void operationComplete(Future future) throws Exception; + } + + /** + * Set key-values for a specific hashKey, async version + * @param hashKey used to decide which partition the key may exist + * if null or empty, means no hash key. + * @param values all (sortKey, value) pairs + * should not be null or empty + * @param ttlSeconds time to live in seconds + * 0 means no ttl, default value is 0 + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return the future for current op + * + * Future return: + * On success: no return + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncMultiSet(byte[] hashKey, List> values, + int ttlSeconds, int timeout/*ms*/); + public Future asyncMultiSet(byte[] hashKey, List> values, int timeout/*ms*/); + + ///< -------- Del -------- + + public static interface DelListener extends GenericFutureListener> { + /** + * This function will be called when listened asyncDel future is done. + * @param future the listened future + * @throws Exception + * + * Notice: User shouldn't do any operations that may block or time-consuming + */ + @Override + public void operationComplete(Future future) throws Exception; + } + + /** + * delete value for a specific (hashKey, sortKey) pair, async version + * @param hashKey used to decide which partition the key may exist + * if null or empty, means no hash key. + * @param sortKey all keys under the same hashKey will be sorted by sortKey + * if null or empty, means no sort key + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return the future for current op + * + * Future return: + * On success: no return + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncDel(byte[] hashKey, byte[] sortKey, int timeout/*ms*/); + + ///< -------- MultiDel -------- + + public static interface MultiDelListener extends GenericFutureListener> { + /** + * This function will be called when listened asyncMultiDel future is done. + * @param future the listened future + * @throws Exception + * + * Notice: User shouldn't do any operations that may block or time-consuming + */ + @Override + public void operationComplete(Future future) throws Exception; + } + + /** + * delete mutiple values for a specific hashKey, async version + * @param hashKey used to decide which partition the key may exist + * if null or empty, means no hash key. + * @param sortKeys all the sortKeys need to be deleted + * should not be null or empty + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return the future for current op + * + * Future return: + * On success: no return + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncMultiDel(byte[] hashKey, List sortKeys, int timeout/*ms*/); + + ///< -------- TTL -------- + + public static interface TTLListener extends GenericFutureListener> { + /** + * This function will be called when listened asyncTTL future is done. + * @param future the listened future + * @throws Exception + * + * Notice: User shouldn't do any operations that may block or time-consuming + */ + @Override + public void operationComplete(Future future) throws Exception; + } + + /** + * get TTL value for a specific (hashKey, sortKey) pair, async version + * @param hashKey used to decide which partition the key may exist + * if null or empty, means no hash key. + * @param sortKey all keys under the same hashKey will be sorted by sortKey + * if null or empty, means no sort key + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * + * @return the future for current op + * + * Future return: + * On success: ttl time in seconds; -1 if no ttl set; -2 if not exist. + * On failure: a throwable, which is an instance of PException + * + * Thread safety: + * All the listeners for the same table are guaranteed to be dispatched in the same thread, so all the + * listeners for the same future are guaranteed to be executed as the same order as the listeners added. + * But listeners for different tables are not guaranteed to be dispatched in the same thread. + */ + public Future asyncTTL(byte[] hashKey, byte[] sortKey, int timeout/*ms*/); + + ///< -------- Sync Methods -------- + + /** + * sync version of Exist, please refer to the async version {@link #asyncExist(byte[], byte[], int)} + */ + public boolean exist(byte[] hashKey, byte[] sortKey, int timeout/*ms*/) throws PException; + + /** + * sync version of SortKeyCount, please refer to the async version {@link #asyncSortKeyCount(byte[], int)} + */ + public long sortKeyCount(byte[] hashKey, int timeout/*ms*/) throws PException; + + /** + * sync version of Get, please refer to the async version {@link #asyncGet(byte[], byte[], int)} + */ + public byte[] get(byte[] hashKey, byte[] sortKey, int timeout/*ms*/) throws PException; + + /** + * Batch get values of different keys. + * Will terminate immediately if any error occurs. + * @param keys hashKey and sortKey pair list. + * @param values output values; should be created by caller; if succeed, the size of values will + * be same with keys; the value of keys[i] is stored in values[i]; if the value of + * keys[i] is not found, then values[i] will be set to null. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchGet(List> keys, List values, int timeout/*ms*/) throws PException; + + /** + * Batch get values of different keys. + * Will wait for all requests done even if some error occurs. + * @param keys hashKey and sortKey pair list. + * @param results output results; should be created by caller; after call done, the size of results will + * be same with keys; the results[i] is a Pair: + * - if Pair.left != null : means query keys[i] failed, Pair.left is the exception. + * - if Pair.left == null : means query keys[i] succeed, Pair.right is the result value. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchGet2(List> keys, + List> results, int timeout/*ms*/) throws PException; + + /** + * sync version of MultiGet, please refer to the async version {@link #asyncMultiGet(byte[], List, int, int, int)} + * and {@link #asyncMultiGet(byte[], List, int)} + */ + public MultiGetResult multiGet(byte[] hashKey, List sortKeys, + int maxFetchCount, int maxFetchSize, int timeout/*ms*/) throws PException; + public MultiGetResult multiGet(byte[] hashKey, List sortKeys, int timeout/*ms*/) throws PException; + + /** + * sync version of MultiGet, please refer to the async version + * {@link #asyncMultiGet(byte[], byte[], byte[], MultiGetOptions, int, int, int)} + * and {@link #asyncMultiGet(byte[], byte[], byte[], MultiGetOptions, int)} + */ + public MultiGetResult multiGet(byte[] hashKey, byte[] startSortKey, byte[] stopSortKey, + MultiGetOptions options, int maxFetchCount, int maxFetchSize, + int timeout/*ms*/) throws PException; + public MultiGetResult multiGet(byte[] hashKey, byte[] startSortKey, byte[] stopSortKey, + MultiGetOptions options, int timeout/*ms*/) throws PException; + + /** + * Batch get multiple values under the same hash key. + * Will terminate immediately if any error occurs. + * @param keys List{hashKey,List{sortKey}} + * @param values output values; should be created by caller; if succeed, the size of values will + * be same with keys; the data for keys[i] is stored in values[i]. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchMultiGet(List>> keys, + List values, int timeout/*ms*/) throws PException; + + /** + * Batch get multiple values under the same hash key. + * Will wait for all requests done even if some error occurs. + * @param keys List{hashKey,List{sortKey}}; if List{sortKey} is null or empty, means fetch all + * sortKeys under the hashKey. + * @param results output results; should be created by caller; after call done, the size of results will + * be same with keys; the results[i] is a Pair: + * - if Pair.left != null : means query keys[i] failed, Pair.left is the exception. + * - if Pair.left == null : means query keys[i] succeed, Pair.right is the result value. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchMultiGet2(List>> keys, + List> results, int timeout/*ms*/) throws PException; + + /** + * sync version of MultiGetSortKeys, please refer to the async version + * {@link #asyncMultiGetSortKeys(byte[], int, int, int)} and {@link #asyncMultiGetSortKeys(byte[], int)} + */ + public MultiGetSortKeysResult multiGetSortKeys(byte[] hashKey, int maxFetchCount, int maxFetchSize, + int timeout/*ms*/) throws PException; + public MultiGetSortKeysResult multiGetSortKeys(byte[] hashKey, int timeout/*ms*/) throws PException; + + /** + * sync version of Set, please refer to the async version {@link #asyncSet(byte[], byte[], byte[], int, int)} + * and {@link #asyncSet(byte[], byte[], byte[], int)} + */ + public void set(byte[] hashKey, byte[] sortKey, byte[] value, int ttlSeconds, int timeout/*ms*/) throws PException; + public void set(byte[] hashKey, byte[] sortKey, byte[] value, int timeout/*ms*/) throws PException; + + /** + * Batch set lots of values. + * Will terminate immediately if any error occurs. + * @param items list of items. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchSet(List items, int timeout/*ms*/) throws PException; + + /** + * Batch set lots of values. + * Will wait for all requests done even if some error occurs. + * @param items list of items. + * @param results output results; should be created by caller; after call done, the size of results will + * be same with items; the results[i] is a PException: + * - if results[i] != null : means set items[i] failed, results[i] is the exception. + * - if results[i] == null : means set items[i] succeed. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchSet2(List items, List results, int timeout/*ms*/) throws PException; + + /** + * sync version of MultiSet, please refer to the async version {@link #asyncMultiSet(byte[], List, int, int)} + * and {@link #asyncMultiSet(byte[], List, int)} + */ + public void multiSet(byte[] hashKey, List> values, + int ttlSeconds, int timeout/*ms*/) throws PException; + public void multiSet(byte[] hashKey, List> values, + int timeout/*ms*/) throws PException; + + /** + * Batch set multiple value under the same hash key. + * Will terminate immediately if any error occurs. + * @param items list of items. + * @param ttl_seconds time to live in seconds, 0 means no ttl. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchMultiSet(List items, int ttl_seconds, int timeout/*ms*/) throws PException; + + /** + * Batch set multiple value under the same hash key. + * Will wait for all requests done even if some error occurs. + * @param items list of items. + * @param ttl_seconds time to live in seconds, + * 0 means no ttl. default value is 0. + * @param results output results; should be created by caller; after call done, the size of results will + * be same with items; the results[i] is a PException: + * - if results[i] != null : means set items[i] failed, results[i] is the exception. + * - if results[i] == null : means set items[i] succeed. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchMultiSet2(List items, + int ttl_seconds, List results, int timeout/*ms*/) throws PException; + + /** + * sync version of Del, please refer to the async version {@link #asyncDel(byte[], byte[], int)} + */ + public void del(byte[] hashKey, byte[] sortKey, int timeout/*ms*/) throws PException; + + /** + * Batch delete values of different keys. + * Will terminate immediately if any error occurs. + * @param keys hashKey and sortKey pair list. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchDel(List> keys, int timeout/*ms*/) throws PException; + + /** + * Batch delete values of different keys. + * Will wait for all requests done even if some error occurs. + * @param keys hashKey and sortKey pair list. + * @param results output results; should be created by caller; after call done, the size of results will + * be same with keys; the results[i] is a PException: + * - if results[i] != null : means del keys[i] failed, results[i] is the exception. + * - if results[i] == null : means del keys[i] succeed. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchDel2(List> keys, + List results, int timeout/*ms*/) throws PException; + + /** + * sync version of MultiDel, please refer to the async version {@link #asyncMultiDel(byte[], List, int)} + */ + public void multiDel(byte[] hashKey, List sortKeys, int timeout/*ms*/) throws PException; + + /** + * Batch delete specified sort keys under the same hash key. + * Will terminate immediately if any error occurs. + * @param keys List{hashKey,List{sortKey}} + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @throws PException throws exception if any error occurs. + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public void batchMultiDel(List>> keys, int timeout/*ms*/) throws PException; + + /** + * Batch delete specified sort keys under the same hash key. + * Will wait for all requests done even if some error occurs. + * @param keys List{hashKey,List{sortKey}} + * @param results output results; should be created by caller; after call done, the size of results will + * be same with keys; the results[i] is a PException: + * - if results[i] != null : means del keys[i] failed, results[i] is the exception. + * - if results[i] == null : means del keys[i] succeed. + * @param timeout how long will the operation timeout in milliseconds. + * if timeout > 0, it is a timeout value for current op, + * else the timeout value in the configuration file will be used. + * @return succeed count. + * @throws PException + * + * Notice: the method is not atomic, that means, maybe some keys succeed but some keys failed. + */ + public int batchMultiDel2(List>> keys, + List results, int timeout/*ms*/) throws PException; + + /** + * sync version of TTL, please refer to the async version {@link #asyncTTL(byte[], byte[], int)} + */ + public int ttl(byte[] hashKey, byte[] sortKey, int timeout/*ms*/) throws PException; + + /** + * Get Scanner for {startSortKey, stopSortKey} within hashKey + * @param hashKey used to decide which partition to put this k-v, + * @param startSortKey start sort key scan from + * if null or length == 0, means start from begin + * @param stopSortKey stop sort key scan to + * if null or length == 0, means stop to end + * @param options scan options like endpoint inclusive/exclusive + * @return scanner + * @throws PException + */ + public PegasusScannerInterface getScanner(byte[] hashKey, byte[] startSortKey, byte[] stopSortKey, + ScanOptions options) throws PException; + + /** + * Get Scanners for all data in database + * @param maxSplitCount how many scanner expected + * @param options scan options like batchSize + * @return scanners, count of which would be no more than maxSplitCount + * @throws PException + */ + public List getUnorderedScanners(int maxSplitCount, + ScanOptions options) throws PException; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/ScanOptions.java b/src/main/java/com/xiaomi/infra/pegasus/client/ScanOptions.java new file mode 100644 index 00000000..2a8dd8ee --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/ScanOptions.java @@ -0,0 +1,37 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +/** + * @author shenyuannan + * + * Scan options. + */ +public class ScanOptions { + public int timeoutMillis = 5000; // operation timeout in milli-seconds. + // if timeoutMillis > 0, it is a timeout value for current op, + // else the timeout value in the configuration file will be used. + public int batchSize = 1000; // internal buffer batch size + public boolean startInclusive = true; // if the startSortKey is included + public boolean stopInclusive = false; // if the stopSortKey is included + public FilterType hashKeyFilterType = FilterType.FT_NO_FILTER; // filter type for hash key + public byte[] hashKeyFilterPattern = null; // filter pattern for hash key + public FilterType sortKeyFilterType = FilterType.FT_NO_FILTER; // filter type for sort key + public byte[] sortKeyFilterPattern = null; // filter pattern for sort key + public boolean noValue = false; // only fetch hash_key and sort_key, but not fetch value + + public ScanOptions() {} + + public ScanOptions(ScanOptions o) { + timeoutMillis = o.timeoutMillis; + batchSize = o.batchSize; + startInclusive = o.startInclusive; + stopInclusive = o.stopInclusive; + hashKeyFilterType = o.hashKeyFilterType; + hashKeyFilterPattern = o.hashKeyFilterPattern; + sortKeyFilterType = o.sortKeyFilterType; + sortKeyFilterPattern = o.sortKeyFilterPattern; + noValue = o.noValue; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/client/SetItem.java b/src/main/java/com/xiaomi/infra/pegasus/client/SetItem.java new file mode 100644 index 00000000..2ea85982 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/client/SetItem.java @@ -0,0 +1,32 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +/** + * @author qinzuoyan + * + * Set item. + */ +public class SetItem{ + public byte[] hashKey = null; + public byte[] sortKey = null; + public byte[] value = null; + public int ttlSeconds = 0; // 0 means no ttl + + public SetItem() {} + + public SetItem(byte[] hashKey, byte[] sortKey, byte[] value, int ttlSeconds) { + this.hashKey = hashKey; + this.sortKey = sortKey; + this.value = value; + this.ttlSeconds = ttlSeconds; + } + + public SetItem(byte[] hashKey, byte[] sortKey, byte[] value) { + this.hashKey = hashKey; + this.sortKey = sortKey; + this.value = value; + this.ttlSeconds = 0; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsManager.java b/src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsManager.java new file mode 100644 index 00000000..85213a67 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsManager.java @@ -0,0 +1,63 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.metrics; + +import com.xiaomi.infra.pegasus.tools.tools; +import org.slf4j.Logger; + +/** + * Created by weijiesun on 18-3-8. + */ +public final class MetricsManager { + public static void updateCount(String counterName, long count) { + metrics.setMeter(counterName, count); + } + + public static void setHistogramValue(String counterName, long value) { + metrics.setHistorgram(counterName, value); + } + + public static final void initFromHost(String host, String tag, int reportIntervalSec) { + synchronized (logger) { + if (started) { + logger.warn("perf counter system has started with host({}), tag({}), interval({}), " + + "skip this init with host({}), tag({}), interval(){}", + MetricsManager.host, MetricsManager.tag, MetricsManager.reportIntervalSecs, + host, tag, reportIntervalSec); + return; + } + + logger.info("init metrics with host({}), tag({}), interval({})", + host, tag, reportIntervalSec); + + MetricsManager.host = host; + MetricsManager.tag = tag; + MetricsManager.reportIntervalSecs = reportIntervalSec; + metrics = new MetricsPool(host, tag, reportIntervalSec); + reporter = new MetricsReporter(reportIntervalSec, metrics); + reporter.start(); + started = true; + } + } + + public static final void detectHostAndInit(String tag, int reportIntervalSec) { + initFromHost(tools.getLocalHostAddress().getHostName(), tag, reportIntervalSec); + } + + public static final void finish() { + synchronized (logger) { + reporter.stop(); + started = false; + } + } + + private static boolean started = false; + private static String host; + private static String tag; + private static int reportIntervalSecs; + + private static MetricsPool metrics; + private static MetricsReporter reporter; + private static final Logger logger = org.slf4j.LoggerFactory.getLogger(MetricsManager.class); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsPool.java b/src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsPool.java new file mode 100644 index 00000000..59f88425 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsPool.java @@ -0,0 +1,134 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.metrics; + +import com.codahale.metrics.Histogram; +import com.codahale.metrics.Meter; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.Snapshot; +import com.xiaomi.infra.pegasus.tools.tools; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Map; +import java.util.SortedMap; + +/** + * Created by weijiesun on 18-3-9. + */ +public final class MetricsPool { + public MetricsPool(String host, String tags, int reportStepSec) { + theMetric = new FalconMetric(); + theMetric.endpoint = host; + theMetric.step = reportStepSec; + theMetric.tags = tags; + } + + public void setMeter(String counterName, long count) { + registry.meter(counterName).mark(count); + } + + public void setHistorgram(String counterName, long value) { + registry.histogram(counterName).update(value); + } + + public void genJsonsFromMeter(String name, Meter meter, StringBuilder output) throws JSONException { + theMetric.counterType = "GAUGE"; + + theMetric.metric = name + ".cps-1sec"; + theMetric.value = meter.getMeanRate(); + oneMetricToJson(theMetric, output); + output.append(','); + + theMetric.metric = name + ".cps-1min"; + theMetric.value = meter.getOneMinuteRate(); + oneMetricToJson(theMetric, output); + output.append(','); + + theMetric.metric = name + ".cps-5min"; + theMetric.value = meter.getFiveMinuteRate(); + oneMetricToJson(theMetric, output); + output.append(','); + + theMetric.metric = name + ".cps-15min"; + theMetric.value = meter.getFifteenMinuteRate(); + oneMetricToJson(theMetric, output); + } + + public void genJsonsFromHistogram(String name, Histogram hist, StringBuilder output) throws JSONException { + theMetric.counterType = "GAUGE"; + Snapshot s = hist.getSnapshot(); + + theMetric.metric = name + ".p50"; + theMetric.value = s.getMedian(); + oneMetricToJson(theMetric, output); + output.append(','); + + theMetric.metric = name + ".p99"; + theMetric.value = s.get99thPercentile(); + oneMetricToJson(theMetric, output); + output.append(','); + + theMetric.metric = name + ".p999"; + theMetric.value = s.get999thPercentile(); + oneMetricToJson(theMetric, output); + output.append(','); + + theMetric.metric = name + ".max"; + theMetric.value = s.getMax(); + oneMetricToJson(theMetric, output); + } + + public static void oneMetricToJson(FalconMetric metric, StringBuilder output) throws JSONException { + JSONObject obj = new JSONObject(); + obj.put("endpoint", metric.endpoint); + obj.put("metric", metric.metric); + obj.put("timestamp", metric.timestamp); + obj.put("step", metric.step); + obj.put("value", metric.value); + obj.put("counterType", metric.counterType); + obj.put("tags", metric.tags); + output.append(obj.toString()); + } + + public String metricsToJson() throws JSONException { + theMetric.timestamp = tools.unixEpochMills() / 1000; + + StringBuilder builder = new StringBuilder(); + builder.append('['); + SortedMap meters = registry.getMeters(); + boolean start = true; + for (Map.Entry entry : meters.entrySet()) { + if (!start) { + builder.append(','); + } + genJsonsFromMeter(entry.getKey(), entry.getValue(), builder); + start = false; + } + + for (Map.Entry entry : registry.getHistograms().entrySet()) { + if (!start) { + builder.append(','); + } + genJsonsFromHistogram(entry.getKey(), entry.getValue(), builder); + start = false; + } + builder.append("]"); + + return builder.toString(); + } + + final static class FalconMetric { + public String endpoint; // metric host + public String metric; // metric name + public long timestamp; // report time in unix seconds + public int step; // report interval in seconds; + public double value; // metric value + public String counterType; // GAUGE or COUNTER + public String tags; // metrics description + } + + private FalconMetric theMetric; + private final MetricRegistry registry = new MetricRegistry(); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsReporter.java b/src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsReporter.java new file mode 100644 index 00000000..9c3dcea3 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/metrics/MetricsReporter.java @@ -0,0 +1,178 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.metrics; + +import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.Unpooled; +import io.netty.channel.*; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.http.*; +import io.netty.util.CharsetUtil; +import org.json.JSONException; +import org.slf4j.Logger; + +import java.util.concurrent.TimeUnit; + +/** + * Created by weijiesun on 18-3-9. + */ +public class MetricsReporter { + public MetricsReporter(int reportSecs, MetricsPool pool) { + falconAgentIP = "127.0.0.1"; + falconAgentPort = 1988; + falconAgentSocket = falconAgentIP + String.valueOf(falconAgentPort); + + reportIntervalSecs = reportSecs; + falconRequestPath = "/v1/push"; + metrics = pool; + + boot = new Bootstrap(); + httpClientGroup = new NioEventLoopGroup(1); + + boot.group(httpClientGroup).channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .option(ChannelOption.SO_KEEPALIVE, true) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 500) + .handler(new ChannelInitializer() { + @Override + public void initChannel(SocketChannel ch) { + ChannelPipeline p = ch.pipeline(); + p.addLast(new HttpClientCodec()); + p.addLast(new HttpContentDecompressor()); + p.addLast(new HttpClientHandler()); + } + }); + } + + public void start() { + tryConnect(); + } + + public void stop() { + httpClientGroup.shutdownGracefully(); + } + + public void tryConnect() { + boot.connect(falconAgentIP, falconAgentPort).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + if (channelFuture.isSuccess()) { + logger.info("create channel with {} succeed, wait it active", falconAgentSocket); + } else { + logger.error("create channel with {} failed, connect later: ", + falconAgentSocket, + channelFuture.cause()); + scheduleNextConnect(); + } + } + }); + } + + public void scheduleNextConnect() { + httpClientGroup.schedule(new Runnable() { + @Override + public void run() { + tryConnect(); + } + }, (long) reportIntervalSecs, TimeUnit.SECONDS); + } + + public void scheduleNextReport(final Channel channel) { + httpClientGroup.schedule(new Runnable() { + @Override + public void run() { + reportMetrics(channel); + } + }, reportIntervalSecs, TimeUnit.SECONDS); + } + + public void reportMetrics(final Channel channel) { + String json_metrics; + try { + json_metrics = metrics.metricsToJson(); + } catch (JSONException ex) { + logger.warn("encode metrics to json failed, skip current report, retry later: ", ex); + scheduleNextReport(channel); + return; + } + + logger.debug("generate metrics {} and try to report", json_metrics); + FullHttpRequest request = new DefaultFullHttpRequest( + HttpVersion.HTTP_1_1, + HttpMethod.POST, + falconRequestPath, + Unpooled.copiedBuffer(json_metrics.getBytes())); + request.headers().add(HttpHeaders.Names.HOST, falconAgentSocket); + request.headers().add(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); + request.headers().add(HttpHeaders.Names.CONTENT_LENGTH, request.content().readableBytes()); + request.headers().add(HttpHeaders.Names.CONTENT_TYPE, "application/x-www-form-urlencoded"); + + channel.writeAndFlush(request).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + if (!channelFuture.isSuccess()) { + logger.warn("report to {} failed, skip current report, retry later: ", + channel.toString(), + channelFuture.cause()); + channel.close(); + } + } + }); + } + + class HttpClientHandler extends SimpleChannelInboundHandler { + @Override + protected void channelRead0(ChannelHandlerContext ctx, HttpObject httpObject) throws Exception { + if (httpObject instanceof HttpResponse) { + HttpResponse resp = (HttpResponse) httpObject; + if (! resp.getStatus().equals(HttpResponseStatus.OK)) { + logger.error("http response status: {}", resp.getStatus().toString()); + } + logger.debug("http response status {}: CONTENT:[", resp.getStatus().toString()); + } + if (httpObject instanceof HttpContent) { + HttpContent content = (HttpContent) httpObject; + logger.debug(content.content().toString(CharsetUtil.UTF_8)); + + if (content instanceof LastHttpContent) { + logger.debug("], response finished, schedule next report"); + scheduleNextReport(ctx.channel()); + } + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + logger.error("{} exception got: ", ctx.channel().toString(), cause); + ctx.close(); + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + logger.info("channel {} is active", ctx.channel().toString()); + reportMetrics(ctx.channel()); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + logger.info("channel {} is inactive", ctx.channel().toString()); + scheduleNextConnect(); + } + } + + private String falconAgentIP; + private int falconAgentPort; + private String falconAgentSocket; // IP:port; + private int reportIntervalSecs; + private String falconRequestPath; + + private MetricsPool metrics; + + private Bootstrap boot; + private EventLoopGroup httpClientGroup; + + private static final Logger logger = org.slf4j.LoggerFactory.getLogger(MetricsReporter.class); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/client_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/client_operator.java new file mode 100644 index 00000000..ae97908a --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/client_operator.java @@ -0,0 +1,73 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.base.error_code; +import com.xiaomi.infra.pegasus.base.gpid; +import com.xiaomi.infra.pegasus.tools.tools; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.rpc.ThriftHeader; + +public abstract class client_operator { + public client_operator(gpid gpid, String tableName) { + this.header = new ThriftHeader(); + this.header.app_id = gpid.get_app_id(); + this.header.partition_index = gpid.get_pidx(); + this.pid = gpid; + this.tableName = tableName; + this.rpc_error = new error_code(); + } + + public final byte[] prepare_thrift_header(int body_length) { + header.body_length = body_length; + header.header_length = ThriftHeader.HEADER_LENGTH; + header.thread_hash = tools.dsn_gpid_to_thread_hash(header.app_id, header.partition_index); + header.partition_hash = 0; + return header.toByteArray(); + } + + public String getQPSCounter() { + String mark; + switch (rpc_error.errno) { + case ERR_OK: + mark = "succ"; + break; + case ERR_TIMEOUT: + mark = "timeout"; + break; + default: + mark = "fail"; + break; + } + // pegasus.client.put.succ.qps + return new StringBuilder() + .append("pegasus.client.") + .append(name()) + .append(".") + .append(mark) + .append(".qps@") + .append(tableName) + .toString(); + } + + public String getLatencyCounter() { + // pegasus.client.put.latency + return new StringBuilder() + .append("pegasus.client.") + .append(name()) + .append(".latency@") + .append(tableName) + .toString(); + } + + public final gpid get_gpid() { return pid; } + public abstract String name(); + public abstract void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int sequence_id) throws TException; + public abstract void recv_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws TException; + + public ThriftHeader header; + public gpid pid; + public String tableName; // only for metrics + public error_code rpc_error; +}; diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/query_cfg_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/query_cfg_operator.java new file mode 100644 index 00000000..a4a6b663 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/query_cfg_operator.java @@ -0,0 +1,44 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +/** + * Created by weijiesun on 16-11-8. + */ +import com.xiaomi.infra.pegasus.apps.meta; +import com.xiaomi.infra.pegasus.replication.*; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +public class query_cfg_operator extends client_operator { + public query_cfg_operator(com.xiaomi.infra.pegasus.base.gpid gpid, query_cfg_request request) { + super(gpid, ""); + this.request = request; + } + + public String name() { return "query_config"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_CM_QUERY_PARTITION_CONFIG_BY_INDEX", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + meta.query_cfg_args args = new meta.query_cfg_args(request); + args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(TProtocol iprot) throws TException { + meta.query_cfg_result result = new meta.query_cfg_result(); + result.read(iprot); + if (result.isSetSuccess()) + response = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "get scanner failed: unknown result"); + } + + public query_cfg_response get_response() { return response; } + + private query_cfg_request request; + private query_cfg_response response; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_clear_scanner_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_clear_scanner_operator.java new file mode 100644 index 00000000..a28d5941 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_clear_scanner_operator.java @@ -0,0 +1,35 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.apps.scan_response; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +import com.xiaomi.infra.pegasus.apps.rrdb; + +public class rrdb_clear_scanner_operator extends client_operator { + public rrdb_clear_scanner_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, long request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "clear_scanner"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_CLEAR_SCANNER", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.clear_scanner_args args = new rrdb.clear_scanner_args(request); + args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(TProtocol iprot) throws TException { + } + + public scan_response get_response() { return null; } + + private long request; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_get_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_get_operator.java new file mode 100644 index 00000000..643a784a --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_get_operator.java @@ -0,0 +1,43 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.apps.read_response; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; + +import com.xiaomi.infra.pegasus.apps.rrdb; +import com.xiaomi.infra.pegasus.base.blob; +import com.xiaomi.infra.pegasus.base.error_code; +import com.xiaomi.infra.pegasus.base.gpid; + +public class rrdb_get_operator extends client_operator { + public rrdb_get_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, blob request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "get"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_GET", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.get_args get_args = new rrdb.get_args(request); + get_args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws TException { + rrdb.get_result result = new rrdb.get_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "get failed: unknown result"); + } + + public read_response get_response() { return resp; } + private blob request; + private read_response resp; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_get_scanner_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_get_scanner_operator.java new file mode 100644 index 00000000..ec72c395 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_get_scanner_operator.java @@ -0,0 +1,43 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.apps.get_scanner_request; +import com.xiaomi.infra.pegasus.apps.scan_response; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +import com.xiaomi.infra.pegasus.apps.rrdb; + +public class rrdb_get_scanner_operator extends client_operator { + public rrdb_get_scanner_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, get_scanner_request request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "get_scanner"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_GET_SCANNER", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.get_scanner_args args = new rrdb.get_scanner_args(request); + args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(TProtocol iprot) throws TException { + rrdb.get_scanner_result result = new rrdb.get_scanner_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "get scanner failed: unknown result"); + } + + public scan_response get_response() { return resp; } + + private get_scanner_request request; + private scan_response resp; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_get_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_get_operator.java new file mode 100644 index 00000000..d546234d --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_get_operator.java @@ -0,0 +1,43 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.apps.multi_get_request; +import com.xiaomi.infra.pegasus.apps.multi_get_response; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; + +import com.xiaomi.infra.pegasus.apps.rrdb; + +public class rrdb_multi_get_operator extends client_operator { + public rrdb_multi_get_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, multi_get_request request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "multi_get"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_MULTI_GET", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.multi_get_args get_args = new rrdb.multi_get_args(request); + get_args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws TException { + rrdb.multi_get_result result = new rrdb.multi_get_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException( + com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "multi get failed: unknown result"); + } + + public multi_get_response get_response() { return resp; } + private multi_get_request request; + private multi_get_response resp; +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_put_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_put_operator.java new file mode 100644 index 00000000..b9403dab --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_put_operator.java @@ -0,0 +1,43 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +import com.xiaomi.infra.pegasus.apps.rrdb; +import com.xiaomi.infra.pegasus.apps.multi_put_request; +import com.xiaomi.infra.pegasus.apps.update_response; + +public class rrdb_multi_put_operator extends client_operator { + public rrdb_multi_put_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, multi_put_request request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "multi_put"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_MULTI_PUT", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.multi_put_args put_args = new rrdb.multi_put_args(request); + put_args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(TProtocol iprot) throws TException { + rrdb.put_result result = new rrdb.put_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "multi put failed: unknown result"); + } + + public update_response get_response() { return resp; } + + private multi_put_request request; + private update_response resp; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_remove_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_remove_operator.java new file mode 100644 index 00000000..d2e9ce92 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_multi_remove_operator.java @@ -0,0 +1,45 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.apps.multi_remove_request; +import com.xiaomi.infra.pegasus.apps.multi_remove_response; +import com.xiaomi.infra.pegasus.apps.rrdb; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; + +/** + * Created by weijiesun on 16-12-8. + */ +public class rrdb_multi_remove_operator extends client_operator { + public rrdb_multi_remove_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, multi_remove_request request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "multi_remove"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_MULTI_REMOVE", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.multi_remove_args get_args = new rrdb.multi_remove_args(request); + get_args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws TException { + rrdb.multi_remove_result result = new rrdb.multi_remove_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException( + com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "multi get failed: unknown result"); + } + + public multi_remove_response get_response() { return resp; } + + private multi_remove_request request; + private multi_remove_response resp; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_put_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_put_operator.java new file mode 100644 index 00000000..7f3a409c --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_put_operator.java @@ -0,0 +1,43 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.apps.update_response; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +import com.xiaomi.infra.pegasus.apps.rrdb; +import com.xiaomi.infra.pegasus.apps.update_request; + +public class rrdb_put_operator extends client_operator { + public rrdb_put_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, update_request request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "put"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_PUT", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.put_args put_args = new rrdb.put_args(request); + put_args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(TProtocol iprot) throws TException { + rrdb.put_result result = new rrdb.put_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "put failed: unknown result"); + } + + public update_response get_response() { return resp; } + + private update_request request; + private update_response resp; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_remove_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_remove_operator.java new file mode 100644 index 00000000..afd34976 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_remove_operator.java @@ -0,0 +1,43 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.apps.update_response; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +import com.xiaomi.infra.pegasus.apps.rrdb; +import com.xiaomi.infra.pegasus.base.blob; + +public class rrdb_remove_operator extends client_operator { + public rrdb_remove_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, blob request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "remove"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_REMOVE", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.remove_args remove_args = new rrdb.remove_args(request); + remove_args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(TProtocol iprot) throws TException { + rrdb.put_result result = new rrdb.put_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "put failed: unknown result"); + } + + public update_response get_response() { return resp; } + + private blob request; + private update_response resp; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_scan_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_scan_operator.java new file mode 100644 index 00000000..f9f8238e --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_scan_operator.java @@ -0,0 +1,45 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.apps.scan_request; +import com.xiaomi.infra.pegasus.apps.scan_response; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +import com.xiaomi.infra.pegasus.apps.rrdb; + +public class rrdb_scan_operator extends client_operator { + public rrdb_scan_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, scan_request request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "scan"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_SCAN", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.scan_args args = new rrdb.scan_args(request); + args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(TProtocol iprot) throws TException { + rrdb.scan_result result = new rrdb.scan_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "scan failed: unknown result"); + } + + public scan_response get_response() { + return resp; + } + + private scan_request request; + private scan_response resp; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_sortkey_count_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_sortkey_count_operator.java new file mode 100644 index 00000000..2a8491da --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_sortkey_count_operator.java @@ -0,0 +1,45 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.apps.count_response; +import com.xiaomi.infra.pegasus.apps.rrdb; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; + +/** + * Created by weijiesun on 16-12-8. + */ +public class rrdb_sortkey_count_operator extends client_operator { + public rrdb_sortkey_count_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, com.xiaomi.infra.pegasus.base.blob request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "sortkey_count"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_SORTKEY_COUNT", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.sortkey_count_args get_args = new rrdb.sortkey_count_args(request); + get_args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws TException { + rrdb.sortkey_count_result result = new rrdb.sortkey_count_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException( + com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "multi get failed: unknown result"); + } + + public count_response get_response() { return resp; } + + private com.xiaomi.infra.pegasus.base.blob request; + private count_response resp; + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_ttl_operator.java b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_ttl_operator.java new file mode 100644 index 00000000..7058e5a4 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/operator/rrdb_ttl_operator.java @@ -0,0 +1,40 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.operator; + +import com.xiaomi.infra.pegasus.apps.ttl_response; +import com.xiaomi.infra.pegasus.apps.rrdb; +import com.xiaomi.infra.pegasus.base.blob; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; + +public class rrdb_ttl_operator extends client_operator { + public rrdb_ttl_operator(com.xiaomi.infra.pegasus.base.gpid gpid, String tableName, blob request) { + super(gpid, tableName); + this.request = request; + } + + public String name() { return "ttl"; } + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_TTL", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.get_args get_args = new rrdb.get_args(request); + get_args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws TException { + rrdb.ttl_result result = new rrdb.ttl_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException(com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, "ttl failed: unknown result"); + } + + public ttl_response get_response() { return resp; } + private blob request; + private ttl_response resp; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/replication/partition_configuration.java b/src/main/java/com/xiaomi/infra/pegasus/replication/partition_configuration.java new file mode 100644 index 00000000..449dc53d --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/replication/partition_configuration.java @@ -0,0 +1,1097 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.replication; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class partition_configuration implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("partition_configuration"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("pid", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField BALLOT_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("ballot", com.xiaomi.infra.pegasus.thrift.protocol.TType.I64, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField MAX_REPLICA_COUNT_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("max_replica_count", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PRIMARY_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("primary", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField SECONDARIES_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("secondaries", com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, (short)5); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField LAST_DROPS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("last_drops", com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, (short)6); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField LAST_COMMITTED_DECREE_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("last_committed_decree", com.xiaomi.infra.pegasus.thrift.protocol.TType.I64, (short)7); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new partition_configurationStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new partition_configurationTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.gpid pid; // required + public long ballot; // required + public int max_replica_count; // required + public com.xiaomi.infra.pegasus.base.rpc_address primary; // required + public java.util.List secondaries; // required + public java.util.List last_drops; // required + public long last_committed_decree; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + PID((short)1, "pid"), + BALLOT((short)2, "ballot"), + MAX_REPLICA_COUNT((short)3, "max_replica_count"), + PRIMARY((short)4, "primary"), + SECONDARIES((short)5, "secondaries"), + LAST_DROPS((short)6, "last_drops"), + LAST_COMMITTED_DECREE((short)7, "last_committed_decree"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // PID + return PID; + case 2: // BALLOT + return BALLOT; + case 3: // MAX_REPLICA_COUNT + return MAX_REPLICA_COUNT; + case 4: // PRIMARY + return PRIMARY; + case 5: // SECONDARIES + return SECONDARIES; + case 6: // LAST_DROPS + return LAST_DROPS; + case 7: // LAST_COMMITTED_DECREE + return LAST_COMMITTED_DECREE; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __BALLOT_ISSET_ID = 0; + private static final int __MAX_REPLICA_COUNT_ISSET_ID = 1; + private static final int __LAST_COMMITTED_DECREE_ISSET_ID = 2; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.PID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("pid", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.gpid.class))); + tmpMap.put(_Fields.BALLOT, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("ballot", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I64))); + tmpMap.put(_Fields.MAX_REPLICA_COUNT, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("max_replica_count", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.PRIMARY, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("primary", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.rpc_address.class))); + tmpMap.put(_Fields.SECONDARIES, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("secondaries", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.ListMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.rpc_address.class)))); + tmpMap.put(_Fields.LAST_DROPS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("last_drops", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.ListMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.rpc_address.class)))); + tmpMap.put(_Fields.LAST_COMMITTED_DECREE, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("last_committed_decree", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I64))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(partition_configuration.class, metaDataMap); + } + + public partition_configuration() { + } + + public partition_configuration( + com.xiaomi.infra.pegasus.base.gpid pid, + long ballot, + int max_replica_count, + com.xiaomi.infra.pegasus.base.rpc_address primary, + java.util.List secondaries, + java.util.List last_drops, + long last_committed_decree) + { + this(); + this.pid = pid; + this.ballot = ballot; + setBallotIsSet(true); + this.max_replica_count = max_replica_count; + setMax_replica_countIsSet(true); + this.primary = primary; + this.secondaries = secondaries; + this.last_drops = last_drops; + this.last_committed_decree = last_committed_decree; + setLast_committed_decreeIsSet(true); + } + + /** + * Performs a deep copy on other. + */ + public partition_configuration(partition_configuration other) { + __isset_bitfield = other.__isset_bitfield; + if (other.isSetPid()) { + this.pid = new com.xiaomi.infra.pegasus.base.gpid(other.pid); + } + this.ballot = other.ballot; + this.max_replica_count = other.max_replica_count; + if (other.isSetPrimary()) { + this.primary = new com.xiaomi.infra.pegasus.base.rpc_address(other.primary); + } + if (other.isSetSecondaries()) { + java.util.List __this__secondaries = new java.util.ArrayList(other.secondaries.size()); + for (com.xiaomi.infra.pegasus.base.rpc_address other_element : other.secondaries) { + __this__secondaries.add(new com.xiaomi.infra.pegasus.base.rpc_address(other_element)); + } + this.secondaries = __this__secondaries; + } + if (other.isSetLast_drops()) { + java.util.List __this__last_drops = new java.util.ArrayList(other.last_drops.size()); + for (com.xiaomi.infra.pegasus.base.rpc_address other_element : other.last_drops) { + __this__last_drops.add(new com.xiaomi.infra.pegasus.base.rpc_address(other_element)); + } + this.last_drops = __this__last_drops; + } + this.last_committed_decree = other.last_committed_decree; + } + + public partition_configuration deepCopy() { + return new partition_configuration(this); + } + + @Override + public void clear() { + this.pid = null; + setBallotIsSet(false); + this.ballot = 0; + setMax_replica_countIsSet(false); + this.max_replica_count = 0; + this.primary = null; + this.secondaries = null; + this.last_drops = null; + setLast_committed_decreeIsSet(false); + this.last_committed_decree = 0; + } + + public com.xiaomi.infra.pegasus.base.gpid getPid() { + return this.pid; + } + + public partition_configuration setPid(com.xiaomi.infra.pegasus.base.gpid pid) { + this.pid = pid; + return this; + } + + public void unsetPid() { + this.pid = null; + } + + /** Returns true if field pid is set (has been assigned a value) and false otherwise */ + public boolean isSetPid() { + return this.pid != null; + } + + public void setPidIsSet(boolean value) { + if (!value) { + this.pid = null; + } + } + + public long getBallot() { + return this.ballot; + } + + public partition_configuration setBallot(long ballot) { + this.ballot = ballot; + setBallotIsSet(true); + return this; + } + + public void unsetBallot() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __BALLOT_ISSET_ID); + } + + /** Returns true if field ballot is set (has been assigned a value) and false otherwise */ + public boolean isSetBallot() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __BALLOT_ISSET_ID); + } + + public void setBallotIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __BALLOT_ISSET_ID, value); + } + + public int getMax_replica_count() { + return this.max_replica_count; + } + + public partition_configuration setMax_replica_count(int max_replica_count) { + this.max_replica_count = max_replica_count; + setMax_replica_countIsSet(true); + return this; + } + + public void unsetMax_replica_count() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __MAX_REPLICA_COUNT_ISSET_ID); + } + + /** Returns true if field max_replica_count is set (has been assigned a value) and false otherwise */ + public boolean isSetMax_replica_count() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __MAX_REPLICA_COUNT_ISSET_ID); + } + + public void setMax_replica_countIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __MAX_REPLICA_COUNT_ISSET_ID, value); + } + + public com.xiaomi.infra.pegasus.base.rpc_address getPrimary() { + return this.primary; + } + + public partition_configuration setPrimary(com.xiaomi.infra.pegasus.base.rpc_address primary) { + this.primary = primary; + return this; + } + + public void unsetPrimary() { + this.primary = null; + } + + /** Returns true if field primary is set (has been assigned a value) and false otherwise */ + public boolean isSetPrimary() { + return this.primary != null; + } + + public void setPrimaryIsSet(boolean value) { + if (!value) { + this.primary = null; + } + } + + public int getSecondariesSize() { + return (this.secondaries == null) ? 0 : this.secondaries.size(); + } + + public java.util.Iterator getSecondariesIterator() { + return (this.secondaries == null) ? null : this.secondaries.iterator(); + } + + public void addToSecondaries(com.xiaomi.infra.pegasus.base.rpc_address elem) { + if (this.secondaries == null) { + this.secondaries = new java.util.ArrayList(); + } + this.secondaries.add(elem); + } + + public java.util.List getSecondaries() { + return this.secondaries; + } + + public partition_configuration setSecondaries(java.util.List secondaries) { + this.secondaries = secondaries; + return this; + } + + public void unsetSecondaries() { + this.secondaries = null; + } + + /** Returns true if field secondaries is set (has been assigned a value) and false otherwise */ + public boolean isSetSecondaries() { + return this.secondaries != null; + } + + public void setSecondariesIsSet(boolean value) { + if (!value) { + this.secondaries = null; + } + } + + public int getLast_dropsSize() { + return (this.last_drops == null) ? 0 : this.last_drops.size(); + } + + public java.util.Iterator getLast_dropsIterator() { + return (this.last_drops == null) ? null : this.last_drops.iterator(); + } + + public void addToLast_drops(com.xiaomi.infra.pegasus.base.rpc_address elem) { + if (this.last_drops == null) { + this.last_drops = new java.util.ArrayList(); + } + this.last_drops.add(elem); + } + + public java.util.List getLast_drops() { + return this.last_drops; + } + + public partition_configuration setLast_drops(java.util.List last_drops) { + this.last_drops = last_drops; + return this; + } + + public void unsetLast_drops() { + this.last_drops = null; + } + + /** Returns true if field last_drops is set (has been assigned a value) and false otherwise */ + public boolean isSetLast_drops() { + return this.last_drops != null; + } + + public void setLast_dropsIsSet(boolean value) { + if (!value) { + this.last_drops = null; + } + } + + public long getLast_committed_decree() { + return this.last_committed_decree; + } + + public partition_configuration setLast_committed_decree(long last_committed_decree) { + this.last_committed_decree = last_committed_decree; + setLast_committed_decreeIsSet(true); + return this; + } + + public void unsetLast_committed_decree() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __LAST_COMMITTED_DECREE_ISSET_ID); + } + + /** Returns true if field last_committed_decree is set (has been assigned a value) and false otherwise */ + public boolean isSetLast_committed_decree() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __LAST_COMMITTED_DECREE_ISSET_ID); + } + + public void setLast_committed_decreeIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __LAST_COMMITTED_DECREE_ISSET_ID, value); + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case PID: + if (value == null) { + unsetPid(); + } else { + setPid((com.xiaomi.infra.pegasus.base.gpid)value); + } + break; + + case BALLOT: + if (value == null) { + unsetBallot(); + } else { + setBallot((java.lang.Long)value); + } + break; + + case MAX_REPLICA_COUNT: + if (value == null) { + unsetMax_replica_count(); + } else { + setMax_replica_count((java.lang.Integer)value); + } + break; + + case PRIMARY: + if (value == null) { + unsetPrimary(); + } else { + setPrimary((com.xiaomi.infra.pegasus.base.rpc_address)value); + } + break; + + case SECONDARIES: + if (value == null) { + unsetSecondaries(); + } else { + setSecondaries((java.util.List)value); + } + break; + + case LAST_DROPS: + if (value == null) { + unsetLast_drops(); + } else { + setLast_drops((java.util.List)value); + } + break; + + case LAST_COMMITTED_DECREE: + if (value == null) { + unsetLast_committed_decree(); + } else { + setLast_committed_decree((java.lang.Long)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case PID: + return getPid(); + + case BALLOT: + return getBallot(); + + case MAX_REPLICA_COUNT: + return getMax_replica_count(); + + case PRIMARY: + return getPrimary(); + + case SECONDARIES: + return getSecondaries(); + + case LAST_DROPS: + return getLast_drops(); + + case LAST_COMMITTED_DECREE: + return getLast_committed_decree(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case PID: + return isSetPid(); + case BALLOT: + return isSetBallot(); + case MAX_REPLICA_COUNT: + return isSetMax_replica_count(); + case PRIMARY: + return isSetPrimary(); + case SECONDARIES: + return isSetSecondaries(); + case LAST_DROPS: + return isSetLast_drops(); + case LAST_COMMITTED_DECREE: + return isSetLast_committed_decree(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof partition_configuration) + return this.equals((partition_configuration)that); + return false; + } + + public boolean equals(partition_configuration that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_pid = true && this.isSetPid(); + boolean that_present_pid = true && that.isSetPid(); + if (this_present_pid || that_present_pid) { + if (!(this_present_pid && that_present_pid)) + return false; + if (!this.pid.equals(that.pid)) + return false; + } + + boolean this_present_ballot = true; + boolean that_present_ballot = true; + if (this_present_ballot || that_present_ballot) { + if (!(this_present_ballot && that_present_ballot)) + return false; + if (this.ballot != that.ballot) + return false; + } + + boolean this_present_max_replica_count = true; + boolean that_present_max_replica_count = true; + if (this_present_max_replica_count || that_present_max_replica_count) { + if (!(this_present_max_replica_count && that_present_max_replica_count)) + return false; + if (this.max_replica_count != that.max_replica_count) + return false; + } + + boolean this_present_primary = true && this.isSetPrimary(); + boolean that_present_primary = true && that.isSetPrimary(); + if (this_present_primary || that_present_primary) { + if (!(this_present_primary && that_present_primary)) + return false; + if (!this.primary.equals(that.primary)) + return false; + } + + boolean this_present_secondaries = true && this.isSetSecondaries(); + boolean that_present_secondaries = true && that.isSetSecondaries(); + if (this_present_secondaries || that_present_secondaries) { + if (!(this_present_secondaries && that_present_secondaries)) + return false; + if (!this.secondaries.equals(that.secondaries)) + return false; + } + + boolean this_present_last_drops = true && this.isSetLast_drops(); + boolean that_present_last_drops = true && that.isSetLast_drops(); + if (this_present_last_drops || that_present_last_drops) { + if (!(this_present_last_drops && that_present_last_drops)) + return false; + if (!this.last_drops.equals(that.last_drops)) + return false; + } + + boolean this_present_last_committed_decree = true; + boolean that_present_last_committed_decree = true; + if (this_present_last_committed_decree || that_present_last_committed_decree) { + if (!(this_present_last_committed_decree && that_present_last_committed_decree)) + return false; + if (this.last_committed_decree != that.last_committed_decree) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetPid()) ? 131071 : 524287); + if (isSetPid()) + hashCode = hashCode * 8191 + pid.hashCode(); + + hashCode = hashCode * 8191 + com.xiaomi.infra.pegasus.thrift.TBaseHelper.hashCode(ballot); + + hashCode = hashCode * 8191 + max_replica_count; + + hashCode = hashCode * 8191 + ((isSetPrimary()) ? 131071 : 524287); + if (isSetPrimary()) + hashCode = hashCode * 8191 + primary.hashCode(); + + hashCode = hashCode * 8191 + ((isSetSecondaries()) ? 131071 : 524287); + if (isSetSecondaries()) + hashCode = hashCode * 8191 + secondaries.hashCode(); + + hashCode = hashCode * 8191 + ((isSetLast_drops()) ? 131071 : 524287); + if (isSetLast_drops()) + hashCode = hashCode * 8191 + last_drops.hashCode(); + + hashCode = hashCode * 8191 + com.xiaomi.infra.pegasus.thrift.TBaseHelper.hashCode(last_committed_decree); + + return hashCode; + } + + @Override + public int compareTo(partition_configuration other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetPid()).compareTo(other.isSetPid()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPid()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.pid, other.pid); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetBallot()).compareTo(other.isSetBallot()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetBallot()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.ballot, other.ballot); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetMax_replica_count()).compareTo(other.isSetMax_replica_count()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetMax_replica_count()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.max_replica_count, other.max_replica_count); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPrimary()).compareTo(other.isSetPrimary()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPrimary()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.primary, other.primary); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetSecondaries()).compareTo(other.isSetSecondaries()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetSecondaries()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.secondaries, other.secondaries); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetLast_drops()).compareTo(other.isSetLast_drops()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetLast_drops()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.last_drops, other.last_drops); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetLast_committed_decree()).compareTo(other.isSetLast_committed_decree()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetLast_committed_decree()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.last_committed_decree, other.last_committed_decree); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("partition_configuration("); + boolean first = true; + + sb.append("pid:"); + if (this.pid == null) { + sb.append("null"); + } else { + sb.append(this.pid); + } + first = false; + if (!first) sb.append(", "); + sb.append("ballot:"); + sb.append(this.ballot); + first = false; + if (!first) sb.append(", "); + sb.append("max_replica_count:"); + sb.append(this.max_replica_count); + first = false; + if (!first) sb.append(", "); + sb.append("primary:"); + if (this.primary == null) { + sb.append("null"); + } else { + sb.append(this.primary); + } + first = false; + if (!first) sb.append(", "); + sb.append("secondaries:"); + if (this.secondaries == null) { + sb.append("null"); + } else { + sb.append(this.secondaries); + } + first = false; + if (!first) sb.append(", "); + sb.append("last_drops:"); + if (this.last_drops == null) { + sb.append("null"); + } else { + sb.append(this.last_drops); + } + first = false; + if (!first) sb.append(", "); + sb.append("last_committed_decree:"); + sb.append(this.last_committed_decree); + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (pid != null) { + pid.validate(); + } + if (primary != null) { + primary.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class partition_configurationStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public partition_configurationStandardScheme getScheme() { + return new partition_configurationStandardScheme(); + } + } + + private static class partition_configurationStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, partition_configuration struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // PID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.pid = new com.xiaomi.infra.pegasus.base.gpid(); + struct.pid.read(iprot); + struct.setPidIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // BALLOT + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I64) { + struct.ballot = iprot.readI64(); + struct.setBallotIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // MAX_REPLICA_COUNT + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.max_replica_count = iprot.readI32(); + struct.setMax_replica_countIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // PRIMARY + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.primary = new com.xiaomi.infra.pegasus.base.rpc_address(); + struct.primary.read(iprot); + struct.setPrimaryIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 5: // SECONDARIES + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list0 = iprot.readListBegin(); + struct.secondaries = new java.util.ArrayList(_list0.size); + com.xiaomi.infra.pegasus.base.rpc_address _elem1; + for (int _i2 = 0; _i2 < _list0.size; ++_i2) + { + _elem1 = new com.xiaomi.infra.pegasus.base.rpc_address(); + _elem1.read(iprot); + struct.secondaries.add(_elem1); + } + iprot.readListEnd(); + } + struct.setSecondariesIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 6: // LAST_DROPS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list3 = iprot.readListBegin(); + struct.last_drops = new java.util.ArrayList(_list3.size); + com.xiaomi.infra.pegasus.base.rpc_address _elem4; + for (int _i5 = 0; _i5 < _list3.size; ++_i5) + { + _elem4 = new com.xiaomi.infra.pegasus.base.rpc_address(); + _elem4.read(iprot); + struct.last_drops.add(_elem4); + } + iprot.readListEnd(); + } + struct.setLast_dropsIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 7: // LAST_COMMITTED_DECREE + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I64) { + struct.last_committed_decree = iprot.readI64(); + struct.setLast_committed_decreeIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, partition_configuration struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.pid != null) { + oprot.writeFieldBegin(PID_FIELD_DESC); + struct.pid.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(BALLOT_FIELD_DESC); + oprot.writeI64(struct.ballot); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(MAX_REPLICA_COUNT_FIELD_DESC); + oprot.writeI32(struct.max_replica_count); + oprot.writeFieldEnd(); + if (struct.primary != null) { + oprot.writeFieldBegin(PRIMARY_FIELD_DESC); + struct.primary.write(oprot); + oprot.writeFieldEnd(); + } + if (struct.secondaries != null) { + oprot.writeFieldBegin(SECONDARIES_FIELD_DESC); + { + oprot.writeListBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, struct.secondaries.size())); + for (com.xiaomi.infra.pegasus.base.rpc_address _iter6 : struct.secondaries) + { + _iter6.write(oprot); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + if (struct.last_drops != null) { + oprot.writeFieldBegin(LAST_DROPS_FIELD_DESC); + { + oprot.writeListBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, struct.last_drops.size())); + for (com.xiaomi.infra.pegasus.base.rpc_address _iter7 : struct.last_drops) + { + _iter7.write(oprot); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(LAST_COMMITTED_DECREE_FIELD_DESC); + oprot.writeI64(struct.last_committed_decree); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class partition_configurationTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public partition_configurationTupleScheme getScheme() { + return new partition_configurationTupleScheme(); + } + } + + private static class partition_configurationTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, partition_configuration struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetPid()) { + optionals.set(0); + } + if (struct.isSetBallot()) { + optionals.set(1); + } + if (struct.isSetMax_replica_count()) { + optionals.set(2); + } + if (struct.isSetPrimary()) { + optionals.set(3); + } + if (struct.isSetSecondaries()) { + optionals.set(4); + } + if (struct.isSetLast_drops()) { + optionals.set(5); + } + if (struct.isSetLast_committed_decree()) { + optionals.set(6); + } + oprot.writeBitSet(optionals, 7); + if (struct.isSetPid()) { + struct.pid.write(oprot); + } + if (struct.isSetBallot()) { + oprot.writeI64(struct.ballot); + } + if (struct.isSetMax_replica_count()) { + oprot.writeI32(struct.max_replica_count); + } + if (struct.isSetPrimary()) { + struct.primary.write(oprot); + } + if (struct.isSetSecondaries()) { + { + oprot.writeI32(struct.secondaries.size()); + for (com.xiaomi.infra.pegasus.base.rpc_address _iter8 : struct.secondaries) + { + _iter8.write(oprot); + } + } + } + if (struct.isSetLast_drops()) { + { + oprot.writeI32(struct.last_drops.size()); + for (com.xiaomi.infra.pegasus.base.rpc_address _iter9 : struct.last_drops) + { + _iter9.write(oprot); + } + } + } + if (struct.isSetLast_committed_decree()) { + oprot.writeI64(struct.last_committed_decree); + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, partition_configuration struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(7); + if (incoming.get(0)) { + struct.pid = new com.xiaomi.infra.pegasus.base.gpid(); + struct.pid.read(iprot); + struct.setPidIsSet(true); + } + if (incoming.get(1)) { + struct.ballot = iprot.readI64(); + struct.setBallotIsSet(true); + } + if (incoming.get(2)) { + struct.max_replica_count = iprot.readI32(); + struct.setMax_replica_countIsSet(true); + } + if (incoming.get(3)) { + struct.primary = new com.xiaomi.infra.pegasus.base.rpc_address(); + struct.primary.read(iprot); + struct.setPrimaryIsSet(true); + } + if (incoming.get(4)) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list10 = new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, iprot.readI32()); + struct.secondaries = new java.util.ArrayList(_list10.size); + com.xiaomi.infra.pegasus.base.rpc_address _elem11; + for (int _i12 = 0; _i12 < _list10.size; ++_i12) + { + _elem11 = new com.xiaomi.infra.pegasus.base.rpc_address(); + _elem11.read(iprot); + struct.secondaries.add(_elem11); + } + } + struct.setSecondariesIsSet(true); + } + if (incoming.get(5)) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list13 = new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, iprot.readI32()); + struct.last_drops = new java.util.ArrayList(_list13.size); + com.xiaomi.infra.pegasus.base.rpc_address _elem14; + for (int _i15 = 0; _i15 < _list13.size; ++_i15) + { + _elem14 = new com.xiaomi.infra.pegasus.base.rpc_address(); + _elem14.read(iprot); + struct.last_drops.add(_elem14); + } + } + struct.setLast_dropsIsSet(true); + } + if (incoming.get(6)) { + struct.last_committed_decree = iprot.readI64(); + struct.setLast_committed_decreeIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/replication/query_cfg_request.java b/src/main/java/com/xiaomi/infra/pegasus/replication/query_cfg_request.java new file mode 100644 index 00000000..c22f95ef --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/replication/query_cfg_request.java @@ -0,0 +1,528 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.replication; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class query_cfg_request implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("query_cfg_request"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField APP_NAME_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("app_name", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PARTITION_INDICES_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("partition_indices", com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, (short)2); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new query_cfg_requestStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new query_cfg_requestTupleSchemeFactory(); + + public java.lang.String app_name; // required + public java.util.List partition_indices; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + APP_NAME((short)1, "app_name"), + PARTITION_INDICES((short)2, "partition_indices"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // APP_NAME + return APP_NAME; + case 2: // PARTITION_INDICES + return PARTITION_INDICES; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.APP_NAME, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("app_name", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING))); + tmpMap.put(_Fields.PARTITION_INDICES, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("partition_indices", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.ListMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32)))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(query_cfg_request.class, metaDataMap); + } + + public query_cfg_request() { + } + + public query_cfg_request( + java.lang.String app_name, + java.util.List partition_indices) + { + this(); + this.app_name = app_name; + this.partition_indices = partition_indices; + } + + /** + * Performs a deep copy on other. + */ + public query_cfg_request(query_cfg_request other) { + if (other.isSetApp_name()) { + this.app_name = other.app_name; + } + if (other.isSetPartition_indices()) { + java.util.List __this__partition_indices = new java.util.ArrayList(other.partition_indices); + this.partition_indices = __this__partition_indices; + } + } + + public query_cfg_request deepCopy() { + return new query_cfg_request(this); + } + + @Override + public void clear() { + this.app_name = null; + this.partition_indices = null; + } + + public java.lang.String getApp_name() { + return this.app_name; + } + + public query_cfg_request setApp_name(java.lang.String app_name) { + this.app_name = app_name; + return this; + } + + public void unsetApp_name() { + this.app_name = null; + } + + /** Returns true if field app_name is set (has been assigned a value) and false otherwise */ + public boolean isSetApp_name() { + return this.app_name != null; + } + + public void setApp_nameIsSet(boolean value) { + if (!value) { + this.app_name = null; + } + } + + public int getPartition_indicesSize() { + return (this.partition_indices == null) ? 0 : this.partition_indices.size(); + } + + public java.util.Iterator getPartition_indicesIterator() { + return (this.partition_indices == null) ? null : this.partition_indices.iterator(); + } + + public void addToPartition_indices(int elem) { + if (this.partition_indices == null) { + this.partition_indices = new java.util.ArrayList(); + } + this.partition_indices.add(elem); + } + + public java.util.List getPartition_indices() { + return this.partition_indices; + } + + public query_cfg_request setPartition_indices(java.util.List partition_indices) { + this.partition_indices = partition_indices; + return this; + } + + public void unsetPartition_indices() { + this.partition_indices = null; + } + + /** Returns true if field partition_indices is set (has been assigned a value) and false otherwise */ + public boolean isSetPartition_indices() { + return this.partition_indices != null; + } + + public void setPartition_indicesIsSet(boolean value) { + if (!value) { + this.partition_indices = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case APP_NAME: + if (value == null) { + unsetApp_name(); + } else { + setApp_name((java.lang.String)value); + } + break; + + case PARTITION_INDICES: + if (value == null) { + unsetPartition_indices(); + } else { + setPartition_indices((java.util.List)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case APP_NAME: + return getApp_name(); + + case PARTITION_INDICES: + return getPartition_indices(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case APP_NAME: + return isSetApp_name(); + case PARTITION_INDICES: + return isSetPartition_indices(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof query_cfg_request) + return this.equals((query_cfg_request)that); + return false; + } + + public boolean equals(query_cfg_request that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_app_name = true && this.isSetApp_name(); + boolean that_present_app_name = true && that.isSetApp_name(); + if (this_present_app_name || that_present_app_name) { + if (!(this_present_app_name && that_present_app_name)) + return false; + if (!this.app_name.equals(that.app_name)) + return false; + } + + boolean this_present_partition_indices = true && this.isSetPartition_indices(); + boolean that_present_partition_indices = true && that.isSetPartition_indices(); + if (this_present_partition_indices || that_present_partition_indices) { + if (!(this_present_partition_indices && that_present_partition_indices)) + return false; + if (!this.partition_indices.equals(that.partition_indices)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetApp_name()) ? 131071 : 524287); + if (isSetApp_name()) + hashCode = hashCode * 8191 + app_name.hashCode(); + + hashCode = hashCode * 8191 + ((isSetPartition_indices()) ? 131071 : 524287); + if (isSetPartition_indices()) + hashCode = hashCode * 8191 + partition_indices.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(query_cfg_request other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetApp_name()).compareTo(other.isSetApp_name()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetApp_name()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.app_name, other.app_name); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPartition_indices()).compareTo(other.isSetPartition_indices()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPartition_indices()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.partition_indices, other.partition_indices); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("query_cfg_request("); + boolean first = true; + + sb.append("app_name:"); + if (this.app_name == null) { + sb.append("null"); + } else { + sb.append(this.app_name); + } + first = false; + if (!first) sb.append(", "); + sb.append("partition_indices:"); + if (this.partition_indices == null) { + sb.append("null"); + } else { + sb.append(this.partition_indices); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class query_cfg_requestStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public query_cfg_requestStandardScheme getScheme() { + return new query_cfg_requestStandardScheme(); + } + } + + private static class query_cfg_requestStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, query_cfg_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // APP_NAME + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRING) { + struct.app_name = iprot.readString(); + struct.setApp_nameIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // PARTITION_INDICES + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list16 = iprot.readListBegin(); + struct.partition_indices = new java.util.ArrayList(_list16.size); + int _elem17; + for (int _i18 = 0; _i18 < _list16.size; ++_i18) + { + _elem17 = iprot.readI32(); + struct.partition_indices.add(_elem17); + } + iprot.readListEnd(); + } + struct.setPartition_indicesIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, query_cfg_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.app_name != null) { + oprot.writeFieldBegin(APP_NAME_FIELD_DESC); + oprot.writeString(struct.app_name); + oprot.writeFieldEnd(); + } + if (struct.partition_indices != null) { + oprot.writeFieldBegin(PARTITION_INDICES_FIELD_DESC); + { + oprot.writeListBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, struct.partition_indices.size())); + for (int _iter19 : struct.partition_indices) + { + oprot.writeI32(_iter19); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class query_cfg_requestTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public query_cfg_requestTupleScheme getScheme() { + return new query_cfg_requestTupleScheme(); + } + } + + private static class query_cfg_requestTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, query_cfg_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetApp_name()) { + optionals.set(0); + } + if (struct.isSetPartition_indices()) { + optionals.set(1); + } + oprot.writeBitSet(optionals, 2); + if (struct.isSetApp_name()) { + oprot.writeString(struct.app_name); + } + if (struct.isSetPartition_indices()) { + { + oprot.writeI32(struct.partition_indices.size()); + for (int _iter20 : struct.partition_indices) + { + oprot.writeI32(_iter20); + } + } + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, query_cfg_request struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(2); + if (incoming.get(0)) { + struct.app_name = iprot.readString(); + struct.setApp_nameIsSet(true); + } + if (incoming.get(1)) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list21 = new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, iprot.readI32()); + struct.partition_indices = new java.util.ArrayList(_list21.size); + int _elem22; + for (int _i23 = 0; _i23 < _list21.size; ++_i23) + { + _elem22 = iprot.readI32(); + struct.partition_indices.add(_elem22); + } + } + struct.setPartition_indicesIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/replication/query_cfg_response.java b/src/main/java/com/xiaomi/infra/pegasus/replication/query_cfg_response.java new file mode 100644 index 00000000..463b7a6c --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/replication/query_cfg_response.java @@ -0,0 +1,830 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +/** + * Autogenerated by Thrift Compiler (0.11.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +package com.xiaomi.infra.pegasus.replication; + +@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"}) +@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.11.0)", date = "2018-03-12") +public class query_cfg_response implements com.xiaomi.infra.pegasus.thrift.TBase, java.io.Serializable, Cloneable, Comparable { + private static final com.xiaomi.infra.pegasus.thrift.protocol.TStruct STRUCT_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TStruct("query_cfg_response"); + + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField ERR_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("err", com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, (short)1); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField APP_ID_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("app_id", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)2); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PARTITION_COUNT_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("partition_count", com.xiaomi.infra.pegasus.thrift.protocol.TType.I32, (short)3); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField IS_STATEFUL_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("is_stateful", com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL, (short)4); + private static final com.xiaomi.infra.pegasus.thrift.protocol.TField PARTITIONS_FIELD_DESC = new com.xiaomi.infra.pegasus.thrift.protocol.TField("partitions", com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, (short)5); + + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new query_cfg_responseStandardSchemeFactory(); + private static final com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new query_cfg_responseTupleSchemeFactory(); + + public com.xiaomi.infra.pegasus.base.error_code err; // required + public int app_id; // required + public int partition_count; // required + public boolean is_stateful; // required + public java.util.List partitions; // required + + /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ + public enum _Fields implements com.xiaomi.infra.pegasus.thrift.TFieldIdEnum { + ERR((short)1, "err"), + APP_ID((short)2, "app_id"), + PARTITION_COUNT((short)3, "partition_count"), + IS_STATEFUL((short)4, "is_stateful"), + PARTITIONS((short)5, "partitions"); + + private static final java.util.Map byName = new java.util.HashMap(); + + static { + for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) { + byName.put(field.getFieldName(), field); + } + } + + /** + * Find the _Fields constant that matches fieldId, or null if its not found. + */ + public static _Fields findByThriftId(int fieldId) { + switch(fieldId) { + case 1: // ERR + return ERR; + case 2: // APP_ID + return APP_ID; + case 3: // PARTITION_COUNT + return PARTITION_COUNT; + case 4: // IS_STATEFUL + return IS_STATEFUL; + case 5: // PARTITIONS + return PARTITIONS; + default: + return null; + } + } + + /** + * Find the _Fields constant that matches fieldId, throwing an exception + * if it is not found. + */ + public static _Fields findByThriftIdOrThrow(int fieldId) { + _Fields fields = findByThriftId(fieldId); + if (fields == null) throw new java.lang.IllegalArgumentException("Field " + fieldId + " doesn't exist!"); + return fields; + } + + /** + * Find the _Fields constant that matches name, or null if its not found. + */ + public static _Fields findByName(java.lang.String name) { + return byName.get(name); + } + + private final short _thriftId; + private final java.lang.String _fieldName; + + _Fields(short thriftId, java.lang.String fieldName) { + _thriftId = thriftId; + _fieldName = fieldName; + } + + public short getThriftFieldId() { + return _thriftId; + } + + public java.lang.String getFieldName() { + return _fieldName; + } + } + + // isset id assignments + private static final int __APP_ID_ISSET_ID = 0; + private static final int __PARTITION_COUNT_ISSET_ID = 1; + private static final int __IS_STATEFUL_ISSET_ID = 2; + private byte __isset_bitfield = 0; + public static final java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> metaDataMap; + static { + java.util.Map<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData>(_Fields.class); + tmpMap.put(_Fields.ERR, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("err", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, com.xiaomi.infra.pegasus.base.error_code.class))); + tmpMap.put(_Fields.APP_ID, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("app_id", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.PARTITION_COUNT, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("partition_count", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.I32))); + tmpMap.put(_Fields.IS_STATEFUL, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("is_stateful", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.FieldValueMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL))); + tmpMap.put(_Fields.PARTITIONS, new com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData("partitions", com.xiaomi.infra.pegasus.thrift.TFieldRequirementType.DEFAULT, + new com.xiaomi.infra.pegasus.thrift.meta_data.ListMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST, + new com.xiaomi.infra.pegasus.thrift.meta_data.StructMetaData(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, partition_configuration.class)))); + metaDataMap = java.util.Collections.unmodifiableMap(tmpMap); + com.xiaomi.infra.pegasus.thrift.meta_data.FieldMetaData.addStructMetaDataMap(query_cfg_response.class, metaDataMap); + } + + public query_cfg_response() { + } + + public query_cfg_response( + com.xiaomi.infra.pegasus.base.error_code err, + int app_id, + int partition_count, + boolean is_stateful, + java.util.List partitions) + { + this(); + this.err = err; + this.app_id = app_id; + setApp_idIsSet(true); + this.partition_count = partition_count; + setPartition_countIsSet(true); + this.is_stateful = is_stateful; + setIs_statefulIsSet(true); + this.partitions = partitions; + } + + /** + * Performs a deep copy on other. + */ + public query_cfg_response(query_cfg_response other) { + __isset_bitfield = other.__isset_bitfield; + if (other.isSetErr()) { + this.err = new com.xiaomi.infra.pegasus.base.error_code(other.err); + } + this.app_id = other.app_id; + this.partition_count = other.partition_count; + this.is_stateful = other.is_stateful; + if (other.isSetPartitions()) { + java.util.List __this__partitions = new java.util.ArrayList(other.partitions.size()); + for (partition_configuration other_element : other.partitions) { + __this__partitions.add(new partition_configuration(other_element)); + } + this.partitions = __this__partitions; + } + } + + public query_cfg_response deepCopy() { + return new query_cfg_response(this); + } + + @Override + public void clear() { + this.err = null; + setApp_idIsSet(false); + this.app_id = 0; + setPartition_countIsSet(false); + this.partition_count = 0; + setIs_statefulIsSet(false); + this.is_stateful = false; + this.partitions = null; + } + + public com.xiaomi.infra.pegasus.base.error_code getErr() { + return this.err; + } + + public query_cfg_response setErr(com.xiaomi.infra.pegasus.base.error_code err) { + this.err = err; + return this; + } + + public void unsetErr() { + this.err = null; + } + + /** Returns true if field err is set (has been assigned a value) and false otherwise */ + public boolean isSetErr() { + return this.err != null; + } + + public void setErrIsSet(boolean value) { + if (!value) { + this.err = null; + } + } + + public int getApp_id() { + return this.app_id; + } + + public query_cfg_response setApp_id(int app_id) { + this.app_id = app_id; + setApp_idIsSet(true); + return this; + } + + public void unsetApp_id() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + /** Returns true if field app_id is set (has been assigned a value) and false otherwise */ + public boolean isSetApp_id() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __APP_ID_ISSET_ID); + } + + public void setApp_idIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __APP_ID_ISSET_ID, value); + } + + public int getPartition_count() { + return this.partition_count; + } + + public query_cfg_response setPartition_count(int partition_count) { + this.partition_count = partition_count; + setPartition_countIsSet(true); + return this; + } + + public void unsetPartition_count() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __PARTITION_COUNT_ISSET_ID); + } + + /** Returns true if field partition_count is set (has been assigned a value) and false otherwise */ + public boolean isSetPartition_count() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __PARTITION_COUNT_ISSET_ID); + } + + public void setPartition_countIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __PARTITION_COUNT_ISSET_ID, value); + } + + public boolean isIs_stateful() { + return this.is_stateful; + } + + public query_cfg_response setIs_stateful(boolean is_stateful) { + this.is_stateful = is_stateful; + setIs_statefulIsSet(true); + return this; + } + + public void unsetIs_stateful() { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.clearBit(__isset_bitfield, __IS_STATEFUL_ISSET_ID); + } + + /** Returns true if field is_stateful is set (has been assigned a value) and false otherwise */ + public boolean isSetIs_stateful() { + return com.xiaomi.infra.pegasus.thrift.EncodingUtils.testBit(__isset_bitfield, __IS_STATEFUL_ISSET_ID); + } + + public void setIs_statefulIsSet(boolean value) { + __isset_bitfield = com.xiaomi.infra.pegasus.thrift.EncodingUtils.setBit(__isset_bitfield, __IS_STATEFUL_ISSET_ID, value); + } + + public int getPartitionsSize() { + return (this.partitions == null) ? 0 : this.partitions.size(); + } + + public java.util.Iterator getPartitionsIterator() { + return (this.partitions == null) ? null : this.partitions.iterator(); + } + + public void addToPartitions(partition_configuration elem) { + if (this.partitions == null) { + this.partitions = new java.util.ArrayList(); + } + this.partitions.add(elem); + } + + public java.util.List getPartitions() { + return this.partitions; + } + + public query_cfg_response setPartitions(java.util.List partitions) { + this.partitions = partitions; + return this; + } + + public void unsetPartitions() { + this.partitions = null; + } + + /** Returns true if field partitions is set (has been assigned a value) and false otherwise */ + public boolean isSetPartitions() { + return this.partitions != null; + } + + public void setPartitionsIsSet(boolean value) { + if (!value) { + this.partitions = null; + } + } + + public void setFieldValue(_Fields field, java.lang.Object value) { + switch (field) { + case ERR: + if (value == null) { + unsetErr(); + } else { + setErr((com.xiaomi.infra.pegasus.base.error_code)value); + } + break; + + case APP_ID: + if (value == null) { + unsetApp_id(); + } else { + setApp_id((java.lang.Integer)value); + } + break; + + case PARTITION_COUNT: + if (value == null) { + unsetPartition_count(); + } else { + setPartition_count((java.lang.Integer)value); + } + break; + + case IS_STATEFUL: + if (value == null) { + unsetIs_stateful(); + } else { + setIs_stateful((java.lang.Boolean)value); + } + break; + + case PARTITIONS: + if (value == null) { + unsetPartitions(); + } else { + setPartitions((java.util.List)value); + } + break; + + } + } + + public java.lang.Object getFieldValue(_Fields field) { + switch (field) { + case ERR: + return getErr(); + + case APP_ID: + return getApp_id(); + + case PARTITION_COUNT: + return getPartition_count(); + + case IS_STATEFUL: + return isIs_stateful(); + + case PARTITIONS: + return getPartitions(); + + } + throw new java.lang.IllegalStateException(); + } + + /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ + public boolean isSet(_Fields field) { + if (field == null) { + throw new java.lang.IllegalArgumentException(); + } + + switch (field) { + case ERR: + return isSetErr(); + case APP_ID: + return isSetApp_id(); + case PARTITION_COUNT: + return isSetPartition_count(); + case IS_STATEFUL: + return isSetIs_stateful(); + case PARTITIONS: + return isSetPartitions(); + } + throw new java.lang.IllegalStateException(); + } + + @Override + public boolean equals(java.lang.Object that) { + if (that == null) + return false; + if (that instanceof query_cfg_response) + return this.equals((query_cfg_response)that); + return false; + } + + public boolean equals(query_cfg_response that) { + if (that == null) + return false; + if (this == that) + return true; + + boolean this_present_err = true && this.isSetErr(); + boolean that_present_err = true && that.isSetErr(); + if (this_present_err || that_present_err) { + if (!(this_present_err && that_present_err)) + return false; + if (!this.err.equals(that.err)) + return false; + } + + boolean this_present_app_id = true; + boolean that_present_app_id = true; + if (this_present_app_id || that_present_app_id) { + if (!(this_present_app_id && that_present_app_id)) + return false; + if (this.app_id != that.app_id) + return false; + } + + boolean this_present_partition_count = true; + boolean that_present_partition_count = true; + if (this_present_partition_count || that_present_partition_count) { + if (!(this_present_partition_count && that_present_partition_count)) + return false; + if (this.partition_count != that.partition_count) + return false; + } + + boolean this_present_is_stateful = true; + boolean that_present_is_stateful = true; + if (this_present_is_stateful || that_present_is_stateful) { + if (!(this_present_is_stateful && that_present_is_stateful)) + return false; + if (this.is_stateful != that.is_stateful) + return false; + } + + boolean this_present_partitions = true && this.isSetPartitions(); + boolean that_present_partitions = true && that.isSetPartitions(); + if (this_present_partitions || that_present_partitions) { + if (!(this_present_partitions && that_present_partitions)) + return false; + if (!this.partitions.equals(that.partitions)) + return false; + } + + return true; + } + + @Override + public int hashCode() { + int hashCode = 1; + + hashCode = hashCode * 8191 + ((isSetErr()) ? 131071 : 524287); + if (isSetErr()) + hashCode = hashCode * 8191 + err.hashCode(); + + hashCode = hashCode * 8191 + app_id; + + hashCode = hashCode * 8191 + partition_count; + + hashCode = hashCode * 8191 + ((is_stateful) ? 131071 : 524287); + + hashCode = hashCode * 8191 + ((isSetPartitions()) ? 131071 : 524287); + if (isSetPartitions()) + hashCode = hashCode * 8191 + partitions.hashCode(); + + return hashCode; + } + + @Override + public int compareTo(query_cfg_response other) { + if (!getClass().equals(other.getClass())) { + return getClass().getName().compareTo(other.getClass().getName()); + } + + int lastComparison = 0; + + lastComparison = java.lang.Boolean.valueOf(isSetErr()).compareTo(other.isSetErr()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetErr()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.err, other.err); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetApp_id()).compareTo(other.isSetApp_id()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetApp_id()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.app_id, other.app_id); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPartition_count()).compareTo(other.isSetPartition_count()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPartition_count()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.partition_count, other.partition_count); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetIs_stateful()).compareTo(other.isSetIs_stateful()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetIs_stateful()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.is_stateful, other.is_stateful); + if (lastComparison != 0) { + return lastComparison; + } + } + lastComparison = java.lang.Boolean.valueOf(isSetPartitions()).compareTo(other.isSetPartitions()); + if (lastComparison != 0) { + return lastComparison; + } + if (isSetPartitions()) { + lastComparison = com.xiaomi.infra.pegasus.thrift.TBaseHelper.compareTo(this.partitions, other.partitions); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public _Fields fieldForId(int fieldId) { + return _Fields.findByThriftId(fieldId); + } + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(iprot).read(iprot, this); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot) throws com.xiaomi.infra.pegasus.thrift.TException { + scheme(oprot).write(oprot, this); + } + + @Override + public java.lang.String toString() { + java.lang.StringBuilder sb = new java.lang.StringBuilder("query_cfg_response("); + boolean first = true; + + sb.append("err:"); + if (this.err == null) { + sb.append("null"); + } else { + sb.append(this.err); + } + first = false; + if (!first) sb.append(", "); + sb.append("app_id:"); + sb.append(this.app_id); + first = false; + if (!first) sb.append(", "); + sb.append("partition_count:"); + sb.append(this.partition_count); + first = false; + if (!first) sb.append(", "); + sb.append("is_stateful:"); + sb.append(this.is_stateful); + first = false; + if (!first) sb.append(", "); + sb.append("partitions:"); + if (this.partitions == null) { + sb.append("null"); + } else { + sb.append(this.partitions); + } + first = false; + sb.append(")"); + return sb.toString(); + } + + public void validate() throws com.xiaomi.infra.pegasus.thrift.TException { + // check for required fields + // check for sub-struct validity + if (err != null) { + err.validate(); + } + } + + private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { + try { + write(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(out))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException { + try { + // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. + __isset_bitfield = 0; + read(new com.xiaomi.infra.pegasus.thrift.protocol.TCompactProtocol(new com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport(in))); + } catch (com.xiaomi.infra.pegasus.thrift.TException te) { + throw new java.io.IOException(te); + } + } + + private static class query_cfg_responseStandardSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public query_cfg_responseStandardScheme getScheme() { + return new query_cfg_responseStandardScheme(); + } + } + + private static class query_cfg_responseStandardScheme extends com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iprot, query_cfg_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TField schemeField; + iprot.readStructBegin(); + while (true) + { + schemeField = iprot.readFieldBegin(); + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STOP) { + break; + } + switch (schemeField.id) { + case 1: // ERR + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT) { + struct.err = new com.xiaomi.infra.pegasus.base.error_code(); + struct.err.read(iprot); + struct.setErrIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 2: // APP_ID + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 3: // PARTITION_COUNT + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.I32) { + struct.partition_count = iprot.readI32(); + struct.setPartition_countIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 4: // IS_STATEFUL + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.BOOL) { + struct.is_stateful = iprot.readBool(); + struct.setIs_statefulIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + case 5: // PARTITIONS + if (schemeField.type == com.xiaomi.infra.pegasus.thrift.protocol.TType.LIST) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list24 = iprot.readListBegin(); + struct.partitions = new java.util.ArrayList(_list24.size); + partition_configuration _elem25; + for (int _i26 = 0; _i26 < _list24.size; ++_i26) + { + _elem25 = new partition_configuration(); + _elem25.read(iprot); + struct.partitions.add(_elem25); + } + iprot.readListEnd(); + } + struct.setPartitionsIsSet(true); + } else { + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + break; + default: + com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + + // check for required fields of primitive type, which can't be checked in the validate method + struct.validate(); + } + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, query_cfg_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + struct.validate(); + + oprot.writeStructBegin(STRUCT_DESC); + if (struct.err != null) { + oprot.writeFieldBegin(ERR_FIELD_DESC); + struct.err.write(oprot); + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(APP_ID_FIELD_DESC); + oprot.writeI32(struct.app_id); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(PARTITION_COUNT_FIELD_DESC); + oprot.writeI32(struct.partition_count); + oprot.writeFieldEnd(); + oprot.writeFieldBegin(IS_STATEFUL_FIELD_DESC); + oprot.writeBool(struct.is_stateful); + oprot.writeFieldEnd(); + if (struct.partitions != null) { + oprot.writeFieldBegin(PARTITIONS_FIELD_DESC); + { + oprot.writeListBegin(new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, struct.partitions.size())); + for (partition_configuration _iter27 : struct.partitions) + { + _iter27.write(oprot); + } + oprot.writeListEnd(); + } + oprot.writeFieldEnd(); + } + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + + } + + private static class query_cfg_responseTupleSchemeFactory implements com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory { + public query_cfg_responseTupleScheme getScheme() { + return new query_cfg_responseTupleScheme(); + } + } + + private static class query_cfg_responseTupleScheme extends com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme { + + @Override + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, query_cfg_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol oprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet optionals = new java.util.BitSet(); + if (struct.isSetErr()) { + optionals.set(0); + } + if (struct.isSetApp_id()) { + optionals.set(1); + } + if (struct.isSetPartition_count()) { + optionals.set(2); + } + if (struct.isSetIs_stateful()) { + optionals.set(3); + } + if (struct.isSetPartitions()) { + optionals.set(4); + } + oprot.writeBitSet(optionals, 5); + if (struct.isSetErr()) { + struct.err.write(oprot); + } + if (struct.isSetApp_id()) { + oprot.writeI32(struct.app_id); + } + if (struct.isSetPartition_count()) { + oprot.writeI32(struct.partition_count); + } + if (struct.isSetIs_stateful()) { + oprot.writeBool(struct.is_stateful); + } + if (struct.isSetPartitions()) { + { + oprot.writeI32(struct.partitions.size()); + for (partition_configuration _iter28 : struct.partitions) + { + _iter28.write(oprot); + } + } + } + } + + @Override + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol prot, query_cfg_response struct) throws com.xiaomi.infra.pegasus.thrift.TException { + com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol iprot = (com.xiaomi.infra.pegasus.thrift.protocol.TTupleProtocol) prot; + java.util.BitSet incoming = iprot.readBitSet(5); + if (incoming.get(0)) { + struct.err = new com.xiaomi.infra.pegasus.base.error_code(); + struct.err.read(iprot); + struct.setErrIsSet(true); + } + if (incoming.get(1)) { + struct.app_id = iprot.readI32(); + struct.setApp_idIsSet(true); + } + if (incoming.get(2)) { + struct.partition_count = iprot.readI32(); + struct.setPartition_countIsSet(true); + } + if (incoming.get(3)) { + struct.is_stateful = iprot.readBool(); + struct.setIs_statefulIsSet(true); + } + if (incoming.get(4)) { + { + com.xiaomi.infra.pegasus.thrift.protocol.TList _list29 = new com.xiaomi.infra.pegasus.thrift.protocol.TList(com.xiaomi.infra.pegasus.thrift.protocol.TType.STRUCT, iprot.readI32()); + struct.partitions = new java.util.ArrayList(_list29.size); + partition_configuration _elem30; + for (int _i31 = 0; _i31 < _list29.size; ++_i31) + { + _elem30 = new partition_configuration(); + _elem30.read(iprot); + struct.partitions.add(_elem30); + } + } + struct.setPartitionsIsSet(true); + } + } + } + + private static S scheme(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol proto) { + return (com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/Cluster.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/Cluster.java new file mode 100644 index 00000000..76080c2c --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/Cluster.java @@ -0,0 +1,65 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.rpc.async.ClusterManager; +import java.util.Properties; + +public abstract class Cluster { + public static final int SOCK_TIMEOUT = 1000; + public static final int QUERY_META_TIMEOUT = 1000; + + public static final String PEGASUS_META_SERVERS_KEY = "meta_servers"; + + public static final String PEGASUS_OPERATION_TIMEOUT_KEY = "operation_timeout"; + public static final String PEGASUS_OPERATION_TIMEOUT_DEF = "1000"; + + public static final String PEGASUS_ASYNC_WORKERS_KEY = "async_workers"; + public static final String PEGASUS_ASYNC_WORKERS_DEF = "4"; + + public static final String PEGASUS_ENABLE_PERF_COUNTER_KEY = "enable_perf_counter"; + public static final String PEGASUS_ENABLE_PERF_COUNTER_VALUE = "false"; + + public static final String PEGASUS_PERF_COUNTER_TAGS_KEY = "perf_counter_tags"; + public static final String PEGASUS_PERF_COUNTER_TAGS_DEF = ""; + + public static final String PEGASUS_PUSH_COUNTER_INTERVAL_SECS_KEY = "push_counter_interval_secs"; + public static final String PEGASUS_PUSH_COUNTER_INTERVAL_SECS_DEF = "60"; + + public static Cluster createCluster(Properties config) throws IllegalArgumentException { + int operatorTimeout = Integer.parseInt(config.getProperty( + PEGASUS_OPERATION_TIMEOUT_KEY, PEGASUS_OPERATION_TIMEOUT_DEF)); + String metaList = config.getProperty(PEGASUS_META_SERVERS_KEY); + if (metaList == null) { + throw new IllegalArgumentException("no property set: " + PEGASUS_META_SERVERS_KEY); + } + metaList = metaList.trim(); + if (metaList.isEmpty()) { + throw new IllegalArgumentException("invalid property: " + PEGASUS_META_SERVERS_KEY); + } + String[] address = metaList.split(","); + + int asyncWorkers = Integer.parseInt(config.getProperty( + PEGASUS_ASYNC_WORKERS_KEY, PEGASUS_ASYNC_WORKERS_DEF)); + boolean enablePerfCounter = Boolean.parseBoolean(config.getProperty( + PEGASUS_ENABLE_PERF_COUNTER_KEY, PEGASUS_ENABLE_PERF_COUNTER_VALUE)); + String perfCounterTags = enablePerfCounter ? config.getProperty( + PEGASUS_PERF_COUNTER_TAGS_KEY, PEGASUS_PERF_COUNTER_TAGS_DEF) : null; + int pushIntervalSecs = Integer.parseInt(config.getProperty( + PEGASUS_PUSH_COUNTER_INTERVAL_SECS_KEY, + PEGASUS_PUSH_COUNTER_INTERVAL_SECS_DEF + )); + return new ClusterManager( + operatorTimeout, + asyncWorkers, + enablePerfCounter, + perfCounterTags, + pushIntervalSecs, + address); + } + + public abstract Table openTable(String name, KeyHasher function) throws ReplicationException, TException; + public abstract void close(); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/KeyHasher.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/KeyHasher.java new file mode 100644 index 00000000..d0295432 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/KeyHasher.java @@ -0,0 +1,20 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc; + +import com.xiaomi.infra.pegasus.tools.tools; + +/** + * Created by weijiesun on 16-11-11. + */ +public interface KeyHasher { + KeyHasher DEFAULT = new KeyHasher() { + @Override + public long hash(byte[] key) { + return tools.dsn_crc64(key); + } + }; + + long hash(byte[] key); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/ReplicationException.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/ReplicationException.java new file mode 100644 index 00000000..74fa0b3b --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/ReplicationException.java @@ -0,0 +1,35 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc; + +import com.xiaomi.infra.pegasus.base.error_code; + +public class ReplicationException extends Exception { + private static final long serialVersionUID = 4186015142427786503L; + + public error_code.error_types err_type; + + public ReplicationException() { + super(); + } + + public ReplicationException(error_code.error_types t) { + super(t.name()); + err_type = t; + } + + public ReplicationException(error_code.error_types t, String message) { + super(t.name()+": "+message); + err_type = t; + } + + public ReplicationException(Throwable cause) { + super(cause); + err_type = error_code.error_types.ERR_UNKNOWN; + } + + public ReplicationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/Table.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/Table.java new file mode 100644 index 00000000..5a85ab5d --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/Table.java @@ -0,0 +1,63 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc; + +import com.xiaomi.infra.pegasus.base.gpid; +import com.xiaomi.infra.pegasus.operator.*; +import io.netty.util.concurrent.DefaultPromise; +import io.netty.util.concurrent.EventExecutor; + +public abstract class Table { + public interface ClientOPCallback { + public void onCompletion(client_operator clientOP) throws Throwable; + } + + public final gpid getGpid(byte[] data) { + long hash_value = hasher_.hash(data); + com.xiaomi.infra.pegasus.base.gpid result = new com.xiaomi.infra.pegasus.base.gpid(appID_, -1); + result.set_pidx((int) remainder_unsigned(hash_value, getPartitionCount())); + return result; + } + + public final gpid getHashKeyGpid(byte[] data) { + long hash_value = KeyHasher.DEFAULT.hash(data); + com.xiaomi.infra.pegasus.base.gpid result = new com.xiaomi.infra.pegasus.base.gpid(appID_, -1); + result.set_pidx((int) remainder_unsigned(hash_value, getPartitionCount())); + return result; + } + + public final gpid[] getAllGpid() { + int count = getPartitionCount(); + com.xiaomi.infra.pegasus.base.gpid[] ret = new com.xiaomi.infra.pegasus.base.gpid[count]; + for (int i = 0; i < count; i++) { + ret[i] = new com.xiaomi.infra.pegasus.base.gpid(appID_, i); + } + return ret; + } + + public final String getTableName() { return tableName_; } + + public final int getAppID() { return appID_; } + + public final DefaultPromise newPromise() { + return new DefaultPromise(getExecutor()); + } + public abstract int getDefaultTimeout(); + public abstract int getPartitionCount(); + public abstract void operate(client_operator op, int timeoutMs) throws ReplicationException; + public abstract void asyncOperate(client_operator op, ClientOPCallback callback, int timeoutMs); + public abstract EventExecutor getExecutor(); + + protected String tableName_; + protected int appID_; + protected KeyHasher hasher_; + + public static long remainder_unsigned(long dividend, long divisor) { + if (dividend > 0) { + return dividend % divisor; + } + long reminder = (dividend >>> 1) % divisor * 2 + (dividend & 1); + return reminder >= 0 && reminder < divisor ? reminder : reminder - divisor; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/ThriftHeader.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/ThriftHeader.java new file mode 100644 index 00000000..d55066c0 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/ThriftHeader.java @@ -0,0 +1,37 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc; + +import java.nio.ByteBuffer; + +public class ThriftHeader { + public static final int HEADER_LENGTH = 48; + public static final byte[] HEADER_TYPE = {'T','H','F','T'}; + public int hdr_version = 0; + public int header_length; + public int header_crc32 = 0; + public int body_length; + public int body_crc32 = 0; + public int app_id; + public int partition_index; + public int client_timeout = 0; + public int thread_hash; + public long partition_hash; + + public byte[] toByteArray() { + ByteBuffer bf = ByteBuffer.allocate(HEADER_LENGTH); + bf.put(HEADER_TYPE); + bf.putInt(hdr_version); + bf.putInt(header_length); + bf.putInt(header_crc32); + bf.putInt(body_length); + bf.putInt(body_crc32); + bf.putInt(app_id); + bf.putInt(partition_index); + bf.putInt(client_timeout); + bf.putInt(thread_hash); + bf.putLong(partition_hash); + return bf.array(); + } +}; diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ClientRequestRound.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ClientRequestRound.java new file mode 100644 index 00000000..69c54acf --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ClientRequestRound.java @@ -0,0 +1,63 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc.async; + +import com.xiaomi.infra.pegasus.metrics.MetricsManager; +import com.xiaomi.infra.pegasus.rpc.Table; +import com.xiaomi.infra.pegasus.operator.client_operator; +import org.slf4j.Logger; + +/** + * Created by weijiesun on 16-11-25. + */ +public final class ClientRequestRound { + private static final Logger logger = org.slf4j.LoggerFactory.getLogger(TableHandler.class); + + client_operator operator; + Table.ClientOPCallback callback; + int timeoutMs; + + boolean enableCounter; + long createNanoTime; + long expireNanoTime; + /** + * Constructor. + * @param op + * @param enableCounter whether enable counter. + */ + public ClientRequestRound(client_operator op, + Table.ClientOPCallback cb, + boolean enableCounter, + int timeoutInMilliseconds) { + operator = op; + callback = cb; + timeoutMs = timeoutInMilliseconds; + + this.enableCounter = enableCounter; + createNanoTime = System.nanoTime(); + expireNanoTime = createNanoTime + timeoutMs * 1000000; + } + + public com.xiaomi.infra.pegasus.operator.client_operator getOperator() { + return operator; + } + public void setOperator(client_operator op) { + operator = op; + } + + public void thisRoundCompletion() { + try { + callback.onCompletion(operator); + } catch (Throwable ex) { + // The exception is generated by the user's callback logic, so we don't do much things on it + logger.debug("{} got exception", operator.toString(), ex); + } + + if (enableCounter) { + MetricsManager.updateCount(operator.getQPSCounter(), 1L); + MetricsManager.setHistogramValue(operator.getLatencyCounter(), + System.nanoTime() - createNanoTime); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ClusterManager.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ClusterManager.java new file mode 100644 index 00000000..665802c2 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ClusterManager.java @@ -0,0 +1,143 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc.async; + +import com.xiaomi.infra.pegasus.metrics.MetricsManager; +import com.xiaomi.infra.pegasus.rpc.Cluster; +import com.xiaomi.infra.pegasus.rpc.KeyHasher; +import com.xiaomi.infra.pegasus.rpc.ReplicationException; +import com.xiaomi.infra.pegasus.base.rpc_address; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.epoll.EpollEventLoopGroup; +import io.netty.channel.epoll.EpollSocketChannel; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.util.concurrent.EventExecutor; +import org.slf4j.Logger; + +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Created by sunweijie@xiaomi.com on 16-11-11. + */ +public class ClusterManager extends Cluster { + private int operationTimeout; + private int retryDelay; + private boolean enableCounter; + + private ConcurrentHashMap replicaSessions; + private EventLoopGroup metaGroup; // group used for handle meta logic + private EventLoopGroup replicaGroup; // group used for handle io with replica servers + private EventLoopGroup tableGroup; // group used for handle table logic + private MetaSession metaSession; + + private static final Logger logger; + private static final String osName; + private static final String Linux = "Linux"; + static { + logger = org.slf4j.LoggerFactory.getLogger(ClusterManager.class); + Properties p = System.getProperties(); + osName = p.getProperty("os.name"); + logger.info("operating system name: {}", osName); + } + + public ClusterManager( + int timeout, + int io_threads, + boolean enableCounter, + String perfCounterTags, + int pushIntervalSecs, + String[] address_list) throws IllegalArgumentException { + setTimeout(timeout); + this.enableCounter = enableCounter; + if (enableCounter) { + MetricsManager.detectHostAndInit(perfCounterTags, pushIntervalSecs); + } + + replicaSessions = new ConcurrentHashMap(); + replicaGroup = getEventLoopGroupInstance(io_threads); + metaGroup = getEventLoopGroupInstance(1); + tableGroup = getEventLoopGroupInstance(1); + + // the constructor of meta session is depend on the replicaSessions, + // so the replicaSessions should be initialized earlier + metaSession = new MetaSession(this, address_list, timeout, 10, metaGroup); + } + + public EventExecutor getExecutor(String name, int threadCount) { + return tableGroup.next(); + } + + public MetaSession getMetaSession() { + return metaSession; + } + + public ReplicaSession getReplicaSession(rpc_address address) { + if (address.isInvalid()) { + return null; + } + ReplicaSession ss = replicaSessions.get(address); + if (ss != null) + return ss; + synchronized (this) { + ss = replicaSessions.get(address); + if (ss != null) + return ss; + ss = new ReplicaSession(address, replicaGroup, Cluster.SOCK_TIMEOUT); + replicaSessions.put(address, ss); + return ss; + } + } + + public int getTimeout() { return operationTimeout; } + + public int getRetryDelay(int timeoutMs) { return (timeoutMs < 3 ? 1: timeoutMs/3); } + + public int getRetryDelay() { return retryDelay; } + + public boolean counterEnabled() { return enableCounter; } + + public void setTimeout(int t) { + operationTimeout = t; + // set retry delay as t/3. + retryDelay = (t < 3 ? 1 : t / 3); + } + + public static EventLoopGroup getEventLoopGroupInstance(int threadsCount) { + if (osName.equals(Linux)) { + logger.debug("create epolled eventloop group"); + return new EpollEventLoopGroup(threadsCount); + } + logger.debug("create nio eventloop group"); + return new NioEventLoopGroup(threadsCount); + } + + public static Class getSocketChannelClass() { + if (osName.equals(Linux)) { + logger.debug("create epolled Socket channel"); + return EpollSocketChannel.class; + } + logger.debug("create nio eventloop group"); + return NioSocketChannel.class; + } + + @Override + public TableHandler openTable(String name, KeyHasher h) throws ReplicationException { + return new TableHandler(this, name, h); + } + + @Override + public void close() { + if (enableCounter) { + MetricsManager.finish(); + } + metaGroup.shutdownGracefully(); + logger.info("close meta group"); + replicaGroup.shutdownGracefully(); + logger.info("close replica group"); + tableGroup.shutdownGracefully(); + logger.info("close table group"); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/async/MetaSession.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/MetaSession.java new file mode 100644 index 00000000..af68649a --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/MetaSession.java @@ -0,0 +1,177 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc.async; + +import com.xiaomi.infra.pegasus.base.error_code.error_types; +import com.xiaomi.infra.pegasus.base.rpc_address; +import com.xiaomi.infra.pegasus.operator.client_operator; +import com.xiaomi.infra.pegasus.operator.query_cfg_operator; +import io.netty.channel.EventLoopGroup; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + +/** + * Created by weijiesun on 17-9-13. + */ +public class MetaSession { + public MetaSession(ClusterManager manager, String addrList[], + int eachQueryTimeoutInMills, int defaultMaxQueryCount, EventLoopGroup g) throws IllegalArgumentException { + metaList = new ArrayList(); + for (String addr: addrList) { + rpc_address rpc_addr = new rpc_address(); + if (rpc_addr.fromString(addr)) { + logger.info("add {} as meta server", addr); + metaList.add(manager.getReplicaSession(rpc_addr)); + } + else { + logger.error("invalid address {}", addr); + } + } + if (metaList.isEmpty()) { + throw new IllegalArgumentException("can't find valid meta server address " + addrList.toString()); + } + curLeader = 0; + + this.eachQueryTimeoutInMills = eachQueryTimeoutInMills; + this.defaultMaxQueryCount = defaultMaxQueryCount; + this.group = g; + } + + static public final error_types getMetaServiceError(client_operator metaQueryOp) { + if (metaQueryOp.rpc_error.errno != error_types.ERR_OK) + return metaQueryOp.rpc_error.errno; + query_cfg_operator op = (query_cfg_operator) metaQueryOp; + return op.get_response().getErr().errno; + } + + public final void asyncQuery(client_operator op, Runnable callbackFunc, int maxQueryCount) { + if (maxQueryCount == 0) { + maxQueryCount = defaultMaxQueryCount; + } + MetaRequestRound round; + synchronized (this) { + round = new MetaRequestRound(op, callbackFunc, maxQueryCount, metaList.get(curLeader)); + } + asyncCall(round); + } + + public final void query(client_operator op, int maxQueryCount) { + FutureTask v = new FutureTask(new Callable() { + @Override + public Void call() throws Exception { + return null; + } + }); + asyncQuery(op, v, maxQueryCount); + while (true) { + try { + v.get(); + return; + } catch (InterruptedException e) { + logger.info("operation {} got interrupt exception: ", op.get_gpid().toString(), e); + } catch (ExecutionException e) { + logger.warn("operation {} got execution exception, just return: ", op.get_gpid().toString(), e); + return; + } + } + } + + private final void asyncCall(final MetaRequestRound round) { + round.lastSession.asyncSend(round.op, new Runnable() { + @Override + public void run() { + onFinishQueryMeta(round); + } + }, eachQueryTimeoutInMills); + } + + private final void onFinishQueryMeta(final MetaRequestRound round) { + client_operator op = round.op; + + boolean needDelay = false; + boolean needSwitchLeader = false; + + --round.maxQueryCount; + if (round.maxQueryCount == 0) { + round.callbackFunc.run(); + return; + } + + error_types metaError = error_types.ERR_UNKNOWN; + if (op.rpc_error.errno == error_types.ERR_OK) { + metaError = getMetaServiceError(op); + if (metaError == error_types.ERR_SERVICE_NOT_ACTIVE) { + needDelay = true; + needSwitchLeader = false; + } + else if (metaError == error_types.ERR_FORWARD_TO_OTHERS) { + needDelay = false; + needSwitchLeader = true; + } + else { + round.callbackFunc.run(); + return; + } + } + else if (op.rpc_error.errno == error_types.ERR_SESSION_RESET || op.rpc_error.errno == error_types.ERR_TIMEOUT) { + needDelay = true; + needSwitchLeader = true; + } + else { + logger.error("unknown error: {}", op.rpc_error.errno.toString()); + round.callbackFunc.run(); + return; + } + + logger.info("query meta got error, rpc({}), meta({}), connected leader({}), remain retry count({}), " + + "need switch leader({}), need delay({})", + op.rpc_error.errno.toString(), + metaError.toString(), + round.lastSession.name(), + round.maxQueryCount, + needSwitchLeader, + needDelay + ); + synchronized (this) { + if (needSwitchLeader && metaList.get(curLeader) == round.lastSession) { + curLeader = (curLeader + 1) % metaList.size(); + } + round.lastSession = metaList.get(curLeader); + } + + group.schedule(new Runnable() { + @Override + public void run() { + asyncCall(round); + } + }, needDelay ? 1 : 0, TimeUnit.SECONDS); + } + + private static final class MetaRequestRound { + public client_operator op; + public Runnable callbackFunc; + public int maxQueryCount; + public ReplicaSession lastSession; + + public MetaRequestRound(client_operator o, Runnable r, int q, ReplicaSession l) { + op = o; + callbackFunc = r; + maxQueryCount = q; + lastSession = l; + } + } + + private List metaList; + private int curLeader; + private int eachQueryTimeoutInMills; + private int defaultMaxQueryCount; + private EventLoopGroup group; + + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MetaSession.class); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ReplicaSession.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ReplicaSession.java new file mode 100644 index 00000000..1c1fa9f7 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ReplicaSession.java @@ -0,0 +1,282 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc.async; + +import com.xiaomi.infra.pegasus.base.error_code.error_types; + +import com.xiaomi.infra.pegasus.base.rpc_address; +import com.xiaomi.infra.pegasus.operator.client_operator; +import io.netty.channel.*; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.socket.SocketChannel; + +import org.slf4j.Logger; + +import java.net.UnknownHostException; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Created by weijiesun on 17-9-13. + */ +public class ReplicaSession { + public static class RequestEntry { + public int sequenceId; + public com.xiaomi.infra.pegasus.operator.client_operator op; + public Runnable callback; + public ScheduledFuture timeoutTask; + } + + public enum ConnState { + CONNECTED, + CONNECTING, + DISCONNECTED + } + + public ReplicaSession(rpc_address address, EventLoopGroup rpcGroup, int socketTimeout) { + this.address = address; + this.rpcGroup = rpcGroup; + + final ReplicaSession this_ = this; + boot = new Bootstrap(); + boot.group(rpcGroup).channel(ClusterManager.getSocketChannelClass()) + .option(ChannelOption.TCP_NODELAY, true) + .option(ChannelOption.SO_KEEPALIVE, true) + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, socketTimeout) + .handler(new ChannelInitializer() { + @Override + public void initChannel(SocketChannel ch) { + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast("ThriftEncoder", new ThriftFrameEncoder()); + pipeline.addLast("ThriftDecoder", new ThriftFrameDecoder(this_)); + pipeline.addLast("ClientHandler", new ReplicaSession.DefaultHandler()); + } + }); + } + + public int asyncSend(client_operator op, Runnable callbackFunc, long timeoutInMilliseconds) { + RequestEntry entry = new RequestEntry(); + entry.sequenceId = seqId.getAndIncrement(); + entry.op = op; + entry.callback = callbackFunc; + //NOTICE: must make sure the msg is put into the pendingResponse map BEFORE + //the timer task is scheduled. + pendingResponse.put(new Integer(entry.sequenceId), entry); + entry.timeoutTask = addTimer(entry.sequenceId, timeoutInMilliseconds); + + VolatileFields cache = fields; + if (cache.state == ConnState.CONNECTED) { + write(entry, cache); + } else { + boolean needConnect = false; + synchronized (pendingSend) { + cache = fields; + if (cache.state == ConnState.CONNECTED) { + write(entry, cache); + } else { + pendingSend.offer(entry); + if (cache.state == ConnState.DISCONNECTED) { + cache = new VolatileFields(); + cache.state = ConnState.CONNECTING; + fields = cache; + needConnect = true; + } + } + } + if (needConnect) { + doConnect(); + } + } + return entry.sequenceId; + } + + public RequestEntry getAndRemoveEntry(int seqID) { + return pendingResponse.remove(new Integer(seqID)); + } + + public final String name() { return address.toString(); } + + public final rpc_address getAddress() { return address; } + + private void doConnect() { + try { + boot.connect(address.get_ip(), address.get_port()).addListener( + new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + if (channelFuture.isSuccess()) { + logger.info("{}: start to async connect to target, wait channel to active", name()); + } else { + logger.warn("{}: try to connect to target failed: ", name(), channelFuture.cause()); + markSessionDisconnect(); + } + } + } + ); + } catch (UnknownHostException ex) { + logger.error("invalid address: {}", address.toString()); + assert false; + } + } + + private void markSessionConnected(Channel activeChannel) { + VolatileFields newCache = new VolatileFields(); + newCache.state = ConnState.CONNECTED; + newCache.nettyChannel = activeChannel; + + synchronized (pendingSend) { + while (!pendingSend.isEmpty()) { + RequestEntry e = pendingSend.poll(); + if (pendingResponse.get(new Integer(e.sequenceId)) != null) { + write(e, newCache); + } else { + logger.info("{}: {} is removed from pending, perhaps timeout", name(), e.sequenceId); + } + } + fields = newCache; + } + } + + private void markSessionDisconnect() { + VolatileFields cache = fields; + synchronized (pendingSend) { + if (cache.state != ConnState.DISCONNECTED) { + // NOTICE: + // 1. when a connection is reset, the timeout response + // is not answered in the order they query + // 2. It's likely that when the session is disconnecting + // but the caller of the api query/asyncQuery didn't notice + // this. In this case, we are relying on the timeout task. + while (!pendingSend.isEmpty()) { + RequestEntry e = pendingSend.poll(); + tryNotifyWithSequenceID(e.sequenceId, error_types.ERR_SESSION_RESET, false); + } + List l = new LinkedList(); + for (Map.Entry entry : pendingResponse.entrySet()) { + l.add(entry.getValue()); + } + for (RequestEntry e : l) { + tryNotifyWithSequenceID(e.sequenceId, error_types.ERR_SESSION_RESET, false); + } + + cache = new VolatileFields(); + cache.state = ConnState.DISCONNECTED; + cache.nettyChannel = null; + fields = cache; + } else { + logger.warn("{}: session is closed already", name()); + } + } + } + + private void tryNotifyWithSequenceID( + int seqID, + error_types errno, + boolean isTimeoutTask) { + logger.debug("{}: {} is notified with error {}, isTimeoutTask {}", + name(), seqID, errno.toString(), isTimeoutTask); + RequestEntry entry = pendingResponse.remove(new Integer(seqID)); + if (entry != null) { + if (!isTimeoutTask) + entry.timeoutTask.cancel(true); + entry.op.rpc_error.errno = errno; + entry.callback.run(); + } + else { + logger.warn("{}: {} is removed by others, current error {}, isTimeoutTask {}", + name(), seqID, errno.toString(), isTimeoutTask); + } + } + + private void write(final RequestEntry entry, VolatileFields cache) { + cache.nettyChannel.writeAndFlush(entry).addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture channelFuture) throws Exception { + //NOTICE: we never do the connection things, this should be the duty of + //ChannelHandler, we only notify the request + if (!channelFuture.isSuccess()) { + logger.info("{} write seqid {} failed: ", name(), entry.sequenceId, channelFuture.cause()); + tryNotifyWithSequenceID(entry.sequenceId, error_types.ERR_TIMEOUT, false); + } + } + }); + } + + private ScheduledFuture addTimer(final int seqID, long timeoutInMillseconds) { + return rpcGroup.schedule( + new Runnable() { + @Override + public void run() { + tryNotifyWithSequenceID(seqID, error_types.ERR_TIMEOUT, true); + } + }, + timeoutInMillseconds, + TimeUnit.MILLISECONDS + ); + } + + final class DefaultHandler extends SimpleChannelInboundHandler { + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + logger.warn("Channel {} for session {} is inactive", ctx.channel().toString(), name()); + markSessionDisconnect(); + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + logger.info("Channel {} for session {} is active", ctx.channel().toString(), name()); + markSessionConnected(ctx.channel()); + } + + @Override + public void channelRead0(ChannelHandlerContext ctx, final RequestEntry msg) { + logger.debug("{}: handle response with seqid({})", name(), msg.sequenceId); + if (msg.callback != null) { + msg.callback.run(); + } else { + logger.warn("{}: seqid({}) has no callback, just ignore the response", name(), msg.sequenceId); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + logger.warn("got exception in inbound handler {} for session {}: ", + ctx.channel().toString(), + name(), + cause); + ctx.close(); + } + } + + // for test + ConnState getState() { + return fields.state; + } + + final private ConcurrentHashMap pendingResponse = new ConcurrentHashMap(); + final private AtomicInteger seqId = new AtomicInteger(0); + + final private Queue pendingSend = new LinkedList(); + + private final static class VolatileFields { + public ConnState state = ConnState.DISCONNECTED; + public Channel nettyChannel = null; + } + private volatile VolatileFields fields = new VolatileFields(); + + private rpc_address address; + private Bootstrap boot; + private EventLoopGroup rpcGroup; + + private static final Logger logger = org.slf4j.LoggerFactory.getLogger(ReplicaSession.class); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/async/TByteBufTransport.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/TByteBufTransport.java new file mode 100644 index 00000000..9f083004 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/TByteBufTransport.java @@ -0,0 +1,50 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc.async; + +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * Created by sunweijie@xiaomi.com on 16-11-9. + */ +public class TByteBufTransport extends TTransport { + private io.netty.buffer.ByteBuf buffer_; + + public TByteBufTransport(io.netty.buffer.ByteBuf b) { + buffer_ = b; + } + + public boolean isOpen() { + return true; + } + + public void open() { + } + + public void close() { + } + + public int read(byte[] buf, int off, int len) { + if (buffer_.readableBytes() < len) + len = buffer_.readableBytes(); + buffer_.readBytes(buf, off, len); + return len; + } + + public void write(byte[] buf, int off, int len) { + buffer_.writeBytes(buf, off, len); + } + + public String toString(String enc) { + return ""; + } + + public int length() { + return buffer_.readableBytes(); + } + + public byte[] getArray() { + return buffer_.array(); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/async/TableHandler.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/TableHandler.java new file mode 100644 index 00000000..bb57857e --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/TableHandler.java @@ -0,0 +1,371 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc.async; + +import com.xiaomi.infra.pegasus.rpc.KeyHasher; +import com.xiaomi.infra.pegasus.rpc.ReplicationException; +import com.xiaomi.infra.pegasus.base.error_code.error_types; +import com.xiaomi.infra.pegasus.base.gpid; +import com.xiaomi.infra.pegasus.base.rpc_address; +import com.xiaomi.infra.pegasus.operator.client_operator; +import com.xiaomi.infra.pegasus.operator.query_cfg_operator; +import com.xiaomi.infra.pegasus.replication.partition_configuration; +import com.xiaomi.infra.pegasus.replication.query_cfg_request; +import com.xiaomi.infra.pegasus.replication.query_cfg_response; +import com.xiaomi.infra.pegasus.rpc.Table; +import io.netty.util.concurrent.*; +import org.slf4j.Logger; + +import java.util.ArrayList; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Created by sunweijie@xiaomi.com on 16-11-11. + */ +public class TableHandler extends Table { + final static class ReplicaConfiguration { + public gpid pid = new gpid(); + public long ballot = 0; + public rpc_address primary = new rpc_address(); + public ReplicaSession session = null; + } + + final static class TableConfiguration { + ArrayList replicas; + long updateVersion; + } + + private static final Logger logger = org.slf4j.LoggerFactory.getLogger(TableHandler.class); + ClusterManager manager_; + EventExecutor executor_; // should be only one thread in this service + + AtomicReference< TableConfiguration > tableConfig_; + AtomicBoolean inQuerying_; + long lastQueryTime_; + + public TableHandler(ClusterManager mgr, String name, KeyHasher h) throws ReplicationException { + logger.debug("initialize table handler, table_name({})", name); + query_cfg_request req = new query_cfg_request(name, new ArrayList()); + query_cfg_operator op = new query_cfg_operator(new gpid(-1, -1), req); + + mgr.getMetaSession().query(op, 5); + + error_types err = MetaSession.getMetaServiceError(op); + if (err != error_types.ERR_OK) { + throw new ReplicationException(err); + } + + query_cfg_response resp = op.get_response(); + logger.info("query meta configuration succeed, table_name({}), app_id({}), partition_count({})", + name, resp.app_id, resp.partition_count); + + // superclass members + tableName_ = name; + appID_ = resp.app_id; + hasher_ = h; + + // members of this + manager_ = mgr; + executor_ = manager_.getExecutor(name, 1); + + tableConfig_ = new AtomicReference(null); + initTableConfiguration(resp); + + inQuerying_ = new AtomicBoolean(false); + lastQueryTime_ = 0; + } + + ReplicaConfiguration getReplicaConfig(int index) { + return tableConfig_.get().replicas.get(index); + } + + // update the table configuration & appID_ according to to queried response + void initTableConfiguration(query_cfg_response resp) { + TableConfiguration oldConfig = tableConfig_.get(); + TableConfiguration newConfig = new TableConfiguration(); + + newConfig.updateVersion = (oldConfig == null) ? 1: (oldConfig.updateVersion + 1); + newConfig.replicas = new ArrayList(resp.getPartition_count()); + + boolean noticeOld = false; + if (appID_ == resp.getApp_id() && + oldConfig != null && + oldConfig.replicas.size() == resp.getPartition_count() ) { + noticeOld = true; + logger.info("{}: take care and compare the old configuration from the new one when update config", tableName_); + } else { + logger.info("{}: skip the old config in current table", tableName_); + } + + for (int i=0; i!=resp.getPartition_count(); ++i) { + ReplicaConfiguration newReplicaConfig = new ReplicaConfiguration(); + newReplicaConfig.pid.set_app_id(resp.getApp_id()); + newReplicaConfig.pid.set_pidx(i); + + if (noticeOld) { + ReplicaConfiguration oldReplicaConfig = oldConfig.replicas.get(i); + newReplicaConfig.ballot = oldReplicaConfig.ballot; + newReplicaConfig.primary = oldReplicaConfig.primary; + newReplicaConfig.session = oldReplicaConfig.session; + } + newConfig.replicas.add(newReplicaConfig); + } + + for (partition_configuration pc: resp.getPartitions()) { + ReplicaConfiguration s = newConfig.replicas.get(pc.getPid().get_pidx()); + logger.info("{}: gpid({}) ballot: {} -> {}, primary: {} -> {}", + tableName_, + pc.getPid().toString(), + s.ballot, + pc.ballot, + s.primary, + pc.primary); + + s.ballot = pc.ballot; + s.primary = pc.primary; + if (pc.primary.isInvalid()) { + s.session = null; + } + else { + if (s.session == null || !s.session.getAddress().equals(pc.primary)) { + // reset to new primary + s.session = manager_.getReplicaSession(pc.primary); + } + } + } + + // there should only be one thread to do the table config update + appID_ = resp.getApp_id(); + tableConfig_.set(newConfig); + } + + void onUpdateConfiguration(final query_cfg_operator op) { + error_types err = MetaSession.getMetaServiceError(op); + if (err != error_types.ERR_OK) { + logger.warn("query meta for table({}) failed, error_code({})", tableName_, err.toString()); + } + else { + logger.info("query meta for table({}) received response", tableName_); + query_cfg_response resp = op.get_response(); + if (resp.app_id != appID_ || resp.partition_count != tableConfig_.get().replicas.size()) { + logger.warn("table({}) meta reset, app_id({}->{}), partition_count({}->{})", + tableName_, + appID_, + resp.app_id, + tableConfig_.get().replicas.size(), + resp.partition_count); + } + initTableConfiguration(resp); + } + + inQuerying_.set(false); + } + + boolean tryQueryMeta(long cachedConfigVersion) { + if (!inQuerying_.compareAndSet(false, true)) + return false; + + long now = System.currentTimeMillis(); + if (now - lastQueryTime_ < manager_.getRetryDelay()) { + inQuerying_.set(false); + return false; + } + if (tableConfig_.get().updateVersion > cachedConfigVersion) { + inQuerying_.set(false); + return false; + } + + lastQueryTime_ = now; + query_cfg_request req = new query_cfg_request(tableName_, new ArrayList()); + final query_cfg_operator query_op = new query_cfg_operator(new gpid(-1, -1), req); + + logger.info("query meta for table({}) query request", tableName_); + manager_.getMetaSession().asyncQuery(query_op, new Runnable() { + @Override + public void run() { + onUpdateConfiguration(query_op); + } + }, 5); + + return true; + } + + void onRpcReply(ClientRequestRound round, + int tryId, + ReplicaConfiguration cachedHandle, + long cachedConfigVersion) { + client_operator operator = round.getOperator(); + + boolean needQueryMeta = false; + switch (operator.rpc_error.errno) { + case ERR_OK: + round.thisRoundCompletion(); + return; + + case ERR_TIMEOUT: // <- operation timeout + logger.warn("{}: rpc timeout for gpid({}), operator({}), try({}), error_code({})", + tableName_, + operator.get_gpid().toString(), + operator, + tryId, + operator.rpc_error.errno.toString()); + break; + + case ERR_INVALID_DATA: // <- maybe because task code is invalid + logger.error("{}: invalid data for gpid({}), operator({}), try({}), error_code({})", + tableName_, + operator.get_gpid().toString(), + operator, + tryId, + operator.rpc_error.errno.toString()); + assert false; + break; + + // under these cases we should query the new config from meta + case ERR_SESSION_RESET: // <- connection with the server failed + case ERR_OBJECT_NOT_FOUND: // <- replica server doesn't serve this gpid + case ERR_INVALID_STATE: // <- replica server is not primary + logger.warn("{}: replica server({}) doesn't serve gpid({}), operator({}), try({}), error_code({}), need query meta", + tableName_, + cachedHandle.session.name(), + operator.get_gpid().toString(), + operator, + tryId, + operator.rpc_error.errno.toString()); + needQueryMeta = true; + break; + + case ERR_NOT_ENOUGH_MEMBER: + case ERR_CAPACITY_EXCEEDED: + logger.warn("{}: replica server({}) can't serve writing for gpid({}), operator({}), try({}), error_code({}), retry later", + tableName_, + cachedHandle.session.name(), + operator.get_gpid().toString(), + operator, + tryId, + operator.rpc_error.errno.toString()); + break; + + default: + logger.error("{}: unexpected error for gpid({}), operator({}), try({}), error_code({})", + tableName_, + operator.get_gpid().toString(), + operator, + tryId, + operator.rpc_error.errno.toString()); + assert false; + break; + } + + if (needQueryMeta) { + tryQueryMeta(cachedConfigVersion); + } + + tryDelayCall(round, tryId + 1); + } + + void tryDelayCall(final ClientRequestRound round, final int tryId) { + long nanoDelay = manager_.getRetryDelay(round.timeoutMs) * 1000000; + if (round.expireNanoTime - System.nanoTime() > nanoDelay) { + executor_.schedule(new Runnable() { + @Override + public void run() { + call(round, tryId); + } + }, nanoDelay, TimeUnit.NANOSECONDS); + } + else { + // errno == ERR_UNKNOWN means the request has never attemptted to contact any replica servers + // this may happen when we can't initialize a null replica session for a long time + if (round.getOperator().rpc_error.errno == error_types.ERR_UNKNOWN) { + round.getOperator().rpc_error.errno = error_types.ERR_TIMEOUT; + } + round.thisRoundCompletion(); + } + } + + void call(final ClientRequestRound round, final int tryId) { + // tableConfig & handle is initialized in constructor, so both shouldn't be null + final TableConfiguration tableConfig = tableConfig_.get(); + final ReplicaConfiguration handle = tableConfig.replicas.get(round.getOperator().get_gpid().get_pidx()); + if (handle.session != null) { + handle.session.asyncSend(round.getOperator(), new Runnable() { + @Override + public void run() { + onRpcReply(round, tryId, handle, tableConfig.updateVersion); + } + }, round.timeoutMs); + } + else { + logger.warn("{}: no primary for gpid({}), operator({}), try({}), retry later", + tableName_, + round.getOperator().get_gpid().toString(), + round.getOperator(), + tryId); + tryQueryMeta(tableConfig.updateVersion); + tryDelayCall(round, tryId + 1); + } + } + + @Override + public int getPartitionCount() { return tableConfig_.get().replicas.size(); } + + @Override + public void operate(client_operator op, int timeoutMs) throws ReplicationException { + final FutureTask syncer = new FutureTask(new Callable() { + @Override + public Void call() throws Exception { + return null; + } + }); + ClientOPCallback cb = new ClientOPCallback() { + @Override + public void onCompletion(client_operator op) throws Throwable { + syncer.run(); + } + }; + + asyncOperate(op, cb, timeoutMs); + + try { + syncer.get(timeoutMs, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + logger.info("got exception: " + e); + throw new ReplicationException(e); + } catch (ExecutionException e) { + logger.info("got exception: " + e); + throw new ReplicationException(e); + } catch (TimeoutException e) { + op.rpc_error.errno = error_types.ERR_TIMEOUT; + } + + if (op.rpc_error.errno != error_types.ERR_OK) { + throw new ReplicationException(op.rpc_error.errno); + } + } + + @Override + public EventExecutor getExecutor() { + return executor_; + } + + @Override + public int getDefaultTimeout() { return manager_.getTimeout(); } + + @Override + public void asyncOperate(client_operator op, ClientOPCallback callback, int timeoutMs) { + if (timeoutMs <= 0) { + timeoutMs = manager_.getTimeout(); + } + + ClientRequestRound round = new ClientRequestRound( + op, + callback, + manager_.counterEnabled(), + timeoutMs); + call(round, 1); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ThriftFrameDecoder.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ThriftFrameDecoder.java new file mode 100644 index 00000000..8e61c503 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ThriftFrameDecoder.java @@ -0,0 +1,74 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc.async; + +import com.xiaomi.infra.pegasus.base.error_code; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TBinaryProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import org.slf4j.Logger; + +import java.util.List; + +/** + * Created by sunweijie@xiaomi.com on 16-11-9. + */ +public class ThriftFrameDecoder extends ByteToMessageDecoder { + private static final Logger logger = org.slf4j.LoggerFactory.getLogger(ThriftFrameDecoder.class); + + private ReplicaSession session; + public ThriftFrameDecoder(ReplicaSession s) { + session = s; + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws TException { + if (in.readableBytes() < 4) + return; + + in.markReaderIndex(); + int frameSize = in.readInt() - 4; + if (in.readableBytes() < frameSize) + { + in.resetReaderIndex(); + return; + } + + int nextReaderIndex = in.readerIndex() + frameSize; + TBinaryProtocol iprot = new TBinaryProtocol(new TByteBufTransport(in)); + com.xiaomi.infra.pegasus.base.error_code ec = new com.xiaomi.infra.pegasus.base.error_code(); + + try { + ec.read(iprot); + TMessage msgHeader = iprot.readMessageBegin(); + ReplicaSession.RequestEntry e = session.getAndRemoveEntry(msgHeader.seqid); + if (e!=null) { + e.timeoutTask.cancel(true); + e.op.rpc_error.errno = ec.errno; + if (e.op.rpc_error.errno == error_code.error_types.ERR_OK) { + e.op.recv_data(iprot); + } + out.add(e); + } + else { + logger.info("{}: {} removed, perhaps timeout", ctx.channel().toString(), msgHeader.seqid); + } + } catch (TException e) { + logger.error("{}: got exception in thrift decode: ", ctx.channel().toString(), e); + throw e; + } finally { + in.readerIndex(nextReaderIndex); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + logger.warn("{} for session {} got exception in inbound handler: ", + ctx.channel().toString(), session.name(), cause); + super.exceptionCaught(ctx, cause); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ThriftFrameEncoder.java b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ThriftFrameEncoder.java new file mode 100644 index 00000000..800ffcc5 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/rpc/async/ThriftFrameEncoder.java @@ -0,0 +1,42 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc.async; + +import com.xiaomi.infra.pegasus.rpc.ThriftHeader; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; +import com.xiaomi.infra.pegasus.thrift.protocol.TBinaryProtocol; +import org.slf4j.Logger; + +/** + * Created by sunweijie@xiaomi.com on 16-11-9. + */ +public class ThriftFrameEncoder extends MessageToByteEncoder { + private static final Logger logger = org.slf4j.LoggerFactory.getLogger(ThriftFrameEncoder.class); + + public ThriftFrameEncoder() { + } + + @Override + protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ReplicaSession.RequestEntry entry, boolean preferDirect) throws Exception { + return preferDirect?ctx.alloc().ioBuffer(256):ctx.alloc().heapBuffer(256); + } + + @Override + protected void encode(ChannelHandlerContext ctx, ReplicaSession.RequestEntry e, ByteBuf out) throws Exception{ + int initIndex = out.writerIndex(); + + // write the Memory buffer + out.writerIndex(initIndex + ThriftHeader.HEADER_LENGTH); + TBinaryProtocol protocol = new TBinaryProtocol(new TByteBufTransport(out)); + e.op.send_data(protocol, e.sequenceId); + out.setBytes(initIndex, e.op.prepare_thrift_header(out.readableBytes() - ThriftHeader.HEADER_LENGTH)); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + logger.warn("got exception in outbound handler of {}, just ignore this: ", ctx.channel().toString(), cause); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/AsyncProcessFunction.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/AsyncProcessFunction.java new file mode 100644 index 00000000..85fb6f54 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/AsyncProcessFunction.java @@ -0,0 +1,56 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer; + +public abstract class AsyncProcessFunction { + final String methodName; + + public AsyncProcessFunction(String methodName) { + this.methodName = methodName; + } + + protected abstract boolean isOneway(); + + public abstract void start(I iface, T args, AsyncMethodCallback resultHandler) throws TException; + + public abstract T getEmptyArgsInstance(); + + public abstract AsyncMethodCallback getResultHandler(final AbstractNonblockingServer.AsyncFrameBuffer fb, int seqid); + + public String getMethodName() { + return methodName; + } + + public void sendResponse(final AbstractNonblockingServer.AsyncFrameBuffer fb, final TSerializable result, final byte type, final int seqid) throws TException { + TProtocol oprot = fb.getOutputProtocol(); + + oprot.writeMessageBegin(new TMessage(getMethodName(), type, seqid)); + result.write(oprot); + oprot.writeMessageEnd(); + oprot.getTransport().flush(); + + fb.responseReady(); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/EncodingUtils.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/EncodingUtils.java new file mode 100644 index 00000000..540c0729 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/EncodingUtils.java @@ -0,0 +1,148 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +/** + * Utility methods for use when encoding/decoding raw data as byte arrays. + */ +public class EncodingUtils { + + /** + * Encode integer as a series of 4 bytes into buf + * starting at position 0 within that buffer. + * + * @param integer + * The integer to encode. + * @param buf + * The buffer to write to. + */ + public static final void encodeBigEndian(final int integer, final byte[] buf) { + encodeBigEndian(integer, buf, 0); + } + + /** + * Encode integer as a series of 4 bytes into buf + * starting at position offset. + * + * @param integer + * The integer to encode. + * @param buf + * The buffer to write to. + * @param offset + * The offset within buf to start the encoding. + */ + public static final void encodeBigEndian(final int integer, final byte[] buf, int offset) { + buf[offset] = (byte) (0xff & (integer >> 24)); + buf[offset + 1] = (byte) (0xff & (integer >> 16)); + buf[offset + 2] = (byte) (0xff & (integer >> 8)); + buf[offset + 3] = (byte) (0xff & (integer)); + } + + /** + * Decode a series of 4 bytes from buf, starting at position 0, + * and interpret them as an integer. + * + * @param buf + * The buffer to read from. + * @return An integer, as read from the buffer. + */ + public static final int decodeBigEndian(final byte[] buf) { + return decodeBigEndian(buf, 0); + } + + /** + * Decode a series of 4 bytes from buf, start at + * offset, and interpret them as an integer. + * + * @param buf + * The buffer to read from. + * @param offset + * The offset with buf to start the decoding. + * @return An integer, as read from the buffer. + */ + public static final int decodeBigEndian(final byte[] buf, int offset) { + return ((buf[offset] & 0xff) << 24) | ((buf[offset + 1] & 0xff) << 16) + | ((buf[offset + 2] & 0xff) << 8) | ((buf[offset + 3] & 0xff)); + } + + /** + * Bitfield utilities. + * Returns true if the bit at position is set in v. + */ + public static final boolean testBit(byte v, int position) { + return testBit((int)v, position); + } + + public static final boolean testBit(short v, int position) { + return testBit((int)v, position); + } + + public static final boolean testBit(int v, int position) { + return (v & (1 << position)) != 0; + } + + public static final boolean testBit(long v, int position) { + return (v & (1L << position)) != 0L; + } + + /** + * Returns v, with the bit at position set to zero. + */ + public static final byte clearBit(byte v, int position) { + return (byte)clearBit((int)v, position); + } + + public static final short clearBit(short v, int position) { + return (short)clearBit((int)v, position); + } + + public static final int clearBit(int v, int position) { + return v & ~(1 << position); + } + + public static final long clearBit(long v, int position) { + return v & ~(1L << position); + } + + /** + * Returns v, with the bit at position set to 1 or 0 depending on value. + */ + public static final byte setBit(byte v, int position, boolean value) { + return (byte)setBit((int)v, position, value); + } + + public static final short setBit(short v, int position, boolean value) { + return (short)setBit((int)v, position, value); + } + + public static final int setBit(int v, int position, boolean value) { + if(value) + return v | (1 << position); + else + return clearBit(v, position); + } + + public static final long setBit(long v, int position, boolean value) { + if(value) + return v | (1L << position); + else + return clearBit(v, position); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/Option.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/Option.java new file mode 100644 index 00000000..58b2a01f --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/Option.java @@ -0,0 +1,121 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +/** + * Implementation of the Option type pattern + */ +public abstract class Option { + + /** + * Whether the Option is defined or not + * @return + * true if the Option is defined (of type Some) + * false if the Option is not defined (of type None) + */ + public abstract boolean isDefined(); + + /** + * Get the value of the Option (if it is defined) + * @return the value + * @throws IllegalStateException if called on a None + */ + public abstract T get(); + + /** + * Get the contained value (if defined) or else return a default value + * @param other what to return if the value is not defined (a None) + * @return either the value, or other if the value is not defined + */ + public T or(T other) { + if (isDefined()) { + return get(); + } else { + return other; + } + } + /** + * The None type, representing an absent value (instead of "null") + */ + public static class None extends Option { + public boolean isDefined() { + return false; + } + + public T get() { + throw new IllegalStateException("Cannot call get() on None"); + } + + public String toString() { + return "None"; + } + } + + /** + * The Some type, representing an existence of some value + * @param The type of value + */ + public static class Some extends Option { + private final T value; + public Some(T value) { + this.value = value; + } + + public boolean isDefined() { + return true; + } + + public T get() { + return value; + } + + public String toString() { + return "Some("+value.toString()+")"; + } + } + + /** + * Wraps value in an Option type, depending on whether or not value is null + * @param value + * @param type of value + * @return Some(value) if value is not null, None if value is null + */ + public static Option fromNullable(T value) { + if (value != null) { + return new Some(value); + } else { + return new None(); + } + } + + /** + * Wrap value in a Some type (NB! value must not be null!) + * @param value + * @param type of value + * @return a new Some(value) + */ + public static Some some(T value) { + return new Some(value); + } + + public static None none() { + return new None(); + } +} \ No newline at end of file diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/ProcessFunction.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/ProcessFunction.java new file mode 100644 index 00000000..9332ce50 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/ProcessFunction.java @@ -0,0 +1,87 @@ +package com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolException; +import com.xiaomi.infra.pegasus.thrift.transport.TTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class ProcessFunction { + private final String methodName; + + private static final Logger LOGGER = LoggerFactory.getLogger(ProcessFunction.class.getName()); + + public ProcessFunction(String methodName) { + this.methodName = methodName; + } + + public final void process(int seqid, TProtocol iprot, TProtocol oprot, I iface) throws TException { + T args = getEmptyArgsInstance(); + try { + args.read(iprot); + } catch (TProtocolException e) { + iprot.readMessageEnd(); + TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage()); + oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid)); + x.write(oprot); + oprot.writeMessageEnd(); + oprot.getTransport().flush(); + return; + } + iprot.readMessageEnd(); + TSerializable result = null; + byte msgType = TMessageType.REPLY; + + try { + result = getResult(iface, args); + } catch (TTransportException ex) { + LOGGER.error("Transport error while processing " + getMethodName(), ex); + throw ex; + } catch (TApplicationException ex) { + LOGGER.error("Internal application error processing " + getMethodName(), ex); + result = ex; + msgType = TMessageType.EXCEPTION; + } catch (Exception ex) { + LOGGER.error("Internal error processing " + getMethodName(), ex); + if(!isOneway()) { + result = new TApplicationException(TApplicationException.INTERNAL_ERROR, + "Internal error processing " + getMethodName()); + msgType = TMessageType.EXCEPTION; + } + } + + if(!isOneway()) { + oprot.writeMessageBegin(new TMessage(getMethodName(), msgType, seqid)); + result.write(oprot); + oprot.writeMessageEnd(); + oprot.getTransport().flush(); + } + } + + private void handleException(int seqid, TProtocol oprot) throws TException { + if (!isOneway()) { + TApplicationException x = new TApplicationException(TApplicationException.INTERNAL_ERROR, + "Internal error processing " + getMethodName()); + oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid)); + x.write(oprot); + oprot.writeMessageEnd(); + oprot.getTransport().flush(); + } + } + + protected boolean handleRuntimeExceptions() { + return false; + } + + protected abstract boolean isOneway(); + + public abstract TBase getResult(I iface, T args) throws TException; + + public abstract T getEmptyArgsInstance(); + + public String getMethodName() { + return methodName; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/ShortStack.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/ShortStack.java new file mode 100644 index 00000000..091dfb41 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/ShortStack.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.xiaomi.infra.pegasus.thrift; + +/** + * ShortStack is a short-specific Stack implementation written for the express + * purpose of very fast operations on TCompactProtocol's field id stack. This + * implementation performs at least 10x faster than java.util.Stack. + */ +public class ShortStack { + + private short[] vector; + private int top = -1; + + public ShortStack(int initialCapacity) { + vector = new short[initialCapacity]; + } + + public short pop() { + return vector[top--]; + } + + public void push(short pushed) { + if (vector.length == top + 1) { + grow(); + } + vector[++top] = pushed; + } + + private void grow() { + short[] newVector = new short[vector.length * 2]; + System.arraycopy(vector, 0, newVector, 0, vector.length); + vector = newVector; + } + + public short peek() { + return vector[top]; + } + + public void clear() { + top = -1; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(">"); + } + + sb.append(vector[i]); + + if (i == top) { + sb.append("<<"); + } + } + sb.append("]>"); + return sb.toString(); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TApplicationException.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TApplicationException.java new file mode 100644 index 00000000..4830a111 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TApplicationException.java @@ -0,0 +1,150 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.protocol.TField; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil; +import com.xiaomi.infra.pegasus.thrift.protocol.TStruct; +import com.xiaomi.infra.pegasus.thrift.protocol.TType; + +/** + * Application level exception + * + */ +public class TApplicationException extends TException implements TSerializable { + + private static final TStruct TAPPLICATION_EXCEPTION_STRUCT = new TStruct("TApplicationException"); + private static final TField MESSAGE_FIELD = new TField("message", TType.STRING, (short)1); + private static final TField TYPE_FIELD = new TField("type", TType.I32, (short)2); + + private static final long serialVersionUID = 1L; + + public static final int UNKNOWN = 0; + public static final int UNKNOWN_METHOD = 1; + public static final int INVALID_MESSAGE_TYPE = 2; + public static final int WRONG_METHOD_NAME = 3; + public static final int BAD_SEQUENCE_ID = 4; + public static final int MISSING_RESULT = 5; + public static final int INTERNAL_ERROR = 6; + public static final int PROTOCOL_ERROR = 7; + public static final int INVALID_TRANSFORM = 8; + public static final int INVALID_PROTOCOL = 9; + public static final int UNSUPPORTED_CLIENT_TYPE = 10; + + protected int type_ = UNKNOWN; + private String message_ = null; + + public TApplicationException() { + super(); + } + + public TApplicationException(int type) { + super(); + type_ = type; + } + + public TApplicationException(int type, String message) { + super(message); + type_ = type; + } + + public TApplicationException(String message) { + super(message); + } + + public int getType() { + return type_; + } + + @Override + public String getMessage() { + if (message_ == null) { + return super.getMessage(); + } + else { + return message_; + } + } + + public void read(TProtocol iprot) throws TException + { + TField field; + iprot.readStructBegin(); + + String message = null; + int type = UNKNOWN; + + while (true) { + field = iprot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + switch (field.id) { + case 1: + if (field.type == TType.STRING) { + message = iprot.readString(); + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case 2: + if (field.type == TType.I32) { + type = iprot.readI32(); + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + default: + TProtocolUtil.skip(iprot, field.type); + break; + } + iprot.readFieldEnd(); + } + iprot.readStructEnd(); + type_ = type; + message_ = message; + } + + /** + * Convenience factory method for constructing a TApplicationException given a TProtocol input + */ + public static TApplicationException readFrom(TProtocol iprot) throws TException + { + TApplicationException result = new TApplicationException(); + result.read(iprot); + return result; + } + + public void write(TProtocol oprot) throws TException + { + oprot.writeStructBegin(TAPPLICATION_EXCEPTION_STRUCT); + if (getMessage() != null) { + oprot.writeFieldBegin(MESSAGE_FIELD); + oprot.writeString(getMessage()); + oprot.writeFieldEnd(); + } + oprot.writeFieldBegin(TYPE_FIELD); + oprot.writeI32(type_); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TAsyncProcessor.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TAsyncProcessor.java new file mode 100644 index 00000000..206368fa --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TAsyncProcessor.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.protocol.*; + +import com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.Map; + +public interface TAsyncProcessor { + /** + * Implementations must call fb.responseReady() once processing is complete + */ + public boolean process(final AsyncFrameBuffer fb) throws TException; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TBase.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TBase.java new file mode 100644 index 00000000..51a480e2 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TBase.java @@ -0,0 +1,67 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +import java.io.Serializable; + +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +/** + * Generic base interface for generated Thrift objects. + * + */ +public interface TBase, F extends TFieldIdEnum> extends Comparable, TSerializable, Serializable { + + /** + * Get the F instance that corresponds to fieldId. + */ + public F fieldForId(int fieldId); + + /** + * Check if a field is currently set or unset. + * + * @param field + */ + public boolean isSet(F field); + + /** + * Get a field's value by field variable. Primitive types will be wrapped in + * the appropriate "boxed" types. + * + * @param field + */ + public Object getFieldValue(F field); + + /** + * Set a field's value by field variable. Primitive types must be "boxed" in + * the appropriate object wrapper type. + * + * @param field + */ + public void setFieldValue(F field, Object value); + + public T deepCopy(); + + /** + * Return to the state of having just been initialized, as though you had just + * called the default constructor. + */ + public void clear(); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseAsyncProcessor.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseAsyncProcessor.java new file mode 100644 index 00000000..c9f660a2 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseAsyncProcessor.java @@ -0,0 +1,105 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.protocol.*; +import com.xiaomi.infra.pegasus.thrift.async.AsyncMethodCallback; + +import com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.Map; + +public class TBaseAsyncProcessor implements TAsyncProcessor, TProcessor { + protected final Logger LOGGER = LoggerFactory.getLogger(getClass().getName()); + + final I iface; + final Map> processMap; + + public TBaseAsyncProcessor(I iface, Map> processMap) { + this.iface = iface; + this.processMap = processMap; + } + + public Map> getProcessMapView() { + return Collections.unmodifiableMap(processMap); + } + + public boolean process(final AsyncFrameBuffer fb) throws TException { + + final TProtocol in = fb.getInputProtocol(); + final TProtocol out = fb.getOutputProtocol(); + + //Find processing function + final TMessage msg = in.readMessageBegin(); + AsyncProcessFunction fn = processMap.get(msg.name); + if (fn == null) { + TProtocolUtil.skip(in, TType.STRUCT); + in.readMessageEnd(); + if (!fn.isOneway()) { + TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'"); + out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid)); + x.write(out); + out.writeMessageEnd(); + out.getTransport().flush(); + } + fb.responseReady(); + return true; + } + + //Get Args + TBase args = fn.getEmptyArgsInstance(); + + try { + args.read(in); + } catch (TProtocolException e) { + in.readMessageEnd(); + if (!fn.isOneway()) { + TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage()); + out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid)); + x.write(out); + out.writeMessageEnd(); + out.getTransport().flush(); + } + fb.responseReady(); + return true; + } + in.readMessageEnd(); + + if (fn.isOneway()) { + fb.responseReady(); + } + + //start off processing function + AsyncMethodCallback resultHandler = fn.getResultHandler(fb, msg.seqid); + try { + fn.start(iface, args, resultHandler); + } catch (Exception e) { + resultHandler.onError(e); + } + return true; + } + + @Override + public boolean process(TProtocol in, TProtocol out) throws TException { + return false; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseHelper.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseHelper.java new file mode 100644 index 00000000..22fba3b0 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseHelper.java @@ -0,0 +1,337 @@ +/** + * 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 com.xiaomi.infra.pegasus.thrift; + +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.Collection; + +public final class TBaseHelper { + + private TBaseHelper(){} + + private static final Comparator comparator = new NestedStructureComparator(); + + public static int compareTo(Object o1, Object o2) { + if (o1 instanceof Comparable) { + return compareTo((Comparable)o1, (Comparable)o2); + } else if (o1 instanceof List) { + return compareTo((List)o1, (List)o2); + } else if (o1 instanceof Set) { + return compareTo((Set)o1, (Set)o2); + } else if (o1 instanceof Map) { + return compareTo((Map)o1, (Map)o2); + } else if (o1 instanceof byte[]) { + return compareTo((byte[])o1, (byte[])o2); + } else { + throw new IllegalArgumentException("Cannot compare objects of type " + o1.getClass()); + } + } + + public static int compareTo(boolean a, boolean b) { + return Boolean.valueOf(a).compareTo(b); + } + + public static int compareTo(byte a, byte b) { + if (a < b) { + return -1; + } else if (b < a) { + return 1; + } else { + return 0; + } + } + + public static int compareTo(short a, short b) { + if (a < b) { + return -1; + } else if (b < a) { + return 1; + } else { + return 0; + } + } + + public static int compareTo(int a, int b) { + if (a < b) { + return -1; + } else if (b < a) { + return 1; + } else { + return 0; + } + } + + public static int compareTo(long a, long b) { + if (a < b) { + return -1; + } else if (b < a) { + return 1; + } else { + return 0; + } + } + + public static int compareTo(double a, double b) { + if (a < b) { + return -1; + } else if (b < a) { + return 1; + } else { + return 0; + } + } + + public static int compareTo(String a, String b) { + return a.compareTo(b); + } + + public static int compareTo(byte[] a, byte[] b) { + int sizeCompare = compareTo(a.length, b.length); + if (sizeCompare != 0) { + return sizeCompare; + } + for (int i = 0; i < a.length; i++) { + int byteCompare = compareTo(a[i], b[i]); + if (byteCompare != 0) { + return byteCompare; + } + } + return 0; + } + + public static int compareTo(Comparable a, Comparable b) { + return a.compareTo(b); + } + + public static int compareTo(List a, List b) { + int lastComparison = compareTo(a.size(), b.size()); + if (lastComparison != 0) { + return lastComparison; + } + for (int i = 0; i < a.size(); i++) { + lastComparison = comparator.compare(a.get(i), b.get(i)); + if (lastComparison != 0) { + return lastComparison; + } + } + return 0; + } + + public static int compareTo(Set a, Set b) { + int lastComparison = compareTo(a.size(), b.size()); + if (lastComparison != 0) { + return lastComparison; + } + SortedSet sortedA = new TreeSet(comparator); + sortedA.addAll(a); + SortedSet sortedB = new TreeSet(comparator); + sortedB.addAll(b); + + Iterator iterA = sortedA.iterator(); + Iterator iterB = sortedB.iterator(); + + // Compare each item. + while (iterA.hasNext() && iterB.hasNext()) { + lastComparison = comparator.compare(iterA.next(), iterB.next()); + if (lastComparison != 0) { + return lastComparison; + } + } + + return 0; + } + + public static int compareTo(Map a, Map b) { + int lastComparison = compareTo(a.size(), b.size()); + if (lastComparison != 0) { + return lastComparison; + } + + // Sort a and b so we can compare them. + SortedMap sortedA = new TreeMap(comparator); + sortedA.putAll(a); + Iterator iterA = sortedA.entrySet().iterator(); + SortedMap sortedB = new TreeMap(comparator); + sortedB.putAll(b); + Iterator iterB = sortedB.entrySet().iterator(); + + // Compare each item. + while (iterA.hasNext() && iterB.hasNext()) { + Map.Entry entryA = iterA.next(); + Map.Entry entryB = iterB.next(); + lastComparison = comparator.compare(entryA.getKey(), entryB.getKey()); + if (lastComparison != 0) { + return lastComparison; + } + lastComparison = comparator.compare(entryA.getValue(), entryB.getValue()); + if (lastComparison != 0) { + return lastComparison; + } + } + + return 0; + } + + /** + * Comparator to compare items inside a structure (e.g. a list, set, or map). + */ + private static class NestedStructureComparator implements Comparator, Serializable { + public int compare(Object oA, Object oB) { + if (oA == null && oB == null) { + return 0; + } else if (oA == null) { + return -1; + } else if (oB == null) { + return 1; + } else if (oA instanceof List) { + return compareTo((List)oA, (List)oB); + } else if (oA instanceof Set) { + return compareTo((Set)oA, (Set)oB); + } else if (oA instanceof Map) { + return compareTo((Map)oA, (Map)oB); + } else if (oA instanceof byte[]) { + return compareTo((byte[])oA, (byte[])oB); + } else { + return compareTo((Comparable)oA, (Comparable)oB); + } + } + } + + public static void toString(Collection bbs, StringBuilder sb) { + Iterator it = bbs.iterator(); + if (!it.hasNext()) { + sb.append("[]"); + } else { + sb.append("["); + while (true) { + ByteBuffer bb = it.next(); + com.xiaomi.infra.pegasus.thrift.TBaseHelper.toString(bb, sb); + if (!it.hasNext()) { + sb.append("]"); + return; + } else { + sb.append(", "); + } + } + } + } + + public static void toString(ByteBuffer bb, StringBuilder sb) { + byte[] buf = bb.array(); + + int arrayOffset = bb.arrayOffset(); + int offset = arrayOffset + bb.position(); + int origLimit = arrayOffset + bb.limit(); + int limit = (origLimit - offset > 128) ? offset + 128 : origLimit; + + for (int i = offset; i < limit; i++) { + if (i > offset) { + sb.append(" "); + } + sb.append(paddedByteString(buf[i])); + } + if (origLimit != limit) { + sb.append("..."); + } + } + + public static String paddedByteString(byte b) { + int extended = (b | 0x100) & 0x1ff; + return Integer.toHexString(extended).toUpperCase().substring(1); + } + + public static byte[] byteBufferToByteArray(ByteBuffer byteBuffer) { + if (wrapsFullArray(byteBuffer)) { + return byteBuffer.array(); + } + byte[] target = new byte[byteBuffer.remaining()]; + byteBufferToByteArray(byteBuffer, target, 0); + return target; + } + + public static boolean wrapsFullArray(ByteBuffer byteBuffer) { + return byteBuffer.hasArray() + && byteBuffer.position() == 0 + && byteBuffer.arrayOffset() == 0 + && byteBuffer.remaining() == byteBuffer.capacity(); + } + + public static int byteBufferToByteArray(ByteBuffer byteBuffer, byte[] target, int offset) { + int remaining = byteBuffer.remaining(); + System.arraycopy(byteBuffer.array(), + byteBuffer.arrayOffset() + byteBuffer.position(), + target, + offset, + remaining); + return remaining; + } + + public static ByteBuffer rightSize(ByteBuffer in) { + if (in == null) { + return null; + } + if (wrapsFullArray(in)) { + return in; + } + return ByteBuffer.wrap(byteBufferToByteArray(in)); + } + + public static ByteBuffer copyBinary(final ByteBuffer orig) { + if (orig == null) { + return null; + } + ByteBuffer copy = ByteBuffer.wrap(new byte[orig.remaining()]); + if (orig.hasArray()) { + System.arraycopy(orig.array(), orig.arrayOffset() + orig.position(), copy.array(), 0, orig.remaining()); + } else { + orig.slice().get(copy.array()); + } + + return copy; + } + + public static byte[] copyBinary(final byte[] orig) { + if (orig == null) { + return null; + } + + byte[] copy = new byte[orig.length]; + System.arraycopy(orig, 0, copy, 0, orig.length); + return copy; + } + + public static int hashCode(long value) { + int low = (int) value; + int high = (int) (value >>> 32); + return high * 127 + low; + } + + public static int hashCode(double value) { + return hashCode(Double.doubleToRawLongBits(value)); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseProcessor.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseProcessor.java new file mode 100644 index 00000000..edd79dc1 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TBaseProcessor.java @@ -0,0 +1,42 @@ +package com.xiaomi.infra.pegasus.thrift; + +import java.util.Collections; +import java.util.Map; + +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil; +import com.xiaomi.infra.pegasus.thrift.protocol.TType; + +public abstract class TBaseProcessor implements TProcessor { + private final I iface; + private final Map> processMap; + + protected TBaseProcessor(I iface, Map> processFunctionMap) { + this.iface = iface; + this.processMap = processFunctionMap; + } + + public Map> getProcessMapView() { + return Collections.unmodifiableMap(processMap); + } + + @Override + public boolean process(TProtocol in, TProtocol out) throws TException { + TMessage msg = in.readMessageBegin(); + ProcessFunction fn = processMap.get(msg.name); + if (fn == null) { + TProtocolUtil.skip(in, TType.STRUCT); + in.readMessageEnd(); + TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, "Invalid method name: '"+msg.name+"'"); + out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid)); + x.write(out); + out.writeMessageEnd(); + out.getTransport().flush(); + return true; + } + fn.process(msg.seqid, in, out, iface); + return true; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TByteArrayOutputStream.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TByteArrayOutputStream.java new file mode 100644 index 00000000..b63934d1 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TByteArrayOutputStream.java @@ -0,0 +1,56 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +import java.io.ByteArrayOutputStream; + +/** + * Class that allows access to the underlying buf without doing deep + * copies on it. + * + */ +public class TByteArrayOutputStream extends ByteArrayOutputStream { + + private final int initialSize; + + public TByteArrayOutputStream(int size) { + super(size); + this.initialSize = size; + } + + public TByteArrayOutputStream() { + this(32); + } + + public byte[] get() { + return buf; + } + + public void reset() { + super.reset(); + if (buf.length > initialSize) { + buf = new byte[initialSize]; + } + } + + public int len() { + return count; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TDeserializer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TDeserializer.java new file mode 100644 index 00000000..5467ba98 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TDeserializer.java @@ -0,0 +1,358 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; + +import com.xiaomi.infra.pegasus.thrift.protocol.TBinaryProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TField; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolUtil; +import com.xiaomi.infra.pegasus.thrift.protocol.TType; +import com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport; + +/** + * Generic utility for easily deserializing objects from a byte array or Java + * String. + * + */ +public class TDeserializer { + private final TProtocol protocol_; + private final TMemoryInputTransport trans_; + + /** + * Create a new TDeserializer that uses the TBinaryProtocol by default. + */ + public TDeserializer() { + this(new TBinaryProtocol.Factory()); + } + + /** + * Create a new TDeserializer. It will use the TProtocol specified by the + * factory that is passed in. + * + * @param protocolFactory Factory to create a protocol + */ + public TDeserializer(TProtocolFactory protocolFactory) { + trans_ = new TMemoryInputTransport(); + protocol_ = protocolFactory.getProtocol(trans_); + } + + /** + * Deserialize the Thrift object from a byte array. + * + * @param base The object to read into + * @param bytes The array to read from + */ + public void deserialize(TBase base, byte[] bytes) throws TException { + deserialize(base, bytes, 0, bytes.length); + } + + /** + * Deserialize the Thrift object from a byte array. + * + * @param base The object to read into + * @param bytes The array to read from + * @param offset The offset into {@code bytes} + * @param length The length to read from {@code bytes} + */ + public void deserialize(TBase base, byte[] bytes, int offset, int length) throws TException { + try { + trans_.reset(bytes, offset, length); + base.read(protocol_); + } finally { + trans_.clear(); + protocol_.reset(); + } + } + + /** + * Deserialize the Thrift object from a Java string, using a specified + * character set for decoding. + * + * @param base The object to read into + * @param data The string to read from + * @param charset Valid JVM charset + */ + public void deserialize(TBase base, String data, String charset) throws TException { + try { + deserialize(base, data.getBytes(charset)); + } catch (UnsupportedEncodingException uex) { + throw new TException("JVM DOES NOT SUPPORT ENCODING: " + charset); + } finally { + protocol_.reset(); + } + } + + /** + * Deserialize only a single Thrift object (addressed by recursively using field id) + * from a byte record. + * @param tb The object to read into + * @param bytes The serialized object to read from + * @param fieldIdPathFirst First of the FieldId's that define a path tb + * @param fieldIdPathRest The rest FieldId's that define a path tb + * @throws TException + */ + public void partialDeserialize(TBase tb, byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + try { + if (locateField(bytes, fieldIdPathFirst, fieldIdPathRest) != null) { + // if this line is reached, iprot will be positioned at the start of tb. + tb.read(protocol_); + } + } catch (Exception e) { + throw new TException(e); + } finally { + trans_.clear(); + protocol_.reset(); + } + } + + /** + * Deserialize only a boolean field (addressed by recursively using field id) + * from a byte record. + * @param bytes The serialized object to read from + * @param fieldIdPathFirst First of the FieldId's that define a path to a boolean field + * @param fieldIdPathRest The rest FieldId's that define a path to a boolean field + * @throws TException + */ + public Boolean partialDeserializeBool(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + return (Boolean) partialDeserializeField(TType.BOOL, bytes, fieldIdPathFirst, fieldIdPathRest); + } + + /** + * Deserialize only a byte field (addressed by recursively using field id) + * from a byte record. + * @param bytes The serialized object to read from + * @param fieldIdPathFirst First of the FieldId's that define a path to a byte field + * @param fieldIdPathRest The rest FieldId's that define a path to a byte field + * @throws TException + */ + public Byte partialDeserializeByte(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + return (Byte) partialDeserializeField(TType.BYTE, bytes, fieldIdPathFirst, fieldIdPathRest); + } + + /** + * Deserialize only a double field (addressed by recursively using field id) + * from a byte record. + * @param bytes The serialized object to read from + * @param fieldIdPathFirst First of the FieldId's that define a path to a double field + * @param fieldIdPathRest The rest FieldId's that define a path to a double field + * @throws TException + */ + public Double partialDeserializeDouble(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + return (Double) partialDeserializeField(TType.DOUBLE, bytes, fieldIdPathFirst, fieldIdPathRest); + } + + /** + * Deserialize only an i16 field (addressed by recursively using field id) + * from a byte record. + * @param bytes The serialized object to read from + * @param fieldIdPathFirst First of the FieldId's that define a path to an i16 field + * @param fieldIdPathRest The rest FieldId's that define a path to an i16 field + * @throws TException + */ + public Short partialDeserializeI16(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + return (Short) partialDeserializeField(TType.I16, bytes, fieldIdPathFirst, fieldIdPathRest); + } + + /** + * Deserialize only an i32 field (addressed by recursively using field id) + * from a byte record. + * @param bytes The serialized object to read from + * @param fieldIdPathFirst First of the FieldId's that define a path to an i32 field + * @param fieldIdPathRest The rest FieldId's that define a path to an i32 field + * @throws TException + */ + public Integer partialDeserializeI32(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + return (Integer) partialDeserializeField(TType.I32, bytes, fieldIdPathFirst, fieldIdPathRest); + } + + /** + * Deserialize only an i64 field (addressed by recursively using field id) + * from a byte record. + * @param bytes The serialized object to read from + * @param fieldIdPathFirst First of the FieldId's that define a path to an i64 field + * @param fieldIdPathRest The rest FieldId's that define a path to an i64 field + * @throws TException + */ + public Long partialDeserializeI64(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + return (Long) partialDeserializeField(TType.I64, bytes, fieldIdPathFirst, fieldIdPathRest); + } + + /** + * Deserialize only a string field (addressed by recursively using field id) + * from a byte record. + * @param bytes The serialized object to read from + * @param fieldIdPathFirst First of the FieldId's that define a path to a string field + * @param fieldIdPathRest The rest FieldId's that define a path to a string field + * @throws TException + */ + public String partialDeserializeString(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + return (String) partialDeserializeField(TType.STRING, bytes, fieldIdPathFirst, fieldIdPathRest); + } + + /** + * Deserialize only a binary field (addressed by recursively using field id) + * from a byte record. + * @param bytes The serialized object to read from + * @param fieldIdPathFirst First of the FieldId's that define a path to a binary field + * @param fieldIdPathRest The rest FieldId's that define a path to a binary field + * @throws TException + */ + public ByteBuffer partialDeserializeByteArray(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + // TType does not have binary, so we use the arbitrary num 100 + return (ByteBuffer) partialDeserializeField((byte)100, bytes, fieldIdPathFirst, fieldIdPathRest); + } + + /** + * Deserialize only the id of the field set in a TUnion (addressed by recursively using field id) + * from a byte record. + * @param bytes The serialized object to read from + * @param fieldIdPathFirst First of the FieldId's that define a path to a TUnion + * @param fieldIdPathRest The rest FieldId's that define a path to a TUnion + * @throws TException + */ + public Short partialDeserializeSetFieldIdInUnion(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + try { + TField field = locateField(bytes, fieldIdPathFirst, fieldIdPathRest); + if (field != null){ + protocol_.readStructBegin(); // The Union + return protocol_.readFieldBegin().id; // The field set in the union + } + return null; + } catch (Exception e) { + throw new TException(e); + } finally { + trans_.clear(); + protocol_.reset(); + } + } + + private Object partialDeserializeField(byte ttype, byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + try { + TField field = locateField(bytes, fieldIdPathFirst, fieldIdPathRest); + if (field != null) { + // if this point is reached, iprot will be positioned at the start of the field. + switch(ttype){ + case TType.BOOL: + if (field.type == TType.BOOL){ + return protocol_.readBool(); + } + break; + case TType.BYTE: + if (field.type == TType.BYTE) { + return protocol_.readByte(); + } + break; + case TType.DOUBLE: + if (field.type == TType.DOUBLE) { + return protocol_.readDouble(); + } + break; + case TType.I16: + if (field.type == TType.I16) { + return protocol_.readI16(); + } + break; + case TType.I32: + if (field.type == TType.I32) { + return protocol_.readI32(); + } + break; + case TType.I64: + if (field.type == TType.I64) { + return protocol_.readI64(); + } + break; + case TType.STRING: + if (field.type == TType.STRING) { + return protocol_.readString(); + } + break; + case 100: // hack to differentiate between string and binary + if (field.type == TType.STRING) { + return protocol_.readBinary(); + } + break; + } + } + return null; + } catch (Exception e) { + throw new TException(e); + } finally { + trans_.clear(); + protocol_.reset(); + } + } + + private TField locateField(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { + trans_.reset(bytes); + + TFieldIdEnum[] fieldIdPath= new TFieldIdEnum[fieldIdPathRest.length + 1]; + fieldIdPath[0] = fieldIdPathFirst; + for (int i = 0; i < fieldIdPathRest.length; i++){ + fieldIdPath[i + 1] = fieldIdPathRest[i]; + } + + // index into field ID path being currently searched for + int curPathIndex = 0; + + // this will be the located field, or null if it is not located + TField field = null; + + protocol_.readStructBegin(); + + while (curPathIndex < fieldIdPath.length) { + field = protocol_.readFieldBegin(); + // we can stop searching if we either see a stop or we go past the field + // id we're looking for (since fields should now be serialized in asc + // order). + if (field.type == TType.STOP || field.id > fieldIdPath[curPathIndex].getThriftFieldId()) { + return null; + } + + if (field.id != fieldIdPath[curPathIndex].getThriftFieldId()) { + // Not the field we're looking for. Skip field. + TProtocolUtil.skip(protocol_, field.type); + protocol_.readFieldEnd(); + } else { + // This field is the next step in the path. Step into field. + curPathIndex++; + if (curPathIndex < fieldIdPath.length) { + protocol_.readStructBegin(); + } + } + } + return field; + } + + /** + * Deserialize the Thrift object from a Java string, using the default JVM + * charset encoding. + * + * @param base The object to read into + * @param data The string to read from + */ + public void fromString(TBase base, String data) throws TException { + deserialize(base, data.getBytes()); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TEnum.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TEnum.java new file mode 100644 index 00000000..e3a9ac41 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TEnum.java @@ -0,0 +1,24 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +public interface TEnum { + public int getValue(); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TEnumHelper.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TEnumHelper.java new file mode 100644 index 00000000..a8c27b6d --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TEnumHelper.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift; + +import java.lang.InstantiationException; +import java.lang.NoSuchMethodException; +import java.lang.IllegalAccessException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Utility class with static methods for interacting with TEnum + */ +public class TEnumHelper { + + /** + * Given a TEnum class and integer value, this method will return + * the associated constant from the given TEnum class. + * This method MUST be modified should the name of the 'findByValue' method + * change. + * + * @param enumClass TEnum from which to return a matching constant. + * @param value Value for which to return the constant. + * + * @return The constant in 'enumClass' whose value is 'value' or null if + * something went wrong. + */ + public static TEnum getByValue(Class enumClass, int value) { + try { + Method method = enumClass.getMethod("findByValue", int.class); + return (TEnum) method.invoke(null, value); + } catch (NoSuchMethodException nsme) { + return null; + } catch (IllegalAccessException iae) { + return null; + } catch (InvocationTargetException ite) { + return null; + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TException.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TException.java new file mode 100644 index 00000000..26935748 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TException.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift; + +/** + * Generic exception class for Thrift. + * + */ +public class TException extends Exception { + + private static final long serialVersionUID = 1L; + + public TException() { + super(); + } + + public TException(String message) { + super(message); + } + + public TException(Throwable cause) { + super(cause); + } + + public TException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TFieldIdEnum.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TFieldIdEnum.java new file mode 100644 index 00000000..309bf7b4 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TFieldIdEnum.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.xiaomi.infra.pegasus.thrift; + +/** + * Interface for all generated struct Fields objects. + */ +public interface TFieldIdEnum { + /** + * Get the Thrift field id for the named field. + */ + public short getThriftFieldId(); + + /** + * Get the field's name, exactly as in the IDL. + */ + public String getFieldName(); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TFieldRequirementType.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TFieldRequirementType.java new file mode 100644 index 00000000..3cf0adaf --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TFieldRequirementType.java @@ -0,0 +1,30 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +/** + * Requirement type constants. + * + */ +public final class TFieldRequirementType { + public static final byte REQUIRED = 1; + public static final byte OPTIONAL = 2; + public static final byte DEFAULT = 3; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TMultiplexedProcessor.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TMultiplexedProcessor.java new file mode 100644 index 00000000..e11cdcc5 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TMultiplexedProcessor.java @@ -0,0 +1,154 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.protocol.*; + +import java.util.Map; +import java.util.HashMap; + +/** + * TMultiplexedProcessor is a TProcessor allowing + * a single TServer to provide multiple services. + * + *

To do so, you instantiate the processor and then register additional + * processors with it, as shown in the following example:

+ * + *
+ * TMultiplexedProcessor processor = new TMultiplexedProcessor(); + * + * processor.registerProcessor( + * "Calculator", + * new Calculator.Processor(new CalculatorHandler())); + * + * processor.registerProcessor( + * "WeatherReport", + * new WeatherReport.Processor(new WeatherReportHandler())); + * + * TServerTransport t = new TServerSocket(9090); + * TSimpleServer server = new TSimpleServer(processor, t); + * + * server.serve(); + *
+ */ +public class TMultiplexedProcessor implements TProcessor { + + private final Map SERVICE_PROCESSOR_MAP + = new HashMap(); + private TProcessor defaultProcessor; + + /** + * 'Register' a service with this TMultiplexedProcessor. 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 void registerProcessor(String serviceName, TProcessor processor) { + SERVICE_PROCESSOR_MAP.put(serviceName, processor); + } + + /** + * Register a service to be called to process queries without service name + * @param processor + */ + public void registerDefault(TProcessor processor) { + defaultProcessor = processor; + } + + /** + * This implementation of process performs the following steps: + * + *
    + *
  1. Read the beginning of the message.
  2. + *
  3. Extract the service name from the message.
  4. + *
  5. Using the service name to locate the appropriate processor.
  6. + *
  7. Dispatch to the processor, with a decorated instance of TProtocol + * that allows readMessageBegin() to return the original TMessage.
  8. + *
+ * + * @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. You called {@link #registerProcessor(String, TProcessor) registerProcessor} + * during initialization, right? :) + */ + public boolean process(TProtocol iprot, TProtocol oprot) throws TException { + /* + 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. + */ + TMessage message = iprot.readMessageBegin(); + + if (message.type != TMessageType.CALL && message.type != TMessageType.ONEWAY) { + throw new TException("This should not have happened!?"); + } + + // Extract the service name + int index = message.name.indexOf(TMultiplexedProtocol.SEPARATOR); + if (index < 0) { + if (defaultProcessor != null) { + // Dispatch processing to the stored processor + return defaultProcessor.process(new StoredMessageProtocol(iprot, message), oprot); + } + throw new TException("Service name not found in message name: " + message.name + ". Did you " + + "forget to use a TMultiplexProtocol in your client?"); + } + + // Create a new TMessage, something that can be consumed by any TProtocol + String serviceName = message.name.substring(0, index); + TProcessor actualProcessor = SERVICE_PROCESSOR_MAP.get(serviceName); + if (actualProcessor == null) { + throw new TException("Service name not found: " + serviceName + ". Did you forget " + + "to call registerProcessor()?"); + } + + // Create a new TMessage, removing the service name + TMessage standardMessage = new TMessage( + message.name.substring(serviceName.length()+TMultiplexedProtocol.SEPARATOR.length()), + message.type, + message.seqid + ); + + // Dispatch processing to the stored processor + return actualProcessor.process(new StoredMessageProtocol(iprot, standardMessage), oprot); + } + + /** + * Our goal was to work with any protocol. In order to do that, we needed + * to allow them to call readMessageBegin() and get a TMessage in exactly + * the standard format, without the service name prepended to TMessage.name. + */ + private static class StoredMessageProtocol extends TProtocolDecorator { + TMessage messageBegin; + public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) { + super(protocol); + this.messageBegin = messageBegin; + } + @Override + public TMessage readMessageBegin() throws TException { + return messageBegin; + } + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TNonblockingMultiFetchClient.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TNonblockingMultiFetchClient.java new file mode 100644 index 00000000..2ac4b5e6 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TNonblockingMultiFetchClient.java @@ -0,0 +1,399 @@ +/** + * 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 com.xiaomi.infra.pegasus.thrift; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + + +/** + * This class uses a single thread to set up non-blocking sockets to a set + * of remote servers (hostname and port pairs), and sends a same request to + * all these servers. It then fetches responses from servers. + * + * Parameters: + * int maxRecvBufBytesPerServer - an upper limit for receive buffer size + * per server (in byte). If a response from a server exceeds this limit, the + * client will not allocate memory or read response data for it. + * + * int fetchTimeoutSeconds - time limit for fetching responses from all + * servers (in second). After the timeout, the fetch job is stopped and + * available responses are returned. + * + * ByteBuffer requestBuf - request message that is sent to all servers. + * + * Output: + * Responses are stored in an array of ByteBuffers. Index of elements in + * this array corresponds to index of servers in the server list. Content in + * a ByteBuffer may be in one of the following forms: + * 1. First 4 bytes form an integer indicating length of following data, + * then followed by the data. + * 2. First 4 bytes form an integer indicating length of following data, + * then followed by nothing - this happens when the response data size + * exceeds maxRecvBufBytesPerServer, and the client will not read any + * response data. + * 3. No data in the ByteBuffer - this happens when the server does not + * return any response within fetchTimeoutSeconds. + * + * In some special cases (no servers are given, fetchTimeoutSeconds less + * than or equal to 0, requestBuf is null), the return is null. + * + * Note: + * It assumes all remote servers are TNonblockingServers and use + * TFramedTransport. + * + */ +public class TNonblockingMultiFetchClient { + + private static final Logger LOGGER = LoggerFactory.getLogger( + TNonblockingMultiFetchClient.class.getName() + ); + + // if the size of the response msg exceeds this limit (in byte), we will + // not read the msg + private int maxRecvBufBytesPerServer; + + // time limit for fetching data from all servers (in second) + private int fetchTimeoutSeconds; + + // store request that will be sent to servers + private ByteBuffer requestBuf; + private ByteBuffer requestBufDuplication; + + // a list of remote servers + private List servers; + + // store fetch results + private TNonblockingMultiFetchStats stats; + private ByteBuffer[] recvBuf; + + public TNonblockingMultiFetchClient(int maxRecvBufBytesPerServer, + int fetchTimeoutSeconds, ByteBuffer requestBuf, + List servers) { + this.maxRecvBufBytesPerServer = maxRecvBufBytesPerServer; + this.fetchTimeoutSeconds = fetchTimeoutSeconds; + this.requestBuf = requestBuf; + this.servers = servers; + + stats = new TNonblockingMultiFetchStats(); + recvBuf = null; + } + + public synchronized int getMaxRecvBufBytesPerServer() { + return maxRecvBufBytesPerServer; + } + + public synchronized int getFetchTimeoutSeconds() { + return fetchTimeoutSeconds; + } + + /** + * return a duplication of requestBuf, so that requestBuf will not + * be modified by others. + */ + public synchronized ByteBuffer getRequestBuf() { + if (requestBuf == null) { + return null; + } else { + if (requestBufDuplication == null) { + requestBufDuplication = requestBuf.duplicate(); + } + return requestBufDuplication; + } + } + + public synchronized List getServerList() { + if (servers == null) { + return null; + } + return Collections.unmodifiableList(servers); + } + + public synchronized TNonblockingMultiFetchStats getFetchStats() { + return stats; + } + + /** + * main entry function for fetching from servers + */ + public synchronized ByteBuffer[] fetch() { + // clear previous results + recvBuf = null; + stats.clear(); + + if (servers == null || servers.size() == 0 || + requestBuf == null || fetchTimeoutSeconds <= 0) { + return recvBuf; + } + + ExecutorService executor = Executors.newSingleThreadExecutor(); + MultiFetch multiFetch = new MultiFetch(); + FutureTask task = new FutureTask(multiFetch, null); + executor.execute(task); + try { + task.get(fetchTimeoutSeconds, TimeUnit.SECONDS); + } catch(InterruptedException ie) { + // attempt to cancel execution of the task. + task.cancel(true); + LOGGER.error("interrupted during fetch: "+ie.toString()); + } catch(ExecutionException ee) { + // attempt to cancel execution of the task. + task.cancel(true); + LOGGER.error("exception during fetch: "+ee.toString()); + } catch(TimeoutException te) { + // attempt to cancel execution of the task. + task.cancel(true); + LOGGER.error("timeout for fetch: "+te.toString()); + } + + executor.shutdownNow(); + multiFetch.close(); + return recvBuf; + } + + /** + * Private class that does real fetch job. + * Users are not allowed to directly use this class, as its run() + * function may run forever. + */ + private class MultiFetch implements Runnable { + private Selector selector; + + /** + * main entry function for fetching. + * + * Server responses are stored in TNonblocingMultiFetchClient.recvBuf, + * and fetch statistics is in TNonblockingMultiFetchClient.stats. + * + * Sanity check for parameters has been done in + * TNonblockingMultiFetchClient before calling this function. + */ + public void run() { + long t1 = System.currentTimeMillis(); + + int numTotalServers = servers.size(); + stats.setNumTotalServers(numTotalServers); + + // buffer for receiving response from servers + recvBuf = new ByteBuffer[numTotalServers]; + // buffer for sending request + ByteBuffer sendBuf[] = new ByteBuffer[numTotalServers]; + long numBytesRead[] = new long[numTotalServers]; + int frameSize[] = new int[numTotalServers]; + boolean hasReadFrameSize[] = new boolean[numTotalServers]; + + try { + selector = Selector.open(); + } catch (IOException e) { + LOGGER.error("selector opens error: "+e.toString()); + return; + } + + for (int i = 0; i < numTotalServers; i++) { + // create buffer to send request to server. + sendBuf[i] = requestBuf.duplicate(); + // create buffer to read response's frame size from server + recvBuf[i] = ByteBuffer.allocate(4); + stats.incTotalRecvBufBytes(4); + + InetSocketAddress server = servers.get(i); + SocketChannel s = null; + SelectionKey key = null; + try { + s = SocketChannel.open(); + s.configureBlocking(false); + // now this method is non-blocking + s.connect(server); + key = s.register(selector, s.validOps()); + // attach index of the key + key.attach(i); + } catch (Exception e) { + stats.incNumConnectErrorServers(); + String err = String.format("set up socket to server %s error: %s", + server.toString(), e.toString()); + LOGGER.error(err); + // free resource + if (s != null) { + try {s.close();} catch (Exception ex) {} + } + if (key != null) { + key.cancel(); + } + } + } + + // wait for events + while (stats.getNumReadCompletedServers() + + stats.getNumConnectErrorServers() < stats.getNumTotalServers()) { + // if the thread is interrupted (e.g., task is cancelled) + if (Thread.currentThread().isInterrupted()) { + return; + } + + try{ + selector.select(); + } catch (Exception e) { + LOGGER.error("selector selects error: "+e.toString()); + continue; + } + + Iterator it = selector.selectedKeys().iterator(); + while (it.hasNext()) { + SelectionKey selKey = it.next(); + it.remove(); + + // get previously attached index + int index = (Integer)selKey.attachment(); + + if (selKey.isValid() && selKey.isConnectable()) { + // if this socket throws an exception (e.g., connection refused), + // print error msg and skip it. + try { + SocketChannel sChannel = (SocketChannel)selKey.channel(); + sChannel.finishConnect(); + } catch (Exception e) { + stats.incNumConnectErrorServers(); + String err = String.format("socket %d connects to server %s " + + "error: %s", + index, servers.get(index).toString(), e.toString()); + LOGGER.error(err); + } + } + + if (selKey.isValid() && selKey.isWritable()) { + if (sendBuf[index].hasRemaining()) { + // if this socket throws an exception, print error msg and + // skip it. + try { + SocketChannel sChannel = (SocketChannel)selKey.channel(); + sChannel.write(sendBuf[index]); + } catch (Exception e) { + String err = String.format("socket %d writes to server %s " + + "error: %s", + index, servers.get(index).toString(), e.toString()); + LOGGER.error(err); + } + } + } + + if (selKey.isValid() && selKey.isReadable()) { + // if this socket throws an exception, print error msg and + // skip it. + try { + SocketChannel sChannel = (SocketChannel)selKey.channel(); + int bytesRead = sChannel.read(recvBuf[index]); + + if (bytesRead > 0) { + numBytesRead[index] += bytesRead; + + if (!hasReadFrameSize[index] && + recvBuf[index].remaining()==0) { + // if the frame size has been read completely, then prepare + // to read the actual frame. + frameSize[index] = recvBuf[index].getInt(0); + + if (frameSize[index] <= 0) { + stats.incNumInvalidFrameSize(); + String err = String.format("Read an invalid frame size %d" + + " from %s. Does the server use TFramedTransport? ", + frameSize[index], servers.get(index).toString()); + LOGGER.error(err); + sChannel.close(); + continue; + } + + if (frameSize[index] + 4 > stats.getMaxResponseBytes()) { + stats.setMaxResponseBytes(frameSize[index]+4); + } + + if (frameSize[index] + 4 > maxRecvBufBytesPerServer) { + stats.incNumOverflowedRecvBuf(); + String err = String.format("Read frame size %d from %s," + + " total buffer size would exceed limit %d", + frameSize[index], servers.get(index).toString(), + maxRecvBufBytesPerServer); + LOGGER.error(err); + sChannel.close(); + continue; + } + + // reallocate buffer for actual frame data + recvBuf[index] = ByteBuffer.allocate(frameSize[index] + 4); + recvBuf[index].putInt(frameSize[index]); + + stats.incTotalRecvBufBytes(frameSize[index]); + hasReadFrameSize[index] = true; + } + + if (hasReadFrameSize[index] && + numBytesRead[index] >= frameSize[index]+4) { + // has read all data + sChannel.close(); + stats.incNumReadCompletedServers(); + long t2 = System.currentTimeMillis(); + stats.setReadTime(t2-t1); + } + } + } catch (Exception e) { + String err = String.format("socket %d reads from server %s " + + "error: %s", + index, servers.get(index).toString(), e.toString()); + LOGGER.error(err); + } + } + } + } + } + + /** + * dispose any resource allocated + */ + public void close() { + try { + if (selector.isOpen()) { + Iterator it = selector.keys().iterator(); + while (it.hasNext()) { + SelectionKey selKey = it.next(); + SocketChannel sChannel = (SocketChannel)selKey.channel(); + sChannel.close(); + } + + selector.close(); + } + } catch (IOException e) { + LOGGER.error("free resource error: "+e.toString()); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TNonblockingMultiFetchStats.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TNonblockingMultiFetchStats.java new file mode 100644 index 00000000..7c4f1a96 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TNonblockingMultiFetchStats.java @@ -0,0 +1,80 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.xiaomi.infra.pegasus.thrift; + +/** + * This class keeps track of statistics for TNonblockinMultiFetchClient. + */ +public class TNonblockingMultiFetchStats { + private int numTotalServers; + private int numReadCompletedServers; + private int numConnectErrorServers; + private int totalRecvBufBytes; + private int maxResponseBytes; + private int numOverflowedRecvBuf; + private int numInvalidFrameSize; + // time from the beginning of fetch() function to the reading finish + // time of the last socket (in milli-second) + private long readTime; + + public TNonblockingMultiFetchStats() { + clear(); + } + + public void clear() { + numTotalServers = 0; + numReadCompletedServers = 0; + numConnectErrorServers = 0; + totalRecvBufBytes = 0; + maxResponseBytes = 0; + numOverflowedRecvBuf = 0; + numInvalidFrameSize = 0; + readTime = 0; + } + + public String toString() { + String stats = String.format("numTotalServers=%d, " + + "numReadCompletedServers=%d, numConnectErrorServers=%d, " + + "numUnresponsiveServers=%d, totalRecvBufBytes=%fM, " + + "maxResponseBytes=%d, numOverflowedRecvBuf=%d, " + + "numInvalidFrameSize=%d, readTime=%dms", + numTotalServers, numReadCompletedServers, numConnectErrorServers, + (numTotalServers-numReadCompletedServers-numConnectErrorServers), + totalRecvBufBytes/1024.0/1024, maxResponseBytes, numOverflowedRecvBuf, + numInvalidFrameSize, readTime); + return stats; + } + + public void setNumTotalServers(int val) { numTotalServers = val; } + public void setMaxResponseBytes(int val) { maxResponseBytes = val; } + public void setReadTime(long val) { readTime = val; } + public void incNumReadCompletedServers() { numReadCompletedServers++; } + public void incNumConnectErrorServers() { numConnectErrorServers++; } + public void incNumOverflowedRecvBuf() { numOverflowedRecvBuf++; } + public void incTotalRecvBufBytes(int val) { totalRecvBufBytes += val; } + public void incNumInvalidFrameSize() { numInvalidFrameSize++; } + + public int getMaxResponseBytes() { return maxResponseBytes; } + public int getNumReadCompletedServers() { return numReadCompletedServers; } + public int getNumConnectErrorServers() { return numConnectErrorServers; } + public int getNumTotalServers() { return numTotalServers; } + public int getNumOverflowedRecvBuf() { return numOverflowedRecvBuf;} + public int getTotalRecvBufBytes() { return totalRecvBufBytes;} + public int getNumInvalidFrameSize() { return numInvalidFrameSize; } + public long getReadTime() { return readTime; } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TProcessor.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TProcessor.java new file mode 100644 index 00000000..3b97879b --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TProcessor.java @@ -0,0 +1,32 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +/** + * A processor is a generic object which operates upon an input stream and + * writes to some output stream. + * + */ +public interface TProcessor { + public boolean process(TProtocol in, TProtocol out) + throws TException; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TProcessorFactory.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TProcessorFactory.java new file mode 100644 index 00000000..616252d0 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TProcessorFactory.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * The default processor factory just returns a singleton + * instance. + */ +public class TProcessorFactory { + + private final TProcessor processor_; + + public TProcessorFactory(TProcessor processor) { + processor_ = processor; + } + + public TProcessor getProcessor(TTransport trans) { + return processor_; + } + + public boolean isAsyncProcessor() { + return processor_ instanceof TAsyncProcessor; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TSerializable.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TSerializable.java new file mode 100644 index 00000000..edec66ea --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TSerializable.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +/** + * Generic base interface for generated Thrift objects. + * + */ +public interface TSerializable { + + /** + * Reads the TObject from the given input protocol. + * + * @param iprot Input protocol + */ + public void read(TProtocol iprot) throws TException; + + /** + * Writes the objects out to the protocol + * + * @param oprot Output protocol + */ + public void write(TProtocol oprot) throws TException; + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TSerializer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TSerializer.java new file mode 100644 index 00000000..420ae917 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TSerializer.java @@ -0,0 +1,110 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift; + +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; + +import com.xiaomi.infra.pegasus.thrift.protocol.TBinaryProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory; +import com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport; + +/** + * Generic utility for easily serializing objects into a byte array or Java + * String. + * + */ +public class TSerializer { + + /** + * This is the byte array that data is actually serialized into + */ + private final ByteArrayOutputStream baos_ = new ByteArrayOutputStream(); + + /** + * This transport wraps that byte array + */ + private final TIOStreamTransport transport_ = new TIOStreamTransport(baos_); + + /** + * Internal protocol used for serializing objects. + */ + private TProtocol protocol_; + + /** + * Create a new TSerializer that uses the TBinaryProtocol by default. + */ + public TSerializer() { + this(new TBinaryProtocol.Factory()); + } + + /** + * Create a new TSerializer. It will use the TProtocol specified by the + * factory that is passed in. + * + * @param protocolFactory Factory to create a protocol + */ + public TSerializer(TProtocolFactory protocolFactory) { + protocol_ = protocolFactory.getProtocol(transport_); + } + + /** + * Serialize the Thrift object into a byte array. The process is simple, + * just clear the byte array output, write the object into it, and grab the + * raw bytes. + * + * @param base The object to serialize + * @return Serialized object in byte[] format + */ + public byte[] serialize(TBase base) throws TException { + baos_.reset(); + base.write(protocol_); + return baos_.toByteArray(); + } + + /** + * Serialize the Thrift object into a Java string, using a specified + * character set for encoding. + * + * @param base The object to serialize + * @param charset Valid JVM charset + * @return Serialized object as a String + */ + public String toString(TBase base, String charset) throws TException { + try { + return new String(serialize(base), charset); + } catch (UnsupportedEncodingException uex) { + throw new TException("JVM DOES NOT SUPPORT ENCODING: " + charset); + } + } + + /** + * Serialize the Thrift object into a Java string, using the default JVM + * charset encoding. + * + * @param base The object to serialize + * @return Serialized object as a String + */ + public String toString(TBase base) throws TException { + return new String(serialize(base)); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TServiceClient.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TServiceClient.java new file mode 100644 index 00000000..a5f5488d --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TServiceClient.java @@ -0,0 +1,91 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.protocol.TMessage; +import com.xiaomi.infra.pegasus.thrift.protocol.TMessageType; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +/** + * A TServiceClient is used to communicate with a TService implementation + * across protocols and transports. + */ +public abstract class TServiceClient { + public TServiceClient(TProtocol prot) { + this(prot, prot); + } + + public TServiceClient(TProtocol iprot, TProtocol oprot) { + iprot_ = iprot; + oprot_ = oprot; + } + + protected TProtocol iprot_; + protected TProtocol oprot_; + + protected int seqid_; + + /** + * Get the TProtocol being used as the input (read) protocol. + * @return the TProtocol being used as the input (read) protocol. + */ + public TProtocol getInputProtocol() { + return this.iprot_; + } + + /** + * Get the TProtocol being used as the output (write) protocol. + * @return the TProtocol being used as the output (write) protocol. + */ + public TProtocol getOutputProtocol() { + return this.oprot_; + } + + protected void sendBase(String methodName, TBase args) throws TException { + sendBase(methodName, args, TMessageType.CALL); + } + + protected void sendBaseOneway(String methodName, TBase args) throws TException { + sendBase(methodName, args, TMessageType.ONEWAY); + } + + private void sendBase(String methodName, TBase args, byte type) throws TException { + oprot_.writeMessageBegin(new TMessage(methodName, type, ++seqid_)); + args.write(oprot_); + oprot_.writeMessageEnd(); + oprot_.getTransport().flush(); + } + + protected void receiveBase(TBase result, String methodName) throws TException { + TMessage msg = iprot_.readMessageBegin(); + if (msg.type == TMessageType.EXCEPTION) { + TApplicationException x = new TApplicationException(); + x.read(iprot_); + iprot_.readMessageEnd(); + throw x; + } + if (msg.seqid != seqid_) { + throw new TApplicationException(TApplicationException.BAD_SEQUENCE_ID, + String.format("%s failed: out of sequence response: expected %d but got %d", methodName, seqid_, msg.seqid)); + } + result.read(iprot_); + iprot_.readMessageEnd(); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TServiceClientFactory.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TServiceClientFactory.java new file mode 100644 index 00000000..bd6432c0 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TServiceClientFactory.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift; + +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; + +/** + * A TServiceClientFactory provides a general way to get a TServiceClient + * connected to a remote TService via a protocol. + * @param + */ +public interface TServiceClientFactory { + /** + * Get a brand-new T using prot as both the input and output protocol. + * @param prot + * @return A brand-new T using prot as both the input and output protocol. + */ + public T getClient(TProtocol prot); + + /** + * Get a brand new T using the specified input and output protocols. The + * input and output protocols may be the same instance. + * @param iprot + * @param oprot + * @return a brand new T using the specified input and output protocols + */ + public T getClient(TProtocol iprot, TProtocol oprot); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/TUnion.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/TUnion.java new file mode 100644 index 00000000..1f736897 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/TUnion.java @@ -0,0 +1,279 @@ +/** + * 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 com.xiaomi.infra.pegasus.thrift; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.xiaomi.infra.pegasus.thrift.protocol.TField; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolException; +import com.xiaomi.infra.pegasus.thrift.protocol.TStruct; +import com.xiaomi.infra.pegasus.thrift.scheme.IScheme; +import com.xiaomi.infra.pegasus.thrift.scheme.SchemeFactory; +import com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme; +import com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme; + +public abstract class TUnion, F extends TFieldIdEnum> implements TBase { + + protected Object value_; + protected F setField_; + + protected TUnion() { + setField_ = null; + value_ = null; + } + + private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); + static { + schemes.put(StandardScheme.class, new TUnionStandardSchemeFactory()); + schemes.put(TupleScheme.class, new TUnionTupleSchemeFactory()); + } + + protected TUnion(F setField, Object value) { + setFieldValue(setField, value); + } + + protected TUnion(TUnion other) { + if (!other.getClass().equals(this.getClass())) { + throw new ClassCastException(); + } + setField_ = other.setField_; + value_ = deepCopyObject(other.value_); + } + + private static Object deepCopyObject(Object o) { + if (o instanceof TBase) { + return ((TBase)o).deepCopy(); + } else if (o instanceof ByteBuffer) { + return TBaseHelper.copyBinary((ByteBuffer)o); + } else if (o instanceof List) { + return deepCopyList((List)o); + } else if (o instanceof Set) { + return deepCopySet((Set)o); + } else if (o instanceof Map) { + return deepCopyMap((Map)o); + } else { + return o; + } + } + + private static Map deepCopyMap(Map map) { + Map copy = new HashMap(); + for (Map.Entry entry : map.entrySet()) { + copy.put(deepCopyObject(entry.getKey()), deepCopyObject(entry.getValue())); + } + return copy; + } + + private static Set deepCopySet(Set set) { + Set copy = new HashSet(); + for (Object o : set) { + copy.add(deepCopyObject(o)); + } + return copy; + } + + private static List deepCopyList(List list) { + List copy = new ArrayList(list.size()); + for (Object o : list) { + copy.add(deepCopyObject(o)); + } + return copy; + } + + public F getSetField() { + return setField_; + } + + public Object getFieldValue() { + return value_; + } + + public Object getFieldValue(F fieldId) { + if (fieldId != setField_) { + throw new IllegalArgumentException("Cannot get the value of field " + fieldId + " because union's set field is " + setField_); + } + + return getFieldValue(); + } + + public Object getFieldValue(int fieldId) { + return getFieldValue(enumForId((short)fieldId)); + } + + public boolean isSet() { + return setField_ != null; + } + + public boolean isSet(F fieldId) { + return setField_ == fieldId; + } + + public boolean isSet(int fieldId) { + return isSet(enumForId((short)fieldId)); + } + + public void read(TProtocol iprot) throws TException { + schemes.get(iprot.getScheme()).getScheme().read(iprot, this); + } + + public void setFieldValue(F fieldId, Object value) { + checkType(fieldId, value); + setField_ = fieldId; + value_ = value; + } + + public void setFieldValue(int fieldId, Object value) { + setFieldValue(enumForId((short)fieldId), value); + } + + public void write(TProtocol oprot) throws TException { + schemes.get(oprot.getScheme()).getScheme().write(oprot, this); + } + + /** + * Implementation should be generated so that we can efficiently type check + * various values. + * @param setField + * @param value + */ + protected abstract void checkType(F setField, Object value) throws ClassCastException; + + /** + * Implementation should be generated to read the right stuff from the wire + * based on the field header. + * @param field + * @return read Object based on the field header, as specified by the argument. + */ + protected abstract Object standardSchemeReadValue(TProtocol iprot, TField field) throws TException; + protected abstract void standardSchemeWriteValue(TProtocol oprot) throws TException; + + protected abstract Object tupleSchemeReadValue(TProtocol iprot, short fieldID) throws TException; + protected abstract void tupleSchemeWriteValue(TProtocol oprot) throws TException; + + protected abstract TStruct getStructDesc(); + + protected abstract TField getFieldDesc(F setField); + + protected abstract F enumForId(short id); + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("<"); + sb.append(this.getClass().getSimpleName()); + sb.append(" "); + + if (getSetField() != null) { + Object v = getFieldValue(); + sb.append(getFieldDesc(getSetField()).name); + sb.append(":"); + if(v instanceof ByteBuffer) { + TBaseHelper.toString((ByteBuffer)v, sb); + } else { + sb.append(v.toString()); + } + } + sb.append(">"); + return sb.toString(); + } + + public final void clear() { + this.setField_ = null; + this.value_ = null; + } + + private static class TUnionStandardSchemeFactory implements SchemeFactory { + public TUnionStandardScheme getScheme() { + return new TUnionStandardScheme(); + } + } + + private static class TUnionStandardScheme extends StandardScheme { + + @Override + public void read(TProtocol iprot, TUnion struct) throws TException { + struct.setField_ = null; + struct.value_ = null; + + iprot.readStructBegin(); + + TField field = iprot.readFieldBegin(); + + struct.value_ = struct.standardSchemeReadValue(iprot, field); + if (struct.value_ != null) { + struct.setField_ = struct.enumForId(field.id); + } + + iprot.readFieldEnd(); + // this is so that we will eat the stop byte. we could put a check here to + // make sure that it actually *is* the stop byte, but it's faster to do it + // this way. + iprot.readFieldBegin(); + iprot.readStructEnd(); + } + + @Override + public void write(TProtocol oprot, TUnion struct) throws TException { + if (struct.getSetField() == null || struct.getFieldValue() == null) { + throw new TProtocolException("Cannot write a TUnion with no set value!"); + } + oprot.writeStructBegin(struct.getStructDesc()); + oprot.writeFieldBegin(struct.getFieldDesc(struct.setField_)); + struct.standardSchemeWriteValue(oprot); + oprot.writeFieldEnd(); + oprot.writeFieldStop(); + oprot.writeStructEnd(); + } + } + + private static class TUnionTupleSchemeFactory implements SchemeFactory { + public TUnionTupleScheme getScheme() { + return new TUnionTupleScheme(); + } + } + + private static class TUnionTupleScheme extends TupleScheme { + + @Override + public void read(TProtocol iprot, TUnion struct) throws TException { + struct.setField_ = null; + struct.value_ = null; + short fieldID = iprot.readI16(); + struct.value_ = struct.tupleSchemeReadValue(iprot, fieldID); + if (struct.value_ != null) { + struct.setField_ = struct.enumForId(fieldID); + } + } + + @Override + public void write(TProtocol oprot, TUnion struct) throws TException { + if (struct.getSetField() == null || struct.getFieldValue() == null) { + throw new TProtocolException("Cannot write a TUnion with no set value!"); + } + oprot.writeI16(struct.setField_.getThriftFieldId()); + struct.tupleSchemeWriteValue(oprot); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/async/AsyncMethodCallback.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/async/AsyncMethodCallback.java new file mode 100644 index 00000000..d3fce0bd --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/async/AsyncMethodCallback.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.xiaomi.infra.pegasus.thrift.async; + +/** + * A handler interface asynchronous clients can implement to receive future + * notice of the results of an asynchronous method call. + * + * @param The return type of the asynchronously invoked method. + */ +public interface AsyncMethodCallback { + /** + * This method will be called when the remote side has completed invoking + * your method call and the result is fully read. For {@code oneway} method + * calls, this method will be called as soon as we have completed writing out + * the request. + * + * @param response The return value of the asynchronously invoked method; + * {@code null} for void methods which includes + * {@code oneway} methods. + */ + void onComplete(T response); + + /** + * This method will be called when there is either an unexpected client-side + * exception like an IOException or else when the remote method raises an + * exception, either declared in the IDL or due to an unexpected server-side + * error. + * + * @param exception The exception encountered processing the the asynchronous + * method call, may be a local exception or an unmarshalled + * remote exception. + */ + void onError(Exception exception); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClient.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClient.java new file mode 100644 index 00000000..fb47a778 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClient.java @@ -0,0 +1,102 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.async; + +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory; +import com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport; + +public abstract class TAsyncClient { + protected final TProtocolFactory ___protocolFactory; + protected final TNonblockingTransport ___transport; + protected final TAsyncClientManager ___manager; + protected TAsyncMethodCall ___currentMethod; + private Exception ___error; + private long ___timeout; + + public TAsyncClient(TProtocolFactory protocolFactory, TAsyncClientManager manager, TNonblockingTransport transport) { + this(protocolFactory, manager, transport, 0); + } + + public TAsyncClient(TProtocolFactory protocolFactory, TAsyncClientManager manager, TNonblockingTransport transport, long timeout) { + this.___protocolFactory = protocolFactory; + this.___manager = manager; + this.___transport = transport; + this.___timeout = timeout; + } + + public TProtocolFactory getProtocolFactory() { + return ___protocolFactory; + } + + public long getTimeout() { + return ___timeout; + } + + public boolean hasTimeout() { + return ___timeout > 0; + } + + public void setTimeout(long timeout) { + this.___timeout = timeout; + } + + /** + * Is the client in an error state? + * @return If client in an error state? + */ + public boolean hasError() { + return ___error != null; + } + + /** + * Get the client's error - returns null if no error + * @return Get the client's error.

returns null if no error + */ + public Exception getError() { + return ___error; + } + + protected void checkReady() { + // Ensure we are not currently executing a method + if (___currentMethod != null) { + throw new IllegalStateException("Client is currently executing another method: " + ___currentMethod.getClass().getName()); + } + + // Ensure we're not in an error state + if (___error != null) { + throw new IllegalStateException("Client has an error!", ___error); + } + } + + /** + * Called by delegate method when finished + */ + protected void onComplete() { + ___currentMethod = null; + } + + /** + * Called by delegate method on error + */ + protected void onError(Exception exception) { + ___transport.close(); + ___currentMethod = null; + ___error = exception; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClientFactory.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClientFactory.java new file mode 100644 index 00000000..916fc6db --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClientFactory.java @@ -0,0 +1,25 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.async; + +import com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport; + +public interface TAsyncClientFactory { + public T getAsyncClient(TNonblockingTransport transport); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClientManager.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClientManager.java new file mode 100644 index 00000000..43d31ac0 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncClientManager.java @@ -0,0 +1,201 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.async; + +import java.io.IOException; +import java.io.Serializable; +import java.nio.channels.ClosedSelectorException; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.spi.SelectorProvider; +import java.util.Comparator; +import java.util.Iterator; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.TimeoutException; + +import com.xiaomi.infra.pegasus.thrift.TException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Contains selector thread which transitions method call objects + */ +public class TAsyncClientManager { + private static final Logger LOGGER = LoggerFactory.getLogger(TAsyncClientManager.class.getName()); + + private final SelectThread selectThread; + private final ConcurrentLinkedQueue pendingCalls = new ConcurrentLinkedQueue(); + + public TAsyncClientManager() throws IOException { + this.selectThread = new SelectThread(); + selectThread.start(); + } + + public void call(TAsyncMethodCall method) throws TException { + if (!isRunning()) { + throw new TException("SelectThread is not running"); + } + method.prepareMethodCall(); + pendingCalls.add(method); + selectThread.getSelector().wakeup(); + } + + public void stop() { + selectThread.finish(); + } + + public boolean isRunning() { + return selectThread.isAlive(); + } + + private class SelectThread extends Thread { + private final Selector selector; + private volatile boolean running; + private final TreeSet timeoutWatchSet = new TreeSet(new TAsyncMethodCallTimeoutComparator()); + + public SelectThread() throws IOException { + this.selector = SelectorProvider.provider().openSelector(); + this.running = true; + this.setName("TAsyncClientManager#SelectorThread " + this.getId()); + + // We don't want to hold up the JVM when shutting down + setDaemon(true); + } + + public Selector getSelector() { + return selector; + } + + public void finish() { + running = false; + selector.wakeup(); + } + + public void run() { + while (running) { + try { + try { + if (timeoutWatchSet.size() == 0) { + // No timeouts, so select indefinitely + selector.select(); + } else { + // We have a timeout pending, so calculate the time until then and select appropriately + long nextTimeout = timeoutWatchSet.first().getTimeoutTimestamp(); + long selectTime = nextTimeout - System.currentTimeMillis(); + if (selectTime > 0) { + // Next timeout is in the future, select and wake up then + selector.select(selectTime); + } else { + // Next timeout is now or in past, select immediately so we can time out + selector.selectNow(); + } + } + } catch (IOException e) { + LOGGER.error("Caught IOException in TAsyncClientManager!", e); + } + transitionMethods(); + timeoutMethods(); + startPendingMethods(); + } catch (Exception exception) { + LOGGER.error("Ignoring uncaught exception in SelectThread", exception); + } + } + + try { + selector.close(); + } catch (IOException ex) { + LOGGER.warn("Could not close selector. This may result in leaked resources!", ex); + } + } + + // Transition methods for ready keys + private void transitionMethods() { + try { + Iterator keys = selector.selectedKeys().iterator(); + while (keys.hasNext()) { + SelectionKey key = keys.next(); + keys.remove(); + if (!key.isValid()) { + // this can happen if the method call experienced an error and the + // key was cancelled. can also happen if we timeout a method, which + // results in a channel close. + // just skip + continue; + } + TAsyncMethodCall methodCall = (TAsyncMethodCall)key.attachment(); + methodCall.transition(key); + + // If done or error occurred, remove from timeout watch set + if (methodCall.isFinished() || methodCall.getClient().hasError()) { + timeoutWatchSet.remove(methodCall); + } + } + } catch (ClosedSelectorException e) { + LOGGER.error("Caught ClosedSelectorException in TAsyncClientManager!", e); + } + } + + // Timeout any existing method calls + private void timeoutMethods() { + Iterator iterator = timeoutWatchSet.iterator(); + long currentTime = System.currentTimeMillis(); + while (iterator.hasNext()) { + TAsyncMethodCall methodCall = iterator.next(); + if (currentTime >= methodCall.getTimeoutTimestamp()) { + iterator.remove(); + methodCall.onError(new TimeoutException("Operation " + methodCall.getClass() + " timed out after " + (currentTime - methodCall.getStartTime()) + " ms.")); + } else { + break; + } + } + } + + // Start any new calls + private void startPendingMethods() { + TAsyncMethodCall methodCall; + while ((methodCall = pendingCalls.poll()) != null) { + // Catch registration errors. method will catch transition errors and cleanup. + try { + methodCall.start(selector); + + // If timeout specified and first transition went smoothly, add to timeout watch set + TAsyncClient client = methodCall.getClient(); + if (client.hasTimeout() && !client.hasError()) { + timeoutWatchSet.add(methodCall); + } + } catch (Exception exception) { + LOGGER.warn("Caught exception in TAsyncClientManager!", exception); + methodCall.onError(exception); + } + } + } + } + + /** Comparator used in TreeSet */ + private static class TAsyncMethodCallTimeoutComparator implements Comparator, Serializable { + public int compare(TAsyncMethodCall left, TAsyncMethodCall right) { + if (left.getTimeoutTimestamp() == right.getTimeoutTimestamp()) { + return (int)(left.getSequenceId() - right.getSequenceId()); + } else { + return (int)(left.getTimeoutTimestamp() - right.getTimeoutTimestamp()); + } + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncMethodCall.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncMethodCall.java new file mode 100644 index 00000000..f5bae8f7 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/async/TAsyncMethodCall.java @@ -0,0 +1,284 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.async; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.util.concurrent.atomic.AtomicLong; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory; +import com.xiaomi.infra.pegasus.thrift.transport.TFramedTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TMemoryBuffer; +import com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransportException; + +/** + * Encapsulates an async method call. + *

+ * Need to generate: + *

    + *
  • protected abstract void write_args(TProtocol protocol)
  • + *
  • protected abstract T getResult() throws <Exception_1>, <Exception_2>, ...
  • + *
+ * + * @param The return type of the encapsulated method call. + */ +public abstract class TAsyncMethodCall { + + private static final int INITIAL_MEMORY_BUFFER_SIZE = 128; + private static AtomicLong sequenceIdCounter = new AtomicLong(0); + + public static enum State { + CONNECTING, + WRITING_REQUEST_SIZE, + WRITING_REQUEST_BODY, + READING_RESPONSE_SIZE, + READING_RESPONSE_BODY, + RESPONSE_READ, + ERROR; + } + + /** + * Next step in the call, initialized by start() + */ + private State state = null; + + protected final TNonblockingTransport transport; + private final TProtocolFactory protocolFactory; + protected final TAsyncClient client; + private final AsyncMethodCallback callback; + private final boolean isOneway; + private long sequenceId; + private final long timeout; + + private ByteBuffer sizeBuffer; + private final byte[] sizeBufferArray = new byte[4]; + private ByteBuffer frameBuffer; + + private long startTime = System.currentTimeMillis(); + + protected TAsyncMethodCall(TAsyncClient client, TProtocolFactory protocolFactory, TNonblockingTransport transport, AsyncMethodCallback callback, boolean isOneway) { + this.transport = transport; + this.callback = callback; + this.protocolFactory = protocolFactory; + this.client = client; + this.isOneway = isOneway; + this.sequenceId = TAsyncMethodCall.sequenceIdCounter.getAndIncrement(); + this.timeout = client.getTimeout(); + } + + protected State getState() { + return state; + } + + protected boolean isFinished() { + return state == State.RESPONSE_READ; + } + + protected long getStartTime() { + return startTime; + } + + protected long getSequenceId() { + return sequenceId; + } + + public TAsyncClient getClient() { + return client; + } + + public boolean hasTimeout() { + return timeout > 0; + } + + public long getTimeoutTimestamp() { + return timeout + startTime; + } + + protected abstract void write_args(TProtocol protocol) throws TException; + + protected abstract T getResult() throws Exception; + + /** + * Initialize buffers. + * @throws TException if buffer initialization fails + */ + protected void prepareMethodCall() throws TException { + TMemoryBuffer memoryBuffer = new TMemoryBuffer(INITIAL_MEMORY_BUFFER_SIZE); + TProtocol protocol = protocolFactory.getProtocol(memoryBuffer); + write_args(protocol); + + int length = memoryBuffer.length(); + frameBuffer = ByteBuffer.wrap(memoryBuffer.getArray(), 0, length); + + TFramedTransport.encodeFrameSize(length, sizeBufferArray); + sizeBuffer = ByteBuffer.wrap(sizeBufferArray); + } + + /** + * Register with selector and start first state, which could be either connecting or writing. + * @throws IOException if register or starting fails + */ + void start(Selector sel) throws IOException { + SelectionKey key; + if (transport.isOpen()) { + state = State.WRITING_REQUEST_SIZE; + key = transport.registerSelector(sel, SelectionKey.OP_WRITE); + } else { + state = State.CONNECTING; + key = transport.registerSelector(sel, SelectionKey.OP_CONNECT); + + // non-blocking connect can complete immediately, + // in which case we should not expect the OP_CONNECT + if (transport.startConnect()) { + registerForFirstWrite(key); + } + } + + key.attach(this); + } + + void registerForFirstWrite(SelectionKey key) throws IOException { + state = State.WRITING_REQUEST_SIZE; + key.interestOps(SelectionKey.OP_WRITE); + } + + protected ByteBuffer getFrameBuffer() { + return frameBuffer; + } + + /** + * Transition to next state, doing whatever work is required. Since this + * method is only called by the selector thread, we can make changes to our + * select interests without worrying about concurrency. + * @param key + */ + void transition(SelectionKey key) { + // Ensure key is valid + if (!key.isValid()) { + key.cancel(); + Exception e = new TTransportException("Selection key not valid!"); + onError(e); + return; + } + + // Transition function + try { + switch (state) { + case CONNECTING: + doConnecting(key); + break; + case WRITING_REQUEST_SIZE: + doWritingRequestSize(); + break; + case WRITING_REQUEST_BODY: + doWritingRequestBody(key); + break; + case READING_RESPONSE_SIZE: + doReadingResponseSize(); + break; + case READING_RESPONSE_BODY: + doReadingResponseBody(key); + break; + default: // RESPONSE_READ, ERROR, or bug + throw new IllegalStateException("Method call in state " + state + + " but selector called transition method. Seems like a bug..."); + } + } catch (Exception e) { + key.cancel(); + key.attach(null); + onError(e); + } + } + + protected void onError(Exception e) { + client.onError(e); + callback.onError(e); + state = State.ERROR; + } + + private void doReadingResponseBody(SelectionKey key) throws IOException { + if (transport.read(frameBuffer) < 0) { + throw new IOException("Read call frame failed"); + } + if (frameBuffer.remaining() == 0) { + cleanUpAndFireCallback(key); + } + } + + private void cleanUpAndFireCallback(SelectionKey key) { + state = State.RESPONSE_READ; + key.interestOps(0); + // this ensures that the TAsyncMethod instance doesn't hang around + key.attach(null); + try { + T result = this.getResult(); + client.onComplete(); + callback.onComplete(result); + } catch (Exception e) { + key.cancel(); + onError(e); + } + } + + private void doReadingResponseSize() throws IOException { + if (transport.read(sizeBuffer) < 0) { + throw new IOException("Read call frame size failed"); + } + if (sizeBuffer.remaining() == 0) { + state = State.READING_RESPONSE_BODY; + frameBuffer = ByteBuffer.allocate(TFramedTransport.decodeFrameSize(sizeBufferArray)); + } + } + + private void doWritingRequestBody(SelectionKey key) throws IOException { + if (transport.write(frameBuffer) < 0) { + throw new IOException("Write call frame failed"); + } + if (frameBuffer.remaining() == 0) { + if (isOneway) { + cleanUpAndFireCallback(key); + } else { + state = State.READING_RESPONSE_SIZE; + sizeBuffer.rewind(); // Prepare to read incoming frame size + key.interestOps(SelectionKey.OP_READ); + } + } + } + + private void doWritingRequestSize() throws IOException { + if (transport.write(sizeBuffer) < 0) { + throw new IOException("Write call frame size failed"); + } + if (sizeBuffer.remaining() == 0) { + state = State.WRITING_REQUEST_BODY; + } + } + + private void doConnecting(SelectionKey key) throws IOException { + if (!key.isConnectable() || !transport.finishConnect()) { + throw new IOException("not connectable or finishConnect returned false after we got an OP_CONNECT"); + } + registerForFirstWrite(key); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/EnumMetaData.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/EnumMetaData.java new file mode 100644 index 00000000..d10ffe0f --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/EnumMetaData.java @@ -0,0 +1,31 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.meta_data; + +import com.xiaomi.infra.pegasus.thrift.TEnum; + +public class EnumMetaData extends FieldValueMetaData { + public final Class enumClass; + + public EnumMetaData(byte type, Class sClass){ + super(type); + this.enumClass = sClass; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/FieldMetaData.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/FieldMetaData.java new file mode 100644 index 00000000..470325fb --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/FieldMetaData.java @@ -0,0 +1,70 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.meta_data; + +import java.util.HashMap; +import java.util.Map; +import com.xiaomi.infra.pegasus.thrift.TBase; +import com.xiaomi.infra.pegasus.thrift.TFieldIdEnum; + +/** + * This class is used to store meta data about thrift fields. Every field in a + * a struct should have a corresponding instance of this class describing it. + * + */ +public class FieldMetaData implements java.io.Serializable { + public final String fieldName; + public final byte requirementType; + public final FieldValueMetaData valueMetaData; + private static Map, Map> structMap; + + static { + structMap = new HashMap, Map>(); + } + + public FieldMetaData(String name, byte req, FieldValueMetaData vMetaData){ + this.fieldName = name; + this.requirementType = req; + this.valueMetaData = vMetaData; + } + + public static synchronized void addStructMetaDataMap(Class sClass, Map map){ + structMap.put(sClass, map); + } + + /** + * Returns a map with metadata (i.e. instances of FieldMetaData) that + * describe the fields of the given class. + * + * @param sClass The TBase class for which the metadata map is requested + */ + public static synchronized Map getStructMetaDataMap(Class sClass){ + if (!structMap.containsKey(sClass)){ // Load class if it hasn't been loaded + try{ + sClass.newInstance(); + } catch (InstantiationException e){ + throw new RuntimeException("InstantiationException for TBase class: " + sClass.getName() + ", message: " + e.getMessage()); + } catch (IllegalAccessException e){ + throw new RuntimeException("IllegalAccessException for TBase class: " + sClass.getName() + ", message: " + e.getMessage()); + } + } + return structMap.get(sClass); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/FieldValueMetaData.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/FieldValueMetaData.java new file mode 100644 index 00000000..653af16b --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/FieldValueMetaData.java @@ -0,0 +1,72 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.meta_data; + +import com.xiaomi.infra.pegasus.thrift.protocol.TType; + +/** + * FieldValueMetaData and collection of subclasses to store metadata about + * the value(s) of a field + */ +public class FieldValueMetaData implements java.io.Serializable { + public final byte type; + + private final boolean isTypedefType; + private final String typedefName; + private final boolean isBinary; + + public FieldValueMetaData(byte type, boolean binary) { + this.type = type; + this.isTypedefType = false; + this.typedefName = null; + this.isBinary = binary; + } + + public FieldValueMetaData(byte type) { + this(type, false); + } + + public FieldValueMetaData(byte type, String typedefName) { + this.type = type; + this.isTypedefType = true; + this.typedefName = typedefName; + this.isBinary = false; + } + + public boolean isTypedef() { + return isTypedefType; + } + + public String getTypedefName() { + return typedefName; + } + + public boolean isStruct() { + return type == TType.STRUCT; + } + + public boolean isContainer() { + return type == TType.LIST || type == TType.MAP || type == TType.SET; + } + + public boolean isBinary() { + return isBinary; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/ListMetaData.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/ListMetaData.java new file mode 100644 index 00000000..ac85e6b3 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/ListMetaData.java @@ -0,0 +1,29 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.meta_data; + +public class ListMetaData extends FieldValueMetaData { + public final FieldValueMetaData elemMetaData; + + public ListMetaData(byte type, FieldValueMetaData eMetaData){ + super(type); + this.elemMetaData = eMetaData; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/MapMetaData.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/MapMetaData.java new file mode 100644 index 00000000..53095412 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/MapMetaData.java @@ -0,0 +1,31 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.meta_data; + +public class MapMetaData extends FieldValueMetaData { + public final FieldValueMetaData keyMetaData; + public final FieldValueMetaData valueMetaData; + + public MapMetaData(byte type, FieldValueMetaData kMetaData, FieldValueMetaData vMetaData){ + super(type); + this.keyMetaData = kMetaData; + this.valueMetaData = vMetaData; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/SetMetaData.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/SetMetaData.java new file mode 100644 index 00000000..1f073896 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/SetMetaData.java @@ -0,0 +1,29 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.meta_data; + +public class SetMetaData extends FieldValueMetaData { + public final FieldValueMetaData elemMetaData; + + public SetMetaData(byte type, FieldValueMetaData eMetaData){ + super(type); + this.elemMetaData = eMetaData; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/StructMetaData.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/StructMetaData.java new file mode 100644 index 00000000..2a957ce9 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/meta_data/StructMetaData.java @@ -0,0 +1,31 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.meta_data; + +import com.xiaomi.infra.pegasus.thrift.TBase; + +public class StructMetaData extends FieldValueMetaData { + public final Class structClass; + + public StructMetaData(byte type, Class sClass){ + super(type); + this.structClass = sClass; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TBase64Utils.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TBase64Utils.java new file mode 100644 index 00000000..8e33e373 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TBase64Utils.java @@ -0,0 +1,127 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +/** + * Class for encoding and decoding Base64 data. + * + * This class is kept at package level because the interface does no input + * validation and is therefore too low-level for generalized reuse. + * + * Note also that the encoding does not pad with equal signs , as discussed in + * section 2.2 of the RFC (http://www.faqs.org/rfcs/rfc3548.html). Furthermore, + * bad data encountered when decoding is neither rejected or ignored but simply + * results in bad decoded data -- this is not in compliance with the RFC but is + * done in the interest of performance. + * + */ +class TBase64Utils { + + private static final String ENCODE_TABLE = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + /** + * Encode len bytes of data in src at offset srcOff, storing the result into + * dst at offset dstOff. len must be 1, 2, or 3. dst must have at least len+1 + * bytes of space at dstOff. src and dst should not be the same object. This + * method does no validation of the input values in the interest of + * performance. + * + * @param src the source of bytes to encode + * @param srcOff the offset into the source to read the unencoded bytes + * @param len the number of bytes to encode (must be 1, 2, or 3). + * @param dst the destination for the encoding + * @param dstOff the offset into the destination to place the encoded bytes + */ + static final void encode(byte[] src, int srcOff, int len, byte[] dst, + int dstOff) { + dst[dstOff] = (byte)ENCODE_TABLE.charAt((src[srcOff] >> 2) & 0x3F); + if (len == 3) { + dst[dstOff + 1] = + (byte)ENCODE_TABLE.charAt( + ((src[srcOff] << 4) & 0x30) | ((src[srcOff+1] >> 4) & 0x0F)); + dst[dstOff + 2] = + (byte)ENCODE_TABLE.charAt( + ((src[srcOff+1] << 2) & 0x3C) | ((src[srcOff+2] >> 6) & 0x03)); + dst[dstOff + 3] = + (byte)ENCODE_TABLE.charAt(src[srcOff+2] & 0x3F); + } + else if (len == 2) { + dst[dstOff+1] = + (byte)ENCODE_TABLE.charAt( + ((src[srcOff] << 4) & 0x30) | ((src[srcOff+1] >> 4) & 0x0F)); + dst[dstOff + 2] = + (byte)ENCODE_TABLE.charAt((src[srcOff+1] << 2) & 0x3C); + } + else { // len == 1) { + dst[dstOff + 1] = + (byte)ENCODE_TABLE.charAt((src[srcOff] << 4) & 0x30); + } + } + + private static final byte[] DECODE_TABLE = { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, + 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, + -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, + 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + }; + + /** + * Decode len bytes of data in src at offset srcOff, storing the result into + * dst at offset dstOff. len must be 2, 3, or 4. dst must have at least len-1 + * bytes of space at dstOff. src and dst may be the same object as long as + * dstoff <= srcOff. This method does no validation of the input values in + * the interest of performance. + * + * @param src the source of bytes to decode + * @param srcOff the offset into the source to read the encoded bytes + * @param len the number of bytes to decode (must be 2, 3, or 4) + * @param dst the destination for the decoding + * @param dstOff the offset into the destination to place the decoded bytes + */ + static final void decode(byte[] src, int srcOff, int len, byte[] dst, + int dstOff) { + dst[dstOff] = (byte) + ((DECODE_TABLE[src[srcOff] & 0x0FF] << 2) | + (DECODE_TABLE[src[srcOff+1] & 0x0FF] >> 4)); + if (len > 2) { + dst[dstOff+1] = (byte) + (((DECODE_TABLE[src[srcOff+1] & 0x0FF] << 4) & 0xF0) | + (DECODE_TABLE[src[srcOff+2] & 0x0FF] >> 2)); + if (len > 3) { + dst[dstOff+2] = (byte) + (((DECODE_TABLE[src[srcOff+2] & 0x0FF] << 6) & 0xC0) | + DECODE_TABLE[src[srcOff+3] & 0x0FF]); + } + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TBinaryProtocol.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TBinaryProtocol.java new file mode 100644 index 00000000..2efb0c6e --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TBinaryProtocol.java @@ -0,0 +1,427 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * Binary protocol implementation for thrift. + * + */ +public class TBinaryProtocol extends TProtocol { + private static final TStruct ANONYMOUS_STRUCT = new TStruct(); + private static final long NO_LENGTH_LIMIT = -1; + + protected static final int VERSION_MASK = 0xffff0000; + protected static final int VERSION_1 = 0x80010000; + + /** + * The maximum number of bytes to read from the transport for + * variable-length fields (such as strings or binary) or {@link #NO_LENGTH_LIMIT} for + * unlimited. + */ + private final long stringLengthLimit_; + + /** + * The maximum number of elements to read from the network for + * containers (maps, sets, lists), or {@link #NO_LENGTH_LIMIT} for unlimited. + */ + private final long containerLengthLimit_; + + protected boolean strictRead_; + protected boolean strictWrite_; + + private final byte[] inoutTemp = new byte[8]; + + /** + * Factory + */ + public static class Factory implements TProtocolFactory { + protected long stringLengthLimit_; + protected long containerLengthLimit_; + protected boolean strictRead_; + protected boolean strictWrite_; + + public Factory() { + this(false, true); + } + + public Factory(boolean strictRead, boolean strictWrite) { + this(strictRead, strictWrite, NO_LENGTH_LIMIT, NO_LENGTH_LIMIT); + } + + public Factory(long stringLengthLimit, long containerLengthLimit) { + this(false, true, stringLengthLimit, containerLengthLimit); + } + + public Factory(boolean strictRead, boolean strictWrite, long stringLengthLimit, long containerLengthLimit) { + stringLengthLimit_ = stringLengthLimit; + containerLengthLimit_ = containerLengthLimit; + strictRead_ = strictRead; + strictWrite_ = strictWrite; + } + + public TProtocol getProtocol(TTransport trans) { + return new TBinaryProtocol(trans, stringLengthLimit_, containerLengthLimit_, strictRead_, strictWrite_); + } + } + + /** + * Constructor + */ + public TBinaryProtocol(TTransport trans) { + this(trans, false, true); + } + + public TBinaryProtocol(TTransport trans, boolean strictRead, boolean strictWrite) { + this(trans, NO_LENGTH_LIMIT, NO_LENGTH_LIMIT, strictRead, strictWrite); + } + + public TBinaryProtocol(TTransport trans, long stringLengthLimit, long containerLengthLimit) { + this(trans, stringLengthLimit, containerLengthLimit, false, true); + } + + public TBinaryProtocol(TTransport trans, long stringLengthLimit, long containerLengthLimit, boolean strictRead, boolean strictWrite) { + super(trans); + stringLengthLimit_ = stringLengthLimit; + containerLengthLimit_ = containerLengthLimit; + strictRead_ = strictRead; + strictWrite_ = strictWrite; + } + + public void writeMessageBegin(TMessage message) throws TException { + if (strictWrite_) { + int version = VERSION_1 | message.type; + writeI32(version); + writeString(message.name); + writeI32(message.seqid); + } else { + writeString(message.name); + writeByte(message.type); + writeI32(message.seqid); + } + } + + public void writeMessageEnd() {} + + public void writeStructBegin(TStruct struct) {} + + public void writeStructEnd() {} + + public void writeFieldBegin(TField field) throws TException { + writeByte(field.type); + writeI16(field.id); + } + + public void writeFieldEnd() {} + + public void writeFieldStop() throws TException { + writeByte(TType.STOP); + } + + public void writeMapBegin(TMap map) throws TException { + writeByte(map.keyType); + writeByte(map.valueType); + writeI32(map.size); + } + + public void writeMapEnd() {} + + public void writeListBegin(TList list) throws TException { + writeByte(list.elemType); + writeI32(list.size); + } + + public void writeListEnd() {} + + public void writeSetBegin(TSet set) throws TException { + writeByte(set.elemType); + writeI32(set.size); + } + + public void writeSetEnd() {} + + public void writeBool(boolean b) throws TException { + writeByte(b ? (byte)1 : (byte)0); + } + + public void writeByte(byte b) throws TException { + inoutTemp[0] = b; + trans_.write(inoutTemp, 0, 1); + } + + public void writeI16(short i16) throws TException { + inoutTemp[0] = (byte)(0xff & (i16 >> 8)); + inoutTemp[1] = (byte)(0xff & (i16)); + trans_.write(inoutTemp, 0, 2); + } + + public void writeI32(int i32) throws TException { + inoutTemp[0] = (byte)(0xff & (i32 >> 24)); + inoutTemp[1] = (byte)(0xff & (i32 >> 16)); + inoutTemp[2] = (byte)(0xff & (i32 >> 8)); + inoutTemp[3] = (byte)(0xff & (i32)); + trans_.write(inoutTemp, 0, 4); + } + + public void writeI64(long i64) throws TException { + inoutTemp[0] = (byte)(0xff & (i64 >> 56)); + inoutTemp[1] = (byte)(0xff & (i64 >> 48)); + inoutTemp[2] = (byte)(0xff & (i64 >> 40)); + inoutTemp[3] = (byte)(0xff & (i64 >> 32)); + inoutTemp[4] = (byte)(0xff & (i64 >> 24)); + inoutTemp[5] = (byte)(0xff & (i64 >> 16)); + inoutTemp[6] = (byte)(0xff & (i64 >> 8)); + inoutTemp[7] = (byte)(0xff & (i64)); + trans_.write(inoutTemp, 0, 8); + } + + public void writeDouble(double dub) throws TException { + writeI64(Double.doubleToLongBits(dub)); + } + + public void writeString(String str) throws TException { + try { + byte[] dat = str.getBytes("UTF-8"); + writeI32(dat.length); + trans_.write(dat, 0, dat.length); + } catch (UnsupportedEncodingException uex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + } + + public void writeBinary(ByteBuffer bin) throws TException { + int length = bin.limit() - bin.position(); + writeI32(length); + trans_.write(bin.array(), bin.position() + bin.arrayOffset(), length); + } + + /** + * Reading methods. + */ + + public TMessage readMessageBegin() throws TException { + int size = readI32(); + if (size < 0) { + int version = size & VERSION_MASK; + if (version != VERSION_1) { + throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in readMessageBegin"); + } + return new TMessage(readString(), (byte)(size & 0x000000ff), readI32()); + } else { + if (strictRead_) { + throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?"); + } + return new TMessage(readStringBody(size), readByte(), readI32()); + } + } + + public void readMessageEnd() {} + + public TStruct readStructBegin() { + return ANONYMOUS_STRUCT; + } + + public void readStructEnd() {} + + public TField readFieldBegin() throws TException { + byte type = readByte(); + short id = type == TType.STOP ? 0 : readI16(); + return new TField("", type, id); + } + + public void readFieldEnd() {} + + public TMap readMapBegin() throws TException { + TMap map = new TMap(readByte(), readByte(), readI32()); + checkContainerReadLength(map.size); + return map; + } + + public void readMapEnd() {} + + public TList readListBegin() throws TException { + TList list = new TList(readByte(), readI32()); + checkContainerReadLength(list.size); + return list; + } + + public void readListEnd() {} + + public TSet readSetBegin() throws TException { + TSet set = new TSet(readByte(), readI32()); + checkContainerReadLength(set.size); + return set; + } + + public void readSetEnd() {} + + public boolean readBool() throws TException { + return (readByte() == 1); + } + + public byte readByte() throws TException { + if (trans_.getBytesRemainingInBuffer() >= 1) { + byte b = trans_.getBuffer()[trans_.getBufferPosition()]; + trans_.consumeBuffer(1); + return b; + } + readAll(inoutTemp, 0, 1); + return inoutTemp[0]; + } + + public short readI16() throws TException { + byte[] buf = inoutTemp; + int off = 0; + + if (trans_.getBytesRemainingInBuffer() >= 2) { + buf = trans_.getBuffer(); + off = trans_.getBufferPosition(); + trans_.consumeBuffer(2); + } else { + readAll(inoutTemp, 0, 2); + } + + return + (short) + (((buf[off] & 0xff) << 8) | + ((buf[off+1] & 0xff))); + } + + public int readI32() throws TException { + byte[] buf = inoutTemp; + int off = 0; + + if (trans_.getBytesRemainingInBuffer() >= 4) { + buf = trans_.getBuffer(); + off = trans_.getBufferPosition(); + trans_.consumeBuffer(4); + } else { + readAll(inoutTemp, 0, 4); + } + return + ((buf[off] & 0xff) << 24) | + ((buf[off+1] & 0xff) << 16) | + ((buf[off+2] & 0xff) << 8) | + ((buf[off+3] & 0xff)); + } + + public long readI64() throws TException { + byte[] buf = inoutTemp; + int off = 0; + + if (trans_.getBytesRemainingInBuffer() >= 8) { + buf = trans_.getBuffer(); + off = trans_.getBufferPosition(); + trans_.consumeBuffer(8); + } else { + readAll(inoutTemp, 0, 8); + } + + return + ((long)(buf[off] & 0xff) << 56) | + ((long)(buf[off+1] & 0xff) << 48) | + ((long)(buf[off+2] & 0xff) << 40) | + ((long)(buf[off+3] & 0xff) << 32) | + ((long)(buf[off+4] & 0xff) << 24) | + ((long)(buf[off+5] & 0xff) << 16) | + ((long)(buf[off+6] & 0xff) << 8) | + ((long)(buf[off+7] & 0xff)); + } + + public double readDouble() throws TException { + return Double.longBitsToDouble(readI64()); + } + + public String readString() throws TException { + int size = readI32(); + + checkStringReadLength(size); + + if (trans_.getBytesRemainingInBuffer() >= size) { + try { + String s = new String(trans_.getBuffer(), trans_.getBufferPosition(), size, "UTF-8"); + trans_.consumeBuffer(size); + return s; + } catch (UnsupportedEncodingException e) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + } + + return readStringBody(size); + } + + public String readStringBody(int size) throws TException { + checkStringReadLength(size); + try { + byte[] buf = new byte[size]; + trans_.readAll(buf, 0, size); + return new String(buf, "UTF-8"); + } catch (UnsupportedEncodingException uex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + } + + public ByteBuffer readBinary() throws TException { + int size = readI32(); + + checkStringReadLength(size); + + if (trans_.getBytesRemainingInBuffer() >= size) { + ByteBuffer bb = ByteBuffer.wrap(trans_.getBuffer(), trans_.getBufferPosition(), size); + trans_.consumeBuffer(size); + return bb; + } + + byte[] buf = new byte[size]; + trans_.readAll(buf, 0, size); + return ByteBuffer.wrap(buf); + } + + private void checkStringReadLength(int length) throws TProtocolException { + if (length < 0) { + throw new TProtocolException(TProtocolException.NEGATIVE_SIZE, + "Negative length: " + length); + } + if (stringLengthLimit_ != NO_LENGTH_LIMIT && length > stringLengthLimit_) { + throw new TProtocolException(TProtocolException.SIZE_LIMIT, + "Length exceeded max allowed: " + length); + } + } + + private void checkContainerReadLength(int length) throws TProtocolException { + if (length < 0) { + throw new TProtocolException(TProtocolException.NEGATIVE_SIZE, + "Negative length: " + length); + } + if (containerLengthLimit_ != NO_LENGTH_LIMIT && length > containerLengthLimit_) { + throw new TProtocolException(TProtocolException.SIZE_LIMIT, + "Length exceeded max allowed: " + length); + } + } + + private int readAll(byte[] buf, int off, int len) throws TException { + return trans_.readAll(buf, off, len); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TCompactProtocol.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TCompactProtocol.java new file mode 100644 index 00000000..09545c21 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TCompactProtocol.java @@ -0,0 +1,908 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; + +import com.xiaomi.infra.pegasus.thrift.ShortStack; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * TCompactProtocol2 is the Java implementation of the compact protocol specified + * in THRIFT-110. The fundamental approach to reducing the overhead of + * structures is a) use variable-length integers all over the place and b) make + * use of unused bits wherever possible. Your savings will obviously vary + * based on the specific makeup of your structs, but in general, the more + * fields, nested structures, short strings and collections, and low-value i32 + * and i64 fields you have, the more benefit you'll see. + */ +public class TCompactProtocol extends TProtocol { + private final static byte[] EMPTY_BYTES = new byte[0]; + private final static ByteBuffer EMPTY_BUFFER = ByteBuffer.wrap(EMPTY_BYTES); + + private final static long NO_LENGTH_LIMIT = -1; + + private final static TStruct ANONYMOUS_STRUCT = new TStruct(""); + private final static TField TSTOP = new TField("", TType.STOP, (short)0); + + private final static byte[] ttypeToCompactType = new byte[16]; + + static { + ttypeToCompactType[TType.STOP] = TType.STOP; + ttypeToCompactType[TType.BOOL] = Types.BOOLEAN_TRUE; + ttypeToCompactType[TType.BYTE] = Types.BYTE; + ttypeToCompactType[TType.I16] = Types.I16; + ttypeToCompactType[TType.I32] = Types.I32; + ttypeToCompactType[TType.I64] = Types.I64; + ttypeToCompactType[TType.DOUBLE] = Types.DOUBLE; + ttypeToCompactType[TType.STRING] = Types.BINARY; + ttypeToCompactType[TType.LIST] = Types.LIST; + ttypeToCompactType[TType.SET] = Types.SET; + ttypeToCompactType[TType.MAP] = Types.MAP; + ttypeToCompactType[TType.STRUCT] = Types.STRUCT; + } + + /** + * TProtocolFactory that produces TCompactProtocols. + */ + public static class Factory implements TProtocolFactory { + private final long stringLengthLimit_; + private final long containerLengthLimit_; + + public Factory() { + this(NO_LENGTH_LIMIT, NO_LENGTH_LIMIT); + } + + public Factory(long stringLengthLimit) { + this(stringLengthLimit, NO_LENGTH_LIMIT); + } + + public Factory(long stringLengthLimit, long containerLengthLimit) { + this.containerLengthLimit_ = containerLengthLimit; + this.stringLengthLimit_ = stringLengthLimit; + } + + public TProtocol getProtocol(TTransport trans) { + return new TCompactProtocol(trans, stringLengthLimit_, containerLengthLimit_); + } + } + + private static final byte PROTOCOL_ID = (byte)0x82; + private static final byte VERSION = 1; + private static final byte VERSION_MASK = 0x1f; // 0001 1111 + private static final byte TYPE_MASK = (byte)0xE0; // 1110 0000 + private static final byte TYPE_BITS = 0x07; // 0000 0111 + private static final int TYPE_SHIFT_AMOUNT = 5; + + /** + * All of the on-wire type codes. + */ + private static class Types { + public static final byte BOOLEAN_TRUE = 0x01; + public static final byte BOOLEAN_FALSE = 0x02; + public static final byte BYTE = 0x03; + public static final byte I16 = 0x04; + public static final byte I32 = 0x05; + public static final byte I64 = 0x06; + public static final byte DOUBLE = 0x07; + public static final byte BINARY = 0x08; + public static final byte LIST = 0x09; + public static final byte SET = 0x0A; + public static final byte MAP = 0x0B; + public static final byte STRUCT = 0x0C; + } + + /** + * Used to keep track of the last field for the current and previous structs, + * so we can do the delta stuff. + */ + private ShortStack lastField_ = new ShortStack(15); + + private short lastFieldId_ = 0; + + /** + * If we encounter a boolean field begin, save the TField here so it can + * have the value incorporated. + */ + private TField booleanField_ = null; + + /** + * If we read a field header, and it's a boolean field, save the boolean + * value here so that readBool can use it. + */ + private Boolean boolValue_ = null; + + /** + * The maximum number of bytes to read from the transport for + * variable-length fields (such as strings or binary) or {@link #NO_LENGTH_LIMIT} for + * unlimited. + */ + private final long stringLengthLimit_; + + /** + * The maximum number of elements to read from the network for + * containers (maps, sets, lists), or {@link #NO_LENGTH_LIMIT} for unlimited. + */ + private final long containerLengthLimit_; + + /** + * Temporary buffer used for various operations that would otherwise require a + * small allocation. + */ + private final byte[] temp = new byte[10]; + + /** + * Create a TCompactProtocol. + * + * @param transport the TTransport object to read from or write to. + * @param stringLengthLimit the maximum number of bytes to read for + * variable-length fields. + * @param containerLengthLimit the maximum number of elements to read + * for containers. + */ + public TCompactProtocol(TTransport transport, long stringLengthLimit, long containerLengthLimit) { + super(transport); + this.stringLengthLimit_ = stringLengthLimit; + this.containerLengthLimit_ = containerLengthLimit; + } + + /** + * Create a TCompactProtocol. + * + * @param transport the TTransport object to read from or write to. + * @param stringLengthLimit the maximum number of bytes to read for + * variable-length fields. + * @deprecated Use constructor specifying both string limit and container limit instead + */ + @Deprecated + public TCompactProtocol(TTransport transport, long stringLengthLimit) { + this(transport, stringLengthLimit, NO_LENGTH_LIMIT); + } + + /** + * Create a TCompactProtocol. + * + * @param transport the TTransport object to read from or write to. + */ + public TCompactProtocol(TTransport transport) { + this(transport, NO_LENGTH_LIMIT, NO_LENGTH_LIMIT); + } + + @Override + public void reset() { + lastField_.clear(); + lastFieldId_ = 0; + } + + // + // Public Writing methods. + // + + /** + * Write a message header to the wire. Compact Protocol messages contain the + * protocol version so we can migrate forwards in the future if need be. + */ + public void writeMessageBegin(TMessage message) throws TException { + writeByteDirect(PROTOCOL_ID); + writeByteDirect((VERSION & VERSION_MASK) | ((message.type << TYPE_SHIFT_AMOUNT) & TYPE_MASK)); + writeVarint32(message.seqid); + writeString(message.name); + } + + /** + * Write a struct begin. This doesn't actually put anything on the wire. We + * use it as an opportunity to put special placeholder markers on the field + * stack so we can get the field id deltas correct. + */ + public void writeStructBegin(TStruct struct) throws TException { + lastField_.push(lastFieldId_); + lastFieldId_ = 0; + } + + /** + * Write a struct end. This doesn't actually put anything on the wire. We use + * this as an opportunity to pop the last field from the current struct off + * of the field stack. + */ + public void writeStructEnd() throws TException { + lastFieldId_ = lastField_.pop(); + } + + /** + * Write a field header containing the field id and field type. If the + * difference between the current field id and the last one is small (< 15), + * then the field id will be encoded in the 4 MSB as a delta. Otherwise, the + * field id will follow the type header as a zigzag varint. + */ + public void writeFieldBegin(TField field) throws TException { + if (field.type == TType.BOOL) { + // we want to possibly include the value, so we'll wait. + booleanField_ = field; + } else { + writeFieldBeginInternal(field, (byte)-1); + } + } + + /** + * The workhorse of writeFieldBegin. It has the option of doing a + * 'type override' of the type header. This is used specifically in the + * boolean field case. + */ + private void writeFieldBeginInternal(TField field, byte typeOverride) throws TException { + // short lastField = lastField_.pop(); + + // if there's a type override, use that. + byte typeToWrite = typeOverride == -1 ? getCompactType(field.type) : typeOverride; + + // check if we can use delta encoding for the field id + if (field.id > lastFieldId_ && field.id - lastFieldId_ <= 15) { + // write them together + writeByteDirect((field.id - lastFieldId_) << 4 | typeToWrite); + } else { + // write them separate + writeByteDirect(typeToWrite); + writeI16(field.id); + } + + lastFieldId_ = field.id; + // lastField_.push(field.id); + } + + /** + * Write the STOP symbol so we know there are no more fields in this struct. + */ + public void writeFieldStop() throws TException { + writeByteDirect(TType.STOP); + } + + /** + * Write a map header. If the map is empty, omit the key and value type + * headers, as we don't need any additional information to skip it. + */ + public void writeMapBegin(TMap map) throws TException { + if (map.size == 0) { + writeByteDirect(0); + } else { + writeVarint32(map.size); + writeByteDirect(getCompactType(map.keyType) << 4 | getCompactType(map.valueType)); + } + } + + /** + * Write a list header. + */ + public void writeListBegin(TList list) throws TException { + writeCollectionBegin(list.elemType, list.size); + } + + /** + * Write a set header. + */ + public void writeSetBegin(TSet set) throws TException { + writeCollectionBegin(set.elemType, set.size); + } + + /** + * Write a boolean value. Potentially, this could be a boolean field, in + * which case the field header info isn't written yet. If so, decide what the + * right type header is for the value and then write the field header. + * Otherwise, write a single byte. + */ + public void writeBool(boolean b) throws TException { + if (booleanField_ != null) { + // we haven't written the field header yet + writeFieldBeginInternal(booleanField_, b ? Types.BOOLEAN_TRUE : Types.BOOLEAN_FALSE); + booleanField_ = null; + } else { + // we're not part of a field, so just write the value. + writeByteDirect(b ? Types.BOOLEAN_TRUE : Types.BOOLEAN_FALSE); + } + } + + /** + * Write a byte. Nothing to see here! + */ + public void writeByte(byte b) throws TException { + writeByteDirect(b); + } + + /** + * Write an I16 as a zigzag varint. + */ + public void writeI16(short i16) throws TException { + writeVarint32(intToZigZag(i16)); + } + + /** + * Write an i32 as a zigzag varint. + */ + public void writeI32(int i32) throws TException { + writeVarint32(intToZigZag(i32)); + } + + /** + * Write an i64 as a zigzag varint. + */ + public void writeI64(long i64) throws TException { + writeVarint64(longToZigzag(i64)); + } + + /** + * Write a double to the wire as 8 bytes. + */ + public void writeDouble(double dub) throws TException { + fixedLongToBytes(Double.doubleToLongBits(dub), temp, 0); + trans_.write(temp, 0, 8); + } + + /** + * Write a string to the wire with a varint size preceding. + */ + public void writeString(String str) throws TException { + try { + byte[] bytes = str.getBytes("UTF-8"); + writeBinary(bytes, 0, bytes.length); + } catch (UnsupportedEncodingException e) { + throw new TException("UTF-8 not supported!"); + } + } + + /** + * Write a byte array, using a varint for the size. + */ + public void writeBinary(ByteBuffer bin) throws TException { + int length = bin.limit() - bin.position(); + writeBinary(bin.array(), bin.position() + bin.arrayOffset(), length); + } + + private void writeBinary(byte[] buf, int offset, int length) throws TException { + writeVarint32(length); + trans_.write(buf, offset, length); + } + + // + // These methods are called by structs, but don't actually have any wire + // output or purpose. + // + + public void writeMessageEnd() throws TException {} + public void writeMapEnd() throws TException {} + public void writeListEnd() throws TException {} + public void writeSetEnd() throws TException {} + public void writeFieldEnd() throws TException {} + + // + // Internal writing methods + // + + /** + * Abstract method for writing the start of lists and sets. List and sets on + * the wire differ only by the type indicator. + */ + protected void writeCollectionBegin(byte elemType, int size) throws TException { + if (size <= 14) { + writeByteDirect(size << 4 | getCompactType(elemType)); + } else { + writeByteDirect(0xf0 | getCompactType(elemType)); + writeVarint32(size); + } + } + + /** + * Write an i32 as a varint. Results in 1-5 bytes on the wire. + * TODO: make a permanent buffer like writeVarint64? + */ + private void writeVarint32(int n) throws TException { + int idx = 0; + while (true) { + if ((n & ~0x7F) == 0) { + temp[idx++] = (byte)n; + // writeByteDirect((byte)n); + break; + // return; + } else { + temp[idx++] = (byte)((n & 0x7F) | 0x80); + // writeByteDirect((byte)((n & 0x7F) | 0x80)); + n >>>= 7; + } + } + trans_.write(temp, 0, idx); + } + + /** + * Write an i64 as a varint. Results in 1-10 bytes on the wire. + */ + private void writeVarint64(long n) throws TException { + int idx = 0; + while (true) { + if ((n & ~0x7FL) == 0) { + temp[idx++] = (byte)n; + break; + } else { + temp[idx++] = ((byte)((n & 0x7F) | 0x80)); + n >>>= 7; + } + } + trans_.write(temp, 0, idx); + } + + /** + * Convert l into a zigzag long. This allows negative numbers to be + * represented compactly as a varint. + */ + private long longToZigzag(long l) { + return (l << 1) ^ (l >> 63); + } + + /** + * Convert n into a zigzag int. This allows negative numbers to be + * represented compactly as a varint. + */ + private int intToZigZag(int n) { + return (n << 1) ^ (n >> 31); + } + + /** + * Convert a long into little-endian bytes in buf starting at off and going + * until off+7. + */ + private void fixedLongToBytes(long n, byte[] buf, int off) { + buf[off+0] = (byte)( n & 0xff); + buf[off+1] = (byte)((n >> 8 ) & 0xff); + buf[off+2] = (byte)((n >> 16) & 0xff); + buf[off+3] = (byte)((n >> 24) & 0xff); + buf[off+4] = (byte)((n >> 32) & 0xff); + buf[off+5] = (byte)((n >> 40) & 0xff); + buf[off+6] = (byte)((n >> 48) & 0xff); + buf[off+7] = (byte)((n >> 56) & 0xff); + } + + /** + * Writes a byte without any possibility of all that field header nonsense. + * Used internally by other writing methods that know they need to write a byte. + */ + private void writeByteDirect(byte b) throws TException { + temp[0] = b; + trans_.write(temp, 0, 1); + } + + /** + * Writes a byte without any possibility of all that field header nonsense. + */ + private void writeByteDirect(int n) throws TException { + writeByteDirect((byte)n); + } + + + // + // Reading methods. + // + + /** + * Read a message header. + */ + public TMessage readMessageBegin() throws TException { + byte protocolId = readByte(); + if (protocolId != PROTOCOL_ID) { + throw new TProtocolException("Expected protocol id " + Integer.toHexString(PROTOCOL_ID) + " but got " + Integer.toHexString(protocolId)); + } + byte versionAndType = readByte(); + byte version = (byte)(versionAndType & VERSION_MASK); + if (version != VERSION) { + throw new TProtocolException("Expected version " + VERSION + " but got " + version); + } + byte type = (byte)((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS); + int seqid = readVarint32(); + String messageName = readString(); + return new TMessage(messageName, type, seqid); + } + + /** + * Read a struct begin. There's nothing on the wire for this, but it is our + * opportunity to push a new struct begin marker onto the field stack. + */ + public TStruct readStructBegin() throws TException { + lastField_.push(lastFieldId_); + lastFieldId_ = 0; + return ANONYMOUS_STRUCT; + } + + /** + * Doesn't actually consume any wire data, just removes the last field for + * this struct from the field stack. + */ + public void readStructEnd() throws TException { + // consume the last field we read off the wire. + lastFieldId_ = lastField_.pop(); + } + + /** + * Read a field header off the wire. + */ + public TField readFieldBegin() throws TException { + byte type = readByte(); + + // if it's a stop, then we can return immediately, as the struct is over. + if (type == TType.STOP) { + return TSTOP; + } + + short fieldId; + + // mask off the 4 MSB of the type header. it could contain a field id delta. + short modifier = (short)((type & 0xf0) >> 4); + if (modifier == 0) { + // not a delta. look ahead for the zigzag varint field id. + fieldId = readI16(); + } else { + // has a delta. add the delta to the last read field id. + fieldId = (short)(lastFieldId_ + modifier); + } + + TField field = new TField("", getTType((byte)(type & 0x0f)), fieldId); + + // if this happens to be a boolean field, the value is encoded in the type + if (isBoolType(type)) { + // save the boolean value in a special instance variable. + boolValue_ = (byte)(type & 0x0f) == Types.BOOLEAN_TRUE ? Boolean.TRUE : Boolean.FALSE; + } + + // push the new field onto the field stack so we can keep the deltas going. + lastFieldId_ = field.id; + return field; + } + + /** + * Read a map header off the wire. If the size is zero, skip reading the key + * and value type. This means that 0-length maps will yield TMaps without the + * "correct" types. + */ + public TMap readMapBegin() throws TException { + int size = readVarint32(); + checkContainerReadLength(size); + byte keyAndValueType = size == 0 ? 0 : readByte(); + return new TMap(getTType((byte)(keyAndValueType >> 4)), getTType((byte)(keyAndValueType & 0xf)), size); + } + + /** + * Read a list header off the wire. If the list size is 0-14, the size will + * be packed into the element type header. If it's a longer list, the 4 MSB + * of the element type header will be 0xF, and a varint will follow with the + * true size. + */ + public TList readListBegin() throws TException { + byte size_and_type = readByte(); + int size = (size_and_type >> 4) & 0x0f; + if (size == 15) { + size = readVarint32(); + } + checkContainerReadLength(size); + byte type = getTType(size_and_type); + return new TList(type, size); + } + + /** + * Read a set header off the wire. If the set size is 0-14, the size will + * be packed into the element type header. If it's a longer set, the 4 MSB + * of the element type header will be 0xF, and a varint will follow with the + * true size. + */ + public TSet readSetBegin() throws TException { + return new TSet(readListBegin()); + } + + /** + * Read a boolean off the wire. If this is a boolean field, the value should + * already have been read during readFieldBegin, so we'll just consume the + * pre-stored value. Otherwise, read a byte. + */ + public boolean readBool() throws TException { + if (boolValue_ != null) { + boolean result = boolValue_.booleanValue(); + boolValue_ = null; + return result; + } + return readByte() == Types.BOOLEAN_TRUE; + } + + /** + * Read a single byte off the wire. Nothing interesting here. + */ + public byte readByte() throws TException { + byte b; + if (trans_.getBytesRemainingInBuffer() > 0) { + b = trans_.getBuffer()[trans_.getBufferPosition()]; + trans_.consumeBuffer(1); + } else { + trans_.readAll(temp, 0, 1); + b = temp[0]; + } + return b; + } + + /** + * Read an i16 from the wire as a zigzag varint. + */ + public short readI16() throws TException { + return (short)zigzagToInt(readVarint32()); + } + + /** + * Read an i32 from the wire as a zigzag varint. + */ + public int readI32() throws TException { + return zigzagToInt(readVarint32()); + } + + /** + * Read an i64 from the wire as a zigzag varint. + */ + public long readI64() throws TException { + return zigzagToLong(readVarint64()); + } + + /** + * No magic here - just read a double off the wire. + */ + public double readDouble() throws TException { + trans_.readAll(temp, 0, 8); + return Double.longBitsToDouble(bytesToLong(temp)); + } + + /** + * Reads a byte[] (via readBinary), and then UTF-8 decodes it. + */ + public String readString() throws TException { + int length = readVarint32(); + checkStringReadLength(length); + + if (length == 0) { + return ""; + } + + try { + if (trans_.getBytesRemainingInBuffer() >= length) { + String str = new String(trans_.getBuffer(), trans_.getBufferPosition(), length, "UTF-8"); + trans_.consumeBuffer(length); + return str; + } else { + return new String(readBinary(length), "UTF-8"); + } + } catch (UnsupportedEncodingException e) { + throw new TException("UTF-8 not supported!"); + } + } + + /** + * Read a byte[] from the wire. + */ + public ByteBuffer readBinary() throws TException { + int length = readVarint32(); + checkStringReadLength(length); + if (length == 0) return EMPTY_BUFFER; + + if (trans_.getBytesRemainingInBuffer() >= length) { + ByteBuffer bb = ByteBuffer.wrap(trans_.getBuffer(), trans_.getBufferPosition(), length); + trans_.consumeBuffer(length); + return bb; + } + + byte[] buf = new byte[length]; + trans_.readAll(buf, 0, length); + return ByteBuffer.wrap(buf); + } + + /** + * Read a byte[] of a known length from the wire. + */ + private byte[] readBinary(int length) throws TException { + if (length == 0) return EMPTY_BYTES; + + byte[] buf = new byte[length]; + trans_.readAll(buf, 0, length); + return buf; + } + + private void checkStringReadLength(int length) throws TProtocolException { + if (length < 0) { + throw new TProtocolException(TProtocolException.NEGATIVE_SIZE, + "Negative length: " + length); + } + if (stringLengthLimit_ != NO_LENGTH_LIMIT && length > stringLengthLimit_) { + throw new TProtocolException(TProtocolException.SIZE_LIMIT, + "Length exceeded max allowed: " + length); + } + } + + private void checkContainerReadLength(int length) throws TProtocolException { + if (length < 0) { + throw new TProtocolException(TProtocolException.NEGATIVE_SIZE, + "Negative length: " + length); + } + if (containerLengthLimit_ != NO_LENGTH_LIMIT && length > containerLengthLimit_) { + throw new TProtocolException(TProtocolException.SIZE_LIMIT, + "Length exceeded max allowed: " + length); + } + } + + // + // These methods are here for the struct to call, but don't have any wire + // encoding. + // + public void readMessageEnd() throws TException {} + public void readFieldEnd() throws TException {} + public void readMapEnd() throws TException {} + public void readListEnd() throws TException {} + public void readSetEnd() throws TException {} + + // + // Internal reading methods + // + + /** + * Read an i32 from the wire as a varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 5 bytes. + */ + private int readVarint32() throws TException { + int result = 0; + int shift = 0; + if (trans_.getBytesRemainingInBuffer() >= 5) { + byte[] buf = trans_.getBuffer(); + int pos = trans_.getBufferPosition(); + int off = 0; + while (true) { + byte b = buf[pos+off]; + result |= (int) (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) break; + shift += 7; + off++; + } + trans_.consumeBuffer(off+1); + } else { + while (true) { + byte b = readByte(); + result |= (int) (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) break; + shift += 7; + } + } + return result; + } + + /** + * Read an i64 from the wire as a proper varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 10 bytes. + */ + private long readVarint64() throws TException { + int shift = 0; + long result = 0; + if (trans_.getBytesRemainingInBuffer() >= 10) { + byte[] buf = trans_.getBuffer(); + int pos = trans_.getBufferPosition(); + int off = 0; + while (true) { + byte b = buf[pos+off]; + result |= (long) (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) break; + shift += 7; + off++; + } + trans_.consumeBuffer(off+1); + } else { + while (true) { + byte b = readByte(); + result |= (long) (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) break; + shift +=7; + } + } + return result; + } + + // + // encoding helpers + // + + /** + * Convert from zigzag int to int. + */ + private int zigzagToInt(int n) { + return (n >>> 1) ^ -(n & 1); + } + + /** + * Convert from zigzag long to long. + */ + private long zigzagToLong(long n) { + return (n >>> 1) ^ -(n & 1); + } + + /** + * Note that it's important that the mask bytes are long literals, + * otherwise they'll default to ints, and when you shift an int left 56 bits, + * you just get a messed up int. + */ + private long bytesToLong(byte[] bytes) { + return + ((bytes[7] & 0xffL) << 56) | + ((bytes[6] & 0xffL) << 48) | + ((bytes[5] & 0xffL) << 40) | + ((bytes[4] & 0xffL) << 32) | + ((bytes[3] & 0xffL) << 24) | + ((bytes[2] & 0xffL) << 16) | + ((bytes[1] & 0xffL) << 8) | + ((bytes[0] & 0xffL)); + } + + // + // type testing and converting + // + + private boolean isBoolType(byte b) { + int lowerNibble = b & 0x0f; + return lowerNibble == Types.BOOLEAN_TRUE || lowerNibble == Types.BOOLEAN_FALSE; + } + + /** + * Given a TCompactProtocol.Types constant, convert it to its corresponding + * TType value. + */ + private byte getTType(byte type) throws TProtocolException { + switch ((byte)(type & 0x0f)) { + case TType.STOP: + return TType.STOP; + case Types.BOOLEAN_FALSE: + case Types.BOOLEAN_TRUE: + return TType.BOOL; + case Types.BYTE: + return TType.BYTE; + case Types.I16: + return TType.I16; + case Types.I32: + return TType.I32; + case Types.I64: + return TType.I64; + case Types.DOUBLE: + return TType.DOUBLE; + case Types.BINARY: + return TType.STRING; + case Types.LIST: + return TType.LIST; + case Types.SET: + return TType.SET; + case Types.MAP: + return TType.MAP; + case Types.STRUCT: + return TType.STRUCT; + default: + throw new TProtocolException("don't know what type: " + (byte)(type & 0x0f)); + } + } + + /** + * Given a TType value, find the appropriate TCompactProtocol.Types constant. + */ + private byte getCompactType(byte ttype) { + return ttypeToCompactType[ttype]; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TField.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TField.java new file mode 100644 index 00000000..fff27654 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TField.java @@ -0,0 +1,66 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +/** + * Helper class that encapsulates field metadata. + * + */ +public class TField { + public TField() { + this("", TType.STOP, (short)0); + } + + public TField(String n, byte t, short i) { + name = n; + type = t; + id = i; + } + + public final String name; + public final byte type; + public final short id; + + public String toString() { + return ""; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + id; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + type; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TField otherField = (TField) obj; + return type == otherField.type && id == otherField.id; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TJSONProtocol.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TJSONProtocol.java new file mode 100644 index 00000000..3f14a90d --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TJSONProtocol.java @@ -0,0 +1,1007 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Stack; + +import com.xiaomi.infra.pegasus.thrift.TByteArrayOutputStream; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * JSON protocol implementation for thrift. + * + * This is a full-featured protocol supporting write and read. + * + * Please see the C++ class header for a detailed description of the + * protocol's wire format. + * + */ +public class TJSONProtocol extends TProtocol { + + /** + * Factory for JSON protocol objects + */ + public static class Factory implements TProtocolFactory { + protected boolean fieldNamesAsString_ = false; + + public Factory() {} + + public Factory(boolean fieldNamesAsString) { + fieldNamesAsString_ = fieldNamesAsString; + } + + public TProtocol getProtocol(TTransport trans) { + return new TJSONProtocol(trans, fieldNamesAsString_); + } + + } + + private static final byte[] COMMA = new byte[] {','}; + private static final byte[] COLON = new byte[] {':'}; + private static final byte[] LBRACE = new byte[] {'{'}; + private static final byte[] RBRACE = new byte[] {'}'}; + private static final byte[] LBRACKET = new byte[] {'['}; + private static final byte[] RBRACKET = new byte[] {']'}; + private static final byte[] QUOTE = new byte[] {'"'}; + private static final byte[] BACKSLASH = new byte[] {'\\'}; + private static final byte[] ZERO = new byte[] {'0'}; + + private static final byte[] ESCSEQ = new byte[] {'\\','u','0','0'}; + + private static final long VERSION = 1; + + private static final byte[] JSON_CHAR_TABLE = { + /* 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 + }; + + private static final String ESCAPE_CHARS = "\"\\/bfnrt"; + + private static final byte[] ESCAPE_CHAR_VALS = { + '"', '\\', '/', '\b', '\f', '\n', '\r', '\t', + }; + + private static final int DEF_STRING_SIZE = 16; + + private static final byte[] NAME_BOOL = new byte[] {'t', 'f'}; + private static final byte[] NAME_BYTE = new byte[] {'i','8'}; + private static final byte[] NAME_I16 = new byte[] {'i','1','6'}; + private static final byte[] NAME_I32 = new byte[] {'i','3','2'}; + private static final byte[] NAME_I64 = new byte[] {'i','6','4'}; + private static final byte[] NAME_DOUBLE = new byte[] {'d','b','l'}; + private static final byte[] NAME_STRUCT = new byte[] {'r','e','c'}; + private static final byte[] NAME_STRING = new byte[] {'s','t','r'}; + private static final byte[] NAME_MAP = new byte[] {'m','a','p'}; + private static final byte[] NAME_LIST = new byte[] {'l','s','t'}; + private static final byte[] NAME_SET = new byte[] {'s','e','t'}; + + private static final TStruct ANONYMOUS_STRUCT = new TStruct(); + + private static final byte[] getTypeNameForTypeID(byte typeID) + throws TException { + switch (typeID) { + case TType.BOOL: + return NAME_BOOL; + case TType.BYTE: + return NAME_BYTE; + case TType.I16: + return NAME_I16; + case TType.I32: + return NAME_I32; + case TType.I64: + return NAME_I64; + case TType.DOUBLE: + return NAME_DOUBLE; + case TType.STRING: + return NAME_STRING; + case TType.STRUCT: + return NAME_STRUCT; + case TType.MAP: + return NAME_MAP; + case TType.SET: + return NAME_SET; + case TType.LIST: + return NAME_LIST; + default: + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, + "Unrecognized type"); + } + } + + private static final byte getTypeIDForTypeName(byte[] name) + throws TException { + byte result = TType.STOP; + if (name.length > 1) { + switch (name[0]) { + case 'd': + result = TType.DOUBLE; + break; + case 'i': + switch (name[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.LIST; + break; + case 'm': + result = TType.MAP; + break; + case 'r': + result = TType.STRUCT; + break; + case 's': + if (name[1] == 't') { + result = TType.STRING; + } + else if (name[1] == 'e') { + result = TType.SET; + } + break; + case 't': + result = TType.BOOL; + break; + } + } + if (result == TType.STOP) { + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, + "Unrecognized type"); + } + return result; + } + + // Base class for tracking JSON contexts that may require inserting/reading + // additional JSON syntax characters + // This base context does nothing. + protected class JSONBaseContext { + protected void write() throws TException {} + + protected void read() throws TException {} + + protected boolean escapeNum() { return false; } + } + + // Context for JSON lists. Will insert/read commas before each item except + // for the first one + protected class JSONListContext extends JSONBaseContext { + private boolean first_ = true; + + @Override + protected void write() throws TException { + if (first_) { + first_ = false; + } else { + trans_.write(COMMA); + } + } + + @Override + protected void read() throws TException { + if (first_) { + first_ = false; + } else { + readJSONSyntaxChar(COMMA); + } + } + } + + // Context for JSON records. Will insert/read colons before the value portion + // of each record pair, and commas before each key except the first. In + // addition, will indicate that numbers in the key position need to be + // escaped in quotes (since JSON keys must be strings). + protected class JSONPairContext extends JSONBaseContext { + private boolean first_ = true; + private boolean colon_ = true; + + @Override + protected void write() throws TException { + if (first_) { + first_ = false; + colon_ = true; + } else { + trans_.write(colon_ ? COLON : COMMA); + colon_ = !colon_; + } + } + + @Override + protected void read() throws TException { + if (first_) { + first_ = false; + colon_ = true; + } else { + readJSONSyntaxChar(colon_ ? COLON : COMMA); + colon_ = !colon_; + } + } + + @Override + protected boolean escapeNum() { + return colon_; + } + } + + // Holds up to one byte from the transport + protected class LookaheadReader { + + private boolean hasData_; + private byte[] data_ = new byte[1]; + + // Return and consume the next byte to be read, either taking it from the + // data buffer if present or getting it from the transport otherwise. + protected byte read() throws TException { + if (hasData_) { + hasData_ = false; + } + else { + trans_.readAll(data_, 0, 1); + } + return data_[0]; + } + + // Return the next byte to be read without consuming, filling the data + // buffer if it has not been filled already. + protected byte peek() throws TException { + if (!hasData_) { + trans_.readAll(data_, 0, 1); + } + hasData_ = true; + return data_[0]; + } + } + + // Stack of nested contexts that we may be in + private Stack contextStack_ = new Stack(); + + // Current context that we are in + private JSONBaseContext context_ = new JSONBaseContext(); + + // Reader that manages a 1-byte buffer + private LookaheadReader reader_ = new LookaheadReader(); + + // Write out the TField names as a string instead of the default integer value + private boolean fieldNamesAsString_ = false; + + // Push a new JSON context onto the stack. + private void pushContext(JSONBaseContext c) { + contextStack_.push(context_); + context_ = c; + } + + // Pop the last JSON context off the stack + private void popContext() { + context_ = contextStack_.pop(); + } + + // Reset the context stack to its initial state + private void resetContext() { + while (!contextStack_.isEmpty()) { + popContext(); + } + } + + /** + * Constructor + */ + public TJSONProtocol(TTransport trans) { + super(trans); + } + + public TJSONProtocol(TTransport trans, boolean fieldNamesAsString) { + super(trans); + fieldNamesAsString_ = fieldNamesAsString; + } + + @Override + public void reset() { + contextStack_.clear(); + context_ = new JSONBaseContext(); + reader_ = new LookaheadReader(); + } + + // Temporary buffer used by several methods + private byte[] tmpbuf_ = new byte[4]; + + // Read a byte that must match b[0]; otherwise an exception is thrown. + // Marked protected to avoid synthetic accessor in JSONListContext.read + // and JSONPairContext.read + protected void readJSONSyntaxChar(byte[] b) throws TException { + byte ch = reader_.read(); + if (ch != b[0]) { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Unexpected character:" + (char)ch); + } + } + + // Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its + // corresponding hex value + private static final byte hexVal(byte ch) throws TException { + if ((ch >= '0') && (ch <= '9')) { + return (byte)((char)ch - '0'); + } + else if ((ch >= 'a') && (ch <= 'f')) { + return (byte)((char)ch - 'a' + 10); + } + else { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Expected hex character"); + } + } + + // Convert a byte containing a hex value to its corresponding hex character + private static final byte hexChar(byte val) { + val &= 0x0F; + if (val < 10) { + return (byte)((char)val + '0'); + } + else { + return (byte)((char)(val - 10) + 'a'); + } + } + + // Write the bytes in array buf as a JSON characters, escaping as needed + private void writeJSONString(byte[] b) throws TException { + context_.write(); + trans_.write(QUOTE); + int len = b.length; + for (int i = 0; i < len; i++) { + if ((b[i] & 0x00FF) >= 0x30) { + if (b[i] == BACKSLASH[0]) { + trans_.write(BACKSLASH); + trans_.write(BACKSLASH); + } + else { + trans_.write(b, i, 1); + } + } + else { + tmpbuf_[0] = JSON_CHAR_TABLE[b[i]]; + if (tmpbuf_[0] == 1) { + trans_.write(b, i, 1); + } + else if (tmpbuf_[0] > 1) { + trans_.write(BACKSLASH); + trans_.write(tmpbuf_, 0, 1); + } + else { + trans_.write(ESCSEQ); + tmpbuf_[0] = hexChar((byte)(b[i] >> 4)); + tmpbuf_[1] = hexChar(b[i]); + trans_.write(tmpbuf_, 0, 2); + } + } + } + trans_.write(QUOTE); + } + + // Write out number as a JSON value. If the context dictates so, it will be + // wrapped in quotes to output as a JSON string. + private void writeJSONInteger(long num) throws TException { + context_.write(); + String str = Long.toString(num); + boolean escapeNum = context_.escapeNum(); + if (escapeNum) { + trans_.write(QUOTE); + } + try { + byte[] buf = str.getBytes("UTF-8"); + trans_.write(buf); + } catch (UnsupportedEncodingException uex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + if (escapeNum) { + trans_.write(QUOTE); + } + } + + // Write out a double as a JSON value. If it is NaN or infinity or if the + // context dictates escaping, write out as JSON string. + private void writeJSONDouble(double num) throws TException { + context_.write(); + String str = Double.toString(num); + boolean special = false; + switch (str.charAt(0)) { + case 'N': // NaN + case 'I': // Infinity + special = true; + break; + case '-': + if (str.charAt(1) == 'I') { // -Infinity + special = true; + } + break; + default: + break; + } + + boolean escapeNum = special || context_.escapeNum(); + if (escapeNum) { + trans_.write(QUOTE); + } + try { + byte[] b = str.getBytes("UTF-8"); + trans_.write(b, 0, b.length); + } catch (UnsupportedEncodingException uex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + if (escapeNum) { + trans_.write(QUOTE); + } + } + + // Write out contents of byte array b as a JSON string with base-64 encoded + // data + private void writeJSONBase64(byte[] b, int offset, int length) throws TException { + context_.write(); + trans_.write(QUOTE); + int len = length; + int off = offset; + while (len >= 3) { + // Encode 3 bytes at a time + TBase64Utils.encode(b, off, 3, tmpbuf_, 0); + trans_.write(tmpbuf_, 0, 4); + off += 3; + len -= 3; + } + if (len > 0) { + // Encode remainder + TBase64Utils.encode(b, off, len, tmpbuf_, 0); + trans_.write(tmpbuf_, 0, len + 1); + } + trans_.write(QUOTE); + } + + private void writeJSONObjectStart() throws TException { + context_.write(); + trans_.write(LBRACE); + pushContext(new JSONPairContext()); + } + + private void writeJSONObjectEnd() throws TException { + popContext(); + trans_.write(RBRACE); + } + + private void writeJSONArrayStart() throws TException { + context_.write(); + trans_.write(LBRACKET); + pushContext(new JSONListContext()); + } + + private void writeJSONArrayEnd() throws TException { + popContext(); + trans_.write(RBRACKET); + } + + @Override + public void writeMessageBegin(TMessage message) throws TException { + resetContext(); // THRIFT-3743 + writeJSONArrayStart(); + writeJSONInteger(VERSION); + try { + byte[] b = message.name.getBytes("UTF-8"); + writeJSONString(b); + } catch (UnsupportedEncodingException uex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + writeJSONInteger(message.type); + writeJSONInteger(message.seqid); + } + + @Override + public void writeMessageEnd() throws TException { + writeJSONArrayEnd(); + } + + @Override + public void writeStructBegin(TStruct struct) throws TException { + writeJSONObjectStart(); + } + + @Override + public void writeStructEnd() throws TException { + writeJSONObjectEnd(); + } + + @Override + public void writeFieldBegin(TField field) throws TException { + if (fieldNamesAsString_) { + writeString(field.name); + } else { + writeJSONInteger(field.id); + } + writeJSONObjectStart(); + writeJSONString(getTypeNameForTypeID(field.type)); + } + + @Override + public void writeFieldEnd() throws TException { + writeJSONObjectEnd(); + } + + @Override + public void writeFieldStop() {} + + @Override + public void writeMapBegin(TMap map) throws TException { + writeJSONArrayStart(); + writeJSONString(getTypeNameForTypeID(map.keyType)); + writeJSONString(getTypeNameForTypeID(map.valueType)); + writeJSONInteger(map.size); + writeJSONObjectStart(); + } + + @Override + public void writeMapEnd() throws TException { + writeJSONObjectEnd(); + writeJSONArrayEnd(); + } + + @Override + public void writeListBegin(TList list) throws TException { + writeJSONArrayStart(); + writeJSONString(getTypeNameForTypeID(list.elemType)); + writeJSONInteger(list.size); + } + + @Override + public void writeListEnd() throws TException { + writeJSONArrayEnd(); + } + + @Override + public void writeSetBegin(TSet set) throws TException { + writeJSONArrayStart(); + writeJSONString(getTypeNameForTypeID(set.elemType)); + writeJSONInteger(set.size); + } + + @Override + public void writeSetEnd() throws TException { + writeJSONArrayEnd(); + } + + @Override + public void writeBool(boolean b) throws TException { + writeJSONInteger(b ? (long)1 : (long)0); + } + + @Override + public void writeByte(byte b) throws TException { + writeJSONInteger((long)b); + } + + @Override + public void writeI16(short i16) throws TException { + writeJSONInteger((long)i16); + } + + @Override + public void writeI32(int i32) throws TException { + writeJSONInteger((long)i32); + } + + @Override + public void writeI64(long i64) throws TException { + writeJSONInteger(i64); + } + + @Override + public void writeDouble(double dub) throws TException { + writeJSONDouble(dub); + } + + @Override + public void writeString(String str) throws TException { + try { + byte[] b = str.getBytes("UTF-8"); + writeJSONString(b); + } catch (UnsupportedEncodingException uex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + } + + @Override + public void writeBinary(ByteBuffer bin) throws TException { + writeJSONBase64(bin.array(), bin.position() + bin.arrayOffset(), bin.limit() - bin.position() - bin.arrayOffset()); + } + + /** + * Reading methods. + */ + + // Read in a JSON string, unescaping as appropriate.. Skip reading from the + // context if skipContext is true. + private TByteArrayOutputStream readJSONString(boolean skipContext) + throws TException { + TByteArrayOutputStream arr = new TByteArrayOutputStream(DEF_STRING_SIZE); + ArrayList codeunits = new ArrayList(); + if (!skipContext) { + context_.read(); + } + readJSONSyntaxChar(QUOTE); + while (true) { + byte ch = reader_.read(); + if (ch == QUOTE[0]) { + break; + } + if (ch == ESCSEQ[0]) { + ch = reader_.read(); + if (ch == ESCSEQ[1]) { + trans_.readAll(tmpbuf_, 0, 4); + short cu = (short)( + ((short)hexVal(tmpbuf_[0]) << 12) + + ((short)hexVal(tmpbuf_[1]) << 8) + + ((short)hexVal(tmpbuf_[2]) << 4) + + (short)hexVal(tmpbuf_[3])); + try { + if (Character.isHighSurrogate((char)cu)) { + if (codeunits.size() > 0) { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Expected low surrogate char"); + } + codeunits.add((char)cu); + } + else if (Character.isLowSurrogate((char)cu)) { + if (codeunits.size() == 0) { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Expected high surrogate char"); + } + + codeunits.add((char)cu); + arr.write((new String(new int[] { codeunits.get(0), codeunits.get(1) }, 0, 2)).getBytes("UTF-8")); + codeunits.clear(); + } + else { + arr.write((new String(new int[] { cu }, 0, 1)).getBytes("UTF-8")); + } + continue; + } + catch (UnsupportedEncodingException ex) { + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, + "JVM does not support UTF-8"); + } + catch (IOException ex) { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Invalid unicode sequence"); + } + } + else { + int off = ESCAPE_CHARS.indexOf(ch); + if (off == -1) { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Expected control char"); + } + ch = ESCAPE_CHAR_VALS[off]; + } + } + arr.write(ch); + } + return arr; + } + + // Return true if the given byte could be a valid part of a JSON number. + private boolean isJSONNumeric(byte 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; + } + + // Read in a sequence of characters that are all valid in JSON numbers. Does + // not do a complete regex check to validate that this is actually a number. + private String readJSONNumericChars() throws TException { + StringBuilder strbld = new StringBuilder(); + while (true) { + byte ch = reader_.peek(); + if (!isJSONNumeric(ch)) { + break; + } + strbld.append((char)reader_.read()); + } + return strbld.toString(); + } + + // Read in a JSON number. If the context dictates, read in enclosing quotes. + private long readJSONInteger() throws TException { + context_.read(); + if (context_.escapeNum()) { + readJSONSyntaxChar(QUOTE); + } + String str = readJSONNumericChars(); + if (context_.escapeNum()) { + readJSONSyntaxChar(QUOTE); + } + try { + return Long.valueOf(str); + } + catch (NumberFormatException ex) { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Bad data encounted in numeric data"); + } + } + + // Read in a JSON double value. Throw if the value is not wrapped in quotes + // when expected or if wrapped in quotes when not expected. + private double readJSONDouble() throws TException { + context_.read(); + if (reader_.peek() == QUOTE[0]) { + TByteArrayOutputStream arr = readJSONString(true); + try { + double dub = Double.valueOf(arr.toString("UTF-8")); + if (!context_.escapeNum() && !Double.isNaN(dub) && + !Double.isInfinite(dub)) { + // Throw exception -- we should not be in a string in this case + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Numeric data unexpectedly quoted"); + } + return dub; + } + catch (UnsupportedEncodingException ex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + } + else { + if (context_.escapeNum()) { + // This will throw - we should have had a quote if escapeNum == true + readJSONSyntaxChar(QUOTE); + } + try { + return Double.valueOf(readJSONNumericChars()); + } + catch (NumberFormatException ex) { + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Bad data encounted in numeric data"); + } + } + } + + // Read in a JSON string containing base-64 encoded data and decode it. + private byte[] readJSONBase64() throws TException { + TByteArrayOutputStream arr = readJSONString(false); + byte[] b = arr.get(); + int len = arr.len(); + int off = 0; + int size = 0; + // Ignore padding + int bound = len >= 2 ? len - 2 : 0; + for (int i = len - 1; i >= bound && b[i] == '='; --i) { + --len; + } + while (len >= 4) { + // Decode 4 bytes at a time + TBase64Utils.decode(b, off, 4, b, size); // NB: decoded in place + off += 4; + len -= 4; + size += 3; + } + // Don't decode if we hit the end or got a single leftover byte (invalid + // base64 but legal for skip of regular string type) + if (len > 1) { + // Decode remainder + TBase64Utils.decode(b, off, len, b, size); // NB: decoded in place + size += len - 1; + } + // Sadly we must copy the byte[] (any way around this?) + byte [] result = new byte[size]; + System.arraycopy(b, 0, result, 0, size); + return result; + } + + private void readJSONObjectStart() throws TException { + context_.read(); + readJSONSyntaxChar(LBRACE); + pushContext(new JSONPairContext()); + } + + private void readJSONObjectEnd() throws TException { + readJSONSyntaxChar(RBRACE); + popContext(); + } + + private void readJSONArrayStart() throws TException { + context_.read(); + readJSONSyntaxChar(LBRACKET); + pushContext(new JSONListContext()); + } + + private void readJSONArrayEnd() throws TException { + readJSONSyntaxChar(RBRACKET); + popContext(); + } + + @Override + public TMessage readMessageBegin() throws TException { + resetContext(); // THRIFT-3743 + readJSONArrayStart(); + if (readJSONInteger() != VERSION) { + throw new TProtocolException(TProtocolException.BAD_VERSION, + "Message contained bad version."); + } + String name; + try { + name = readJSONString(false).toString("UTF-8"); + } + catch (UnsupportedEncodingException ex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + byte type = (byte) readJSONInteger(); + int seqid = (int) readJSONInteger(); + return new TMessage(name, type, seqid); + } + + @Override + public void readMessageEnd() throws TException { + readJSONArrayEnd(); + } + + @Override + public TStruct readStructBegin() throws TException { + readJSONObjectStart(); + return ANONYMOUS_STRUCT; + } + + @Override + public void readStructEnd() throws TException { + readJSONObjectEnd(); + } + + @Override + public TField readFieldBegin() throws TException { + byte ch = reader_.peek(); + byte type; + short id = 0; + if (ch == RBRACE[0]) { + type = TType.STOP; + } + else { + id = (short) readJSONInteger(); + readJSONObjectStart(); + type = getTypeIDForTypeName(readJSONString(false).get()); + } + return new TField("", type, id); + } + + @Override + public void readFieldEnd() throws TException { + readJSONObjectEnd(); + } + + @Override + public TMap readMapBegin() throws TException { + readJSONArrayStart(); + byte keyType = getTypeIDForTypeName(readJSONString(false).get()); + byte valueType = getTypeIDForTypeName(readJSONString(false).get()); + int size = (int)readJSONInteger(); + readJSONObjectStart(); + return new TMap(keyType, valueType, size); + } + + @Override + public void readMapEnd() throws TException { + readJSONObjectEnd(); + readJSONArrayEnd(); + } + + @Override + public TList readListBegin() throws TException { + readJSONArrayStart(); + byte elemType = getTypeIDForTypeName(readJSONString(false).get()); + int size = (int)readJSONInteger(); + return new TList(elemType, size); + } + + @Override + public void readListEnd() throws TException { + readJSONArrayEnd(); + } + + @Override + public TSet readSetBegin() throws TException { + readJSONArrayStart(); + byte elemType = getTypeIDForTypeName(readJSONString(false).get()); + int size = (int)readJSONInteger(); + return new TSet(elemType, size); + } + + @Override + public void readSetEnd() throws TException { + readJSONArrayEnd(); + } + + @Override + public boolean readBool() throws TException { + return (readJSONInteger() == 0 ? false : true); + } + + @Override + public byte readByte() throws TException { + return (byte) readJSONInteger(); + } + + @Override + public short readI16() throws TException { + return (short) readJSONInteger(); + } + + @Override + public int readI32() throws TException { + return (int) readJSONInteger(); + } + + @Override + public long readI64() throws TException { + return (long) readJSONInteger(); + } + + @Override + public double readDouble() throws TException { + return readJSONDouble(); + } + + @Override + public String readString() throws TException { + try { + return readJSONString(false).toString("UTF-8"); + } + catch (UnsupportedEncodingException ex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + } + + @Override + public ByteBuffer readBinary() throws TException { + return ByteBuffer.wrap(readJSONBase64()); + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TList.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TList.java new file mode 100644 index 00000000..3dd6dea7 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TList.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.protocol; + +/** + * Helper class that encapsulates list metadata. + * + */ +public final class TList { + public TList() { + this(TType.STOP, 0); + } + + public TList(byte t, int s) { + elemType = t; + size = s; + } + + public final byte elemType; + public final int size; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMap.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMap.java new file mode 100644 index 00000000..60787278 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMap.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.protocol; + +/** + * Helper class that encapsulates map metadata. + * + */ +public final class TMap { + public TMap() { + this(TType.STOP, TType.STOP, 0); + } + + public TMap(byte k, byte v, int s) { + keyType = k; + valueType = v; + size = s; + } + + public final byte keyType; + public final byte valueType; + public final int size; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMessage.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMessage.java new file mode 100644 index 00000000..a7436fb1 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMessage.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.protocol; + +/** + * Helper class that encapsulates struct metadata. + * + */ +public final class TMessage { + public TMessage() { + this("", TType.STOP, 0); + } + + public TMessage(String n, byte t, int s) { + name = n; + type = t; + seqid = s; + } + + public final String name; + public final byte type; + public final int seqid; + + @Override + public String toString() { + return ""; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + seqid; + result = prime * result + type; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TMessage other = (TMessage) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (seqid != other.seqid) + return false; + if (type != other.type) + return false; + return true; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMessageType.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMessageType.java new file mode 100644 index 00000000..abd5328f --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMessageType.java @@ -0,0 +1,31 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +/** + * Message type constants in the Thrift protocol. + * + */ +public final class TMessageType { + public static final byte CALL = 1; + public static final byte REPLY = 2; + public static final byte EXCEPTION = 3; + public static final byte ONEWAY = 4; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMultiplexedProtocol.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMultiplexedProtocol.java new file mode 100644 index 00000000..5e7ea9da --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TMultiplexedProtocol.java @@ -0,0 +1,93 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +import com.xiaomi.infra.pegasus.thrift.TException; + +/** + * TMultiplexedProtocol 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. + * + *

NOTE: THIS IS NOT USED BY SERVERS. On the server, use {@link com.xiaomi.infra.pegasus.thrift.TMultiplexedProcessor TMultiplexedProcessor} to handle requests + * from a multiplexing client. + * + *

This example uses a single socket transport to invoke two services: + * + *

+ * {@code
+ *     TSocket transport = new TSocket("localhost", 9090);
+ *     transport.open();
+ *
+ *     TBinaryProtocol protocol = new TBinaryProtocol(transport);
+ *
+ *     TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
+ *     Calculator.Client service = new Calculator.Client(mp);
+ *
+ *     TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
+ *     WeatherReport.Client service2 = new WeatherReport.Client(mp2);
+ *
+ *     System.out.println(service.add(2,2));
+ *     System.out.println(service2.getTemperature());
+ * }
+ * 
+ * + * @see com.xiaomi.infra.pegasus.thrift.protocol.TProtocolDecorator + */ +public class TMultiplexedProtocol extends TProtocolDecorator { + + /** Used to delimit the service name from the function name */ + public static final String SEPARATOR = ":"; + + private final String SERVICE_NAME; + + /** + * Wrap the specified protocol, allowing it to be used to communicate with a + * multiplexing server. The serviceName 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 protocol Your communication protocol of choice, e.g. TBinaryProtocol. + * @param serviceName The service name of the service communicating via this protocol. + */ + public TMultiplexedProtocol(TProtocol protocol, String serviceName) { + super(protocol); + SERVICE_NAME = serviceName; + } + + /** + * Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR. + * + * @param tMessage The original message. + * @throws TException Passed through from wrapped TProtocol instance. + */ + @Override + public void writeMessageBegin(TMessage tMessage) throws TException { + if (tMessage.type == TMessageType.CALL || tMessage.type == TMessageType.ONEWAY) { + super.writeMessageBegin(new TMessage( + SERVICE_NAME + SEPARATOR + tMessage.name, + tMessage.type, + tMessage.seqid + )); + } else { + super.writeMessageBegin(tMessage); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocol.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocol.java new file mode 100644 index 00000000..f6f981ef --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocol.java @@ -0,0 +1,162 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +import java.nio.ByteBuffer; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.scheme.IScheme; +import com.xiaomi.infra.pegasus.thrift.scheme.StandardScheme; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * Protocol interface definition. + * + */ +public abstract class TProtocol { + + /** + * Prevent direct instantiation + */ + @SuppressWarnings("unused") + private TProtocol() {} + + /** + * Transport + */ + protected TTransport trans_; + + /** + * Constructor + */ + protected TProtocol(TTransport trans) { + trans_ = trans; + } + + /** + * Transport accessor + */ + public TTransport getTransport() { + return trans_; + } + + /** + * Writing methods. + */ + + public abstract void writeMessageBegin(TMessage message) throws TException; + + public abstract void writeMessageEnd() throws TException; + + public abstract void writeStructBegin(TStruct struct) throws TException; + + public abstract void writeStructEnd() throws TException; + + public abstract void writeFieldBegin(TField field) throws TException; + + public abstract void writeFieldEnd() throws TException; + + public abstract void writeFieldStop() throws TException; + + public abstract void writeMapBegin(TMap map) throws TException; + + public abstract void writeMapEnd() throws TException; + + public abstract void writeListBegin(TList list) throws TException; + + public abstract void writeListEnd() throws TException; + + public abstract void writeSetBegin(TSet set) throws TException; + + public abstract void writeSetEnd() throws TException; + + public abstract void writeBool(boolean b) throws TException; + + public abstract void writeByte(byte b) throws TException; + + public abstract void writeI16(short i16) throws TException; + + public abstract void writeI32(int i32) throws TException; + + public abstract void writeI64(long i64) throws TException; + + public abstract void writeDouble(double dub) throws TException; + + public abstract void writeString(String str) throws TException; + + public abstract void writeBinary(ByteBuffer buf) throws TException; + + /** + * Reading methods. + */ + + public abstract TMessage readMessageBegin() throws TException; + + public abstract void readMessageEnd() throws TException; + + public abstract TStruct readStructBegin() throws TException; + + public abstract void readStructEnd() throws TException; + + public abstract TField readFieldBegin() throws TException; + + public abstract void readFieldEnd() throws TException; + + public abstract TMap readMapBegin() throws TException; + + public abstract void readMapEnd() throws TException; + + public abstract TList readListBegin() throws TException; + + public abstract void readListEnd() throws TException; + + public abstract TSet readSetBegin() throws TException; + + public abstract void readSetEnd() throws TException; + + public abstract boolean readBool() throws TException; + + public abstract byte readByte() throws TException; + + public abstract short readI16() throws TException; + + public abstract int readI32() throws TException; + + public abstract long readI64() throws TException; + + public abstract double readDouble() throws TException; + + public abstract String readString() throws TException; + + public abstract ByteBuffer readBinary() throws TException; + + /** + * Reset any internal state back to a blank slate. This method only needs to + * be implemented for stateful protocols. + */ + public void reset() {} + + /** + * Scheme accessor + */ + public Class getScheme() { + return StandardScheme.class; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolDecorator.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolDecorator.java new file mode 100644 index 00000000..2a18aef3 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolDecorator.java @@ -0,0 +1,213 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +import com.xiaomi.infra.pegasus.thrift.TException; + +import java.nio.ByteBuffer; + +/** + * TProtocolDecorator forwards all requests to an enclosed + * TProtocol 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 TProtocol. + * + *

See p.175 of Design Patterns (by Gamma et al.)

+ * + * @see com.xiaomi.infra.pegasus.thrift.protocol.TMultiplexedProtocol + */ +public abstract class TProtocolDecorator extends TProtocol { + + private final TProtocol concreteProtocol; + + /** + * Encloses the specified protocol. + * @param protocol All operations will be forward to this protocol. Must be non-null. + */ + public TProtocolDecorator(TProtocol protocol) { + super(protocol.getTransport()); + concreteProtocol = protocol; + } + + public void writeMessageBegin(TMessage tMessage) throws TException { + concreteProtocol.writeMessageBegin(tMessage); + } + + public void writeMessageEnd() throws TException { + concreteProtocol.writeMessageEnd(); + } + + public void writeStructBegin(TStruct tStruct) throws TException { + concreteProtocol.writeStructBegin(tStruct); + } + + public void writeStructEnd() throws TException { + concreteProtocol.writeStructEnd(); + } + + public void writeFieldBegin(TField tField) throws TException { + concreteProtocol.writeFieldBegin(tField); + } + + public void writeFieldEnd() throws TException { + concreteProtocol.writeFieldEnd(); + } + + public void writeFieldStop() throws TException { + concreteProtocol.writeFieldStop(); + } + + public void writeMapBegin(TMap tMap) throws TException { + concreteProtocol.writeMapBegin(tMap); + } + + public void writeMapEnd() throws TException { + concreteProtocol.writeMapEnd(); + } + + public void writeListBegin(TList tList) throws TException { + concreteProtocol.writeListBegin(tList); + } + + public void writeListEnd() throws TException { + concreteProtocol.writeListEnd(); + } + + public void writeSetBegin(TSet tSet) throws TException { + concreteProtocol.writeSetBegin(tSet); + } + + public void writeSetEnd() throws TException { + concreteProtocol.writeSetEnd(); + } + + public void writeBool(boolean b) throws TException { + concreteProtocol.writeBool(b); + } + + public void writeByte(byte b) throws TException { + concreteProtocol.writeByte(b); + } + + public void writeI16(short i) throws TException { + concreteProtocol.writeI16(i); + } + + public void writeI32(int i) throws TException { + concreteProtocol.writeI32(i); + } + + public void writeI64(long l) throws TException { + concreteProtocol.writeI64(l); + } + + public void writeDouble(double v) throws TException { + concreteProtocol.writeDouble(v); + } + + public void writeString(String s) throws TException { + concreteProtocol.writeString(s); + } + + public void writeBinary(ByteBuffer buf) throws TException { + concreteProtocol.writeBinary(buf); + } + + public TMessage readMessageBegin() throws TException { + return concreteProtocol.readMessageBegin(); + } + + public void readMessageEnd() throws TException { + concreteProtocol.readMessageEnd(); + } + + public TStruct readStructBegin() throws TException { + return concreteProtocol.readStructBegin(); + } + + public void readStructEnd() throws TException { + concreteProtocol.readStructEnd(); + } + + public TField readFieldBegin() throws TException { + return concreteProtocol.readFieldBegin(); + } + + public void readFieldEnd() throws TException { + concreteProtocol.readFieldEnd(); + } + + public TMap readMapBegin() throws TException { + return concreteProtocol.readMapBegin(); + } + + public void readMapEnd() throws TException { + concreteProtocol.readMapEnd(); + } + + public TList readListBegin() throws TException { + return concreteProtocol.readListBegin(); + } + + public void readListEnd() throws TException { + concreteProtocol.readListEnd(); + } + + public TSet readSetBegin() throws TException { + return concreteProtocol.readSetBegin(); + } + + public void readSetEnd() throws TException { + concreteProtocol.readSetEnd(); + } + + public boolean readBool() throws TException { + return concreteProtocol.readBool(); + } + + public byte readByte() throws TException { + return concreteProtocol.readByte(); + } + + public short readI16() throws TException { + return concreteProtocol.readI16(); + } + + public int readI32() throws TException { + return concreteProtocol.readI32(); + } + + public long readI64() throws TException { + return concreteProtocol.readI64(); + } + + public double readDouble() throws TException { + return concreteProtocol.readDouble(); + } + + public String readString() throws TException { + return concreteProtocol.readString(); + } + + public ByteBuffer readBinary() throws TException { + return concreteProtocol.readBinary(); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolException.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolException.java new file mode 100644 index 00000000..4c607900 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolException.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.protocol; + +import com.xiaomi.infra.pegasus.thrift.TException; + +/** + * Protocol exceptions. + * + */ +public class TProtocolException extends TException { + + + private static final long serialVersionUID = 1L; + public static final int UNKNOWN = 0; + public static final int INVALID_DATA = 1; + public static final int NEGATIVE_SIZE = 2; + public static final int SIZE_LIMIT = 3; + public static final int BAD_VERSION = 4; + public static final int NOT_IMPLEMENTED = 5; + public static final int DEPTH_LIMIT = 6; + + protected int type_ = UNKNOWN; + + public TProtocolException() { + super(); + } + + public TProtocolException(int type) { + super(); + type_ = type; + } + + public TProtocolException(int type, String message) { + super(message); + type_ = type; + } + + public TProtocolException(String message) { + super(message); + } + + public TProtocolException(int type, Throwable cause) { + super(cause); + type_ = type; + } + + public TProtocolException(Throwable cause) { + super(cause); + } + + public TProtocolException(String message, Throwable cause) { + super(message, cause); + } + + public TProtocolException(int type, String message, Throwable cause) { + super(message, cause); + type_ = type; + } + + public int getType() { + return type_; + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolFactory.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolFactory.java new file mode 100644 index 00000000..f0d0e0f3 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolFactory.java @@ -0,0 +1,31 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +import java.io.Serializable; + +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * Factory interface for constructing protocol instances. + */ +public interface TProtocolFactory extends Serializable { + public TProtocol getProtocol(TTransport trans); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolUtil.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolUtil.java new file mode 100644 index 00000000..86e79ed0 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TProtocolUtil.java @@ -0,0 +1,221 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +import com.xiaomi.infra.pegasus.thrift.TException; + +/** + * Utility class with static methods for interacting with protocol data + * streams. + * + */ +public class TProtocolUtil { + + /** + * The maximum recursive depth the skip() function will traverse before + * throwing a TException. + */ + private static int maxSkipDepth = Integer.MAX_VALUE; + + /** + * Specifies the maximum recursive depth that the skip function will + * traverse before throwing a TException. This is a global setting, so + * any call to skip in this JVM will enforce this value. + * + * @param depth the maximum recursive depth. A value of 2 would allow + * the skip function to skip a structure or collection with basic children, + * but it would not permit skipping a struct that had a field containing + * a child struct. A value of 1 would only allow skipping of simple + * types and empty structs/collections. + */ + public static void setMaxSkipDepth(int depth) { + maxSkipDepth = depth; + } + + /** + * Skips over the next data element from the provided input TProtocol object. + * + * @param prot the protocol object to read from + * @param type the next value will be interpreted as this TType value. + */ + public static void skip(TProtocol prot, byte type) + throws TException { + skip(prot, type, maxSkipDepth); + } + + /** + * Skips over the next data element from the provided input TProtocol object. + * + * @param prot the protocol object to read from + * @param type the next value will be interpreted as this TType value. + * @param maxDepth this function will only skip complex objects to this + * recursive depth, to prevent Java stack overflow. + */ + public static void skip(TProtocol prot, byte type, int maxDepth) + throws TException { + if (maxDepth <= 0) { + throw new TException("Maximum skip depth exceeded"); + } + switch (type) { + case TType.BOOL: + prot.readBool(); + break; + + case TType.BYTE: + prot.readByte(); + break; + + case TType.I16: + prot.readI16(); + break; + + case TType.I32: + prot.readI32(); + break; + + case TType.I64: + prot.readI64(); + break; + + case TType.DOUBLE: + prot.readDouble(); + break; + + case TType.STRING: + prot.readBinary(); + break; + + case TType.STRUCT: + prot.readStructBegin(); + while (true) { + TField field = prot.readFieldBegin(); + if (field.type == TType.STOP) { + break; + } + skip(prot, field.type, maxDepth - 1); + prot.readFieldEnd(); + } + prot.readStructEnd(); + break; + + case TType.MAP: + TMap map = prot.readMapBegin(); + for (int i = 0; i < map.size; i++) { + skip(prot, map.keyType, maxDepth - 1); + skip(prot, map.valueType, maxDepth - 1); + } + prot.readMapEnd(); + break; + + case TType.SET: + TSet set = prot.readSetBegin(); + for (int i = 0; i < set.size; i++) { + skip(prot, set.elemType, maxDepth - 1); + } + prot.readSetEnd(); + break; + + case TType.LIST: + TList list = prot.readListBegin(); + for (int i = 0; i < list.size; i++) { + skip(prot, list.elemType, maxDepth - 1); + } + prot.readListEnd(); + break; + + default: + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Unrecognized type " + type); + } + } + + /** + * Attempt to determine the protocol used to serialize some data. + * + * The guess is based on known specificities of supported protocols. + * In some cases, no guess can be done, in that case we return the + * fallback TProtocolFactory. + * To be certain to correctly detect the protocol, the first encoded + * field should have a field id < 256 + * + * @param data The serialized data to guess the protocol for. + * @param fallback The TProtocol to return if no guess can be made. + * @return a Class implementing TProtocolFactory which can be used to create a deserializer. + */ + public static TProtocolFactory guessProtocolFactory(byte[] data, TProtocolFactory fallback) { + // + // If the first and last bytes are opening/closing curly braces we guess the protocol as + // being TJSONProtocol. + // It could not be a TCompactBinary encoding for a field of type 0xb (Map) + // with delta id 7 as the last byte for TCompactBinary is always 0. + // + + if ('{' == data[0] && '}' == data[data.length - 1]) { + return new TJSONProtocol.Factory(); + } + + // + // If the last byte is not 0, then it cannot be TCompactProtocol, it must be + // TBinaryProtocol. + // + + if (data[data.length - 1] != 0) { + return new TBinaryProtocol.Factory(); + } + + // + // A first byte of value > 16 indicates TCompactProtocol was used, and the first byte + // encodes a delta field id (id <= 15) and a field type. + // + + if (data[0] > 0x10) { + return new TCompactProtocol.Factory(); + } + + // + // If the second byte is 0 then it is a field id < 256 encoded by TBinaryProtocol. + // It cannot possibly be TCompactProtocol since a value of 0 would imply a field id + // of 0 as the zig zag varint encoding would end. + // + + if (data.length > 1 && 0 == data[1]) { + return new TBinaryProtocol.Factory(); + } + + // + // If bit 7 of the first byte of the field id is set then we have two choices: + // 1. A field id > 63 was encoded with TCompactProtocol. + // 2. A field id > 0x7fff (32767) was encoded with TBinaryProtocol and the last byte of the + // serialized data is 0. + // Option 2 is impossible since field ids are short and thus limited to 32767. + // + + if (data.length > 1 && (data[1] & 0x80) != 0) { + return new TCompactProtocol.Factory(); + } + + // + // The remaining case is either a field id <= 63 encoded as TCompactProtocol, + // one >= 256 encoded with TBinaryProtocol with a last byte at 0, or an empty structure. + // As we cannot really decide, we return the fallback protocol. + // + return fallback; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TSet.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TSet.java new file mode 100644 index 00000000..36d68829 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TSet.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.protocol; + +/** + * Helper class that encapsulates set metadata. + * + */ +public final class TSet { + public TSet() { + this(TType.STOP, 0); + } + + public TSet(byte t, int s) { + elemType = t; + size = s; + } + + public TSet(TList list) { + this(list.elemType, list.size); + } + + public final byte elemType; + public final int size; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TSimpleJSONProtocol.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TSimpleJSONProtocol.java new file mode 100644 index 00000000..3872a417 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TSimpleJSONProtocol.java @@ -0,0 +1,448 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.Stack; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * JSON protocol implementation for thrift. + * + * This protocol is write-only and produces a simple output format + * suitable for parsing by scripting languages. It should not be + * confused with the full-featured TJSONProtocol. + * + */ +public class TSimpleJSONProtocol extends TProtocol { + + /** + * Factory + */ + public static class Factory implements TProtocolFactory { + public TProtocol getProtocol(TTransport trans) { + return new TSimpleJSONProtocol(trans); + } + } + + private static final byte[] COMMA = new byte[] {','}; + private static final byte[] COLON = new byte[] {':'}; + private static final byte[] LBRACE = new byte[] {'{'}; + private static final byte[] RBRACE = new byte[] {'}'}; + private static final byte[] LBRACKET = new byte[] {'['}; + private static final byte[] RBRACKET = new byte[] {']'}; + private static final char QUOTE = '"'; + + private static final TStruct ANONYMOUS_STRUCT = new TStruct(); + private static final TField ANONYMOUS_FIELD = new TField(); + private static final TMessage EMPTY_MESSAGE = new TMessage(); + private static final TSet EMPTY_SET = new TSet(); + private static final TList EMPTY_LIST = new TList(); + private static final TMap EMPTY_MAP = new TMap(); + private static final String LIST = "list"; + private static final String SET = "set"; + private static final String MAP = "map"; + + protected class Context { + protected void write() throws TException {} + + /** + * Returns whether the current value is a key in a map + */ + protected boolean isMapKey() { return false; } + } + + protected class ListContext extends Context { + protected boolean first_ = true; + + protected void write() throws TException { + if (first_) { + first_ = false; + } else { + trans_.write(COMMA); + } + } + } + + protected class StructContext extends Context { + protected boolean first_ = true; + protected boolean colon_ = true; + + protected void write() throws TException { + if (first_) { + first_ = false; + colon_ = true; + } else { + trans_.write(colon_ ? COLON : COMMA); + colon_ = !colon_; + } + } + } + + protected class MapContext extends StructContext { + protected boolean isKey = true; + + @Override + protected void write() throws TException { + super.write(); + isKey = !isKey; + } + + protected boolean isMapKey() { + // we want to coerce map keys to json strings regardless + // of their type + return isKey; + } + } + + protected final Context BASE_CONTEXT = new Context(); + + /** + * Stack of nested contexts that we may be in. + */ + protected Stack writeContextStack_ = new Stack(); + + /** + * Current context that we are in + */ + protected Context writeContext_ = BASE_CONTEXT; + + /** + * Push a new write context onto the stack. + */ + protected void pushWriteContext(Context c) { + writeContextStack_.push(writeContext_); + writeContext_ = c; + } + + /** + * Pop the last write context off the stack + */ + protected void popWriteContext() { + writeContext_ = writeContextStack_.pop(); + } + + /** + * Reset the write context stack to its initial state. + */ + protected void resetWriteContext() { + while (!writeContextStack_.isEmpty()) { + popWriteContext(); + } + } + + /** + * Used to make sure that we are not encountering a map whose keys are containers + */ + protected void assertContextIsNotMapKey(String invalidKeyType) throws CollectionMapKeyException { + if (writeContext_.isMapKey()) { + throw new CollectionMapKeyException("Cannot serialize a map with keys that are of type " + invalidKeyType); + } + } + + /** + * Constructor + */ + public TSimpleJSONProtocol(TTransport trans) { + super(trans); + } + + public void writeMessageBegin(TMessage message) throws TException { + resetWriteContext(); // THRIFT-3743 + trans_.write(LBRACKET); + pushWriteContext(new ListContext()); + writeString(message.name); + writeByte(message.type); + writeI32(message.seqid); + } + + public void writeMessageEnd() throws TException { + popWriteContext(); + trans_.write(RBRACKET); + } + + public void writeStructBegin(TStruct struct) throws TException { + writeContext_.write(); + trans_.write(LBRACE); + pushWriteContext(new StructContext()); + } + + public void writeStructEnd() throws TException { + popWriteContext(); + trans_.write(RBRACE); + } + + public void writeFieldBegin(TField field) throws TException { + // Note that extra type information is omitted in JSON! + writeString(field.name); + } + + public void writeFieldEnd() {} + + public void writeFieldStop() {} + + public void writeMapBegin(TMap map) throws TException { + assertContextIsNotMapKey(MAP); + writeContext_.write(); + trans_.write(LBRACE); + pushWriteContext(new MapContext()); + // No metadata! + } + + public void writeMapEnd() throws TException { + popWriteContext(); + trans_.write(RBRACE); + } + + public void writeListBegin(TList list) throws TException { + assertContextIsNotMapKey(LIST); + writeContext_.write(); + trans_.write(LBRACKET); + pushWriteContext(new ListContext()); + // No metadata! + } + + public void writeListEnd() throws TException { + popWriteContext(); + trans_.write(RBRACKET); + } + + public void writeSetBegin(TSet set) throws TException { + assertContextIsNotMapKey(SET); + writeContext_.write(); + trans_.write(LBRACKET); + pushWriteContext(new ListContext()); + // No metadata! + } + + public void writeSetEnd() throws TException { + popWriteContext(); + trans_.write(RBRACKET); + } + + public void writeBool(boolean b) throws TException { + writeByte(b ? (byte)1 : (byte)0); + } + + public void writeByte(byte b) throws TException { + writeI32(b); + } + + public void writeI16(short i16) throws TException { + writeI32(i16); + } + + public void writeI32(int i32) throws TException { + if(writeContext_.isMapKey()) { + writeString(Integer.toString(i32)); + } else { + writeContext_.write(); + _writeStringData(Integer.toString(i32)); + } + } + + public void _writeStringData(String s) throws TException { + try { + byte[] b = s.getBytes("UTF-8"); + trans_.write(b); + } catch (UnsupportedEncodingException uex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + } + + public void writeI64(long i64) throws TException { + if(writeContext_.isMapKey()) { + writeString(Long.toString(i64)); + } else { + writeContext_.write(); + _writeStringData(Long.toString(i64)); + } + } + + public void writeDouble(double dub) throws TException { + if(writeContext_.isMapKey()) { + writeString(Double.toString(dub)); + } else { + writeContext_.write(); + _writeStringData(Double.toString(dub)); + } + } + + public void writeString(String str) throws TException { + writeContext_.write(); + int length = str.length(); + StringBuffer escape = new StringBuffer(length + 16); + escape.append(QUOTE); + for (int i = 0; i < length; ++i) { + char c = str.charAt(i); + switch (c) { + case '"': + case '\\': + escape.append('\\'); + escape.append(c); + break; + case '\b': + escape.append('\\'); + escape.append('b'); + break; + case '\f': + escape.append('\\'); + escape.append('f'); + break; + case '\n': + escape.append('\\'); + escape.append('n'); + break; + case '\r': + escape.append('\\'); + escape.append('r'); + break; + case '\t': + escape.append('\\'); + escape.append('t'); + break; + default: + // Control characters! According to JSON RFC u0020 (space) + if (c < ' ') { + String hex = Integer.toHexString(c); + escape.append('\\'); + escape.append('u'); + for (int j = 4; j > hex.length(); --j) { + escape.append('0'); + } + escape.append(hex); + } else { + escape.append(c); + } + break; + } + } + escape.append(QUOTE); + _writeStringData(escape.toString()); + } + + public void writeBinary(ByteBuffer bin) throws TException { + try { + // TODO(mcslee): Fix this + writeString(new String(bin.array(), bin.position() + bin.arrayOffset(), bin.limit() - bin.position() - bin.arrayOffset(), "UTF-8")); + } catch (UnsupportedEncodingException uex) { + throw new TException("JVM DOES NOT SUPPORT UTF-8"); + } + } + + /** + * Reading methods. + */ + + public TMessage readMessageBegin() throws TException { + // TODO(mcslee): implement + return EMPTY_MESSAGE; + } + + public void readMessageEnd() {} + + public TStruct readStructBegin() { + // TODO(mcslee): implement + return ANONYMOUS_STRUCT; + } + + public void readStructEnd() {} + + public TField readFieldBegin() throws TException { + // TODO(mcslee): implement + return ANONYMOUS_FIELD; + } + + public void readFieldEnd() {} + + public TMap readMapBegin() throws TException { + // TODO(mcslee): implement + return EMPTY_MAP; + } + + public void readMapEnd() {} + + public TList readListBegin() throws TException { + // TODO(mcslee): implement + return EMPTY_LIST; + } + + public void readListEnd() {} + + public TSet readSetBegin() throws TException { + // TODO(mcslee): implement + return EMPTY_SET; + } + + public void readSetEnd() {} + + public boolean readBool() throws TException { + return (readByte() == 1); + } + + public byte readByte() throws TException { + // TODO(mcslee): implement + return 0; + } + + public short readI16() throws TException { + // TODO(mcslee): implement + return 0; + } + + public int readI32() throws TException { + // TODO(mcslee): implement + return 0; + } + + public long readI64() throws TException { + // TODO(mcslee): implement + return 0; + } + + public double readDouble() throws TException { + // TODO(mcslee): implement + return 0; + } + + public String readString() throws TException { + // TODO(mcslee): implement + return ""; + } + + public String readStringBody(int size) throws TException { + // TODO(mcslee): implement + return ""; + } + + public ByteBuffer readBinary() throws TException { + // TODO(mcslee): implement + return ByteBuffer.wrap(new byte[0]); + } + + public static class CollectionMapKeyException extends TException { + public CollectionMapKeyException(String message) { + super(message); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TStruct.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TStruct.java new file mode 100644 index 00000000..727b0b4f --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TStruct.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.protocol; + +/** + * Helper class that encapsulates struct metadata. + * + */ +public final class TStruct { + public TStruct() { + this(""); + } + + public TStruct(String n) { + name = n; + } + + public final String name; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TTupleProtocol.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TTupleProtocol.java new file mode 100644 index 00000000..a705cacf --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TTupleProtocol.java @@ -0,0 +1,98 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.protocol; + +import java.util.BitSet; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.scheme.IScheme; +import com.xiaomi.infra.pegasus.thrift.scheme.TupleScheme; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +public final class TTupleProtocol extends TCompactProtocol { + public static class Factory implements TProtocolFactory { + public Factory() {} + + public TProtocol getProtocol(TTransport trans) { + return new TTupleProtocol(trans); + } + } + + public TTupleProtocol(TTransport transport) { + super(transport); + } + + @Override + public Class getScheme() { + return TupleScheme.class; + } + + public void writeBitSet(BitSet bs, int vectorWidth) throws TException { + byte[] bytes = toByteArray(bs, vectorWidth); + for (byte b : bytes) { + writeByte(b); + } + } + + public BitSet readBitSet(int i) throws TException { + int length = (int) Math.ceil(i/8.0); + byte[] bytes = new byte[length]; + for (int j = 0; j < length; j++) { + bytes[j] = readByte(); + } + BitSet bs = fromByteArray(bytes); + return bs; + } + + /** + * Returns a bitset containing the values in bytes. The byte-ordering must be + * big-endian. + */ + public static BitSet fromByteArray(byte[] bytes) { + BitSet bits = new BitSet(); + for (int i = 0; i < bytes.length * 8; i++) { + if ((bytes[bytes.length - i / 8 - 1] & (1 << (i % 8))) > 0) { + bits.set(i); + } + } + return bits; + } + + /** + * Returns a byte array of at least length 1. The most significant bit in the + * result is guaranteed not to be a 1 (since BitSet does not support sign + * extension). The byte-ordering of the result is big-endian which means the + * most significant bit is in element 0. The bit at index 0 of the bit set is + * assumed to be the least significant bit. + * + * @param bits + * @param vectorWidth + * @return a byte array of at least length 1 + */ + public static byte[] toByteArray(BitSet bits, int vectorWidth) { + byte[] bytes = new byte[(int) Math.ceil(vectorWidth/8.0)]; + for (int i = 0; i < bits.length(); i++) { + if (bits.get(i)) { + bytes[bytes.length - i / 8 - 1] |= 1 << (i % 8); + } + } + return bytes; + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TType.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TType.java new file mode 100644 index 00000000..79174a52 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/protocol/TType.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.protocol; + +/** + * Type constants in the Thrift protocol. + */ +public final class TType { + public static final byte STOP = 0; + public static final byte VOID = 1; + public static final byte BOOL = 2; + public static final byte BYTE = 3; + public static final byte DOUBLE = 4; + public static final byte I16 = 6; + public static final byte I32 = 8; + public static final byte I64 = 10; + public static final byte STRING = 11; + public static final byte STRUCT = 12; + public static final byte MAP = 13; + public static final byte SET = 14; + public static final byte LIST = 15; + public static final byte ENUM = 16; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/IScheme.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/IScheme.java new file mode 100644 index 00000000..628d5ac8 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/IScheme.java @@ -0,0 +1,29 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.scheme; + +import com.xiaomi.infra.pegasus.thrift.TBase; + +public interface IScheme { + + public void read(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol iproto, T struct) throws com.xiaomi.infra.pegasus.thrift.TException; + + public void write(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oproto, T struct) throws com.xiaomi.infra.pegasus.thrift.TException; + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/SchemeFactory.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/SchemeFactory.java new file mode 100644 index 00000000..9c463894 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/SchemeFactory.java @@ -0,0 +1,25 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.scheme; + +public interface SchemeFactory { + + public S getScheme(); + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/StandardScheme.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/StandardScheme.java new file mode 100644 index 00000000..d2d8e1cd --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/StandardScheme.java @@ -0,0 +1,25 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.scheme; + +import com.xiaomi.infra.pegasus.thrift.TBase; + +public abstract class StandardScheme implements IScheme { + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/TupleScheme.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/TupleScheme.java new file mode 100644 index 00000000..f276c6ae --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/scheme/TupleScheme.java @@ -0,0 +1,25 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.scheme; + +import com.xiaomi.infra.pegasus.thrift.TBase; + +public abstract class TupleScheme implements IScheme { + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/AbstractNonblockingServer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/AbstractNonblockingServer.java new file mode 100644 index 00000000..b15b674a --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/AbstractNonblockingServer.java @@ -0,0 +1,612 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.server; + +import com.xiaomi.infra.pegasus.thrift.TAsyncProcessor; +import com.xiaomi.infra.pegasus.thrift.TByteArrayOutputStream; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.transport.TFramedTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TMemoryInputTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TNonblockingServerTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.spi.SelectorProvider; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Provides common methods and classes used by nonblocking TServer + * implementations. + */ +public abstract class AbstractNonblockingServer extends TServer { + protected final Logger LOGGER = LoggerFactory.getLogger(getClass().getName()); + + public static abstract class AbstractNonblockingServerArgs> extends AbstractServerArgs { + public long maxReadBufferBytes = 256 * 1024 * 1024; + + public AbstractNonblockingServerArgs(TNonblockingServerTransport transport) { + super(transport); + transportFactory(new TFramedTransport.Factory()); + } + } + + /** + * The maximum amount of memory we will allocate to client IO buffers at a + * time. Without this limit, the server will gladly allocate client buffers + * right into an out of memory exception, rather than waiting. + */ + final long MAX_READ_BUFFER_BYTES; + + /** + * How many bytes are currently allocated to read buffers. + */ + final AtomicLong readBufferBytesAllocated = new AtomicLong(0); + + public AbstractNonblockingServer(AbstractNonblockingServerArgs args) { + super(args); + MAX_READ_BUFFER_BYTES = args.maxReadBufferBytes; + } + + /** + * Begin accepting connections and processing invocations. + */ + public void serve() { + // start any IO threads + if (!startThreads()) { + return; + } + + // start listening, or exit + if (!startListening()) { + return; + } + + setServing(true); + + // this will block while we serve + waitForShutdown(); + + setServing(false); + + // do a little cleanup + stopListening(); + } + + /** + * Starts any threads required for serving. + * + * @return true if everything went ok, false if threads could not be started. + */ + protected abstract boolean startThreads(); + + /** + * A method that will block until when threads handling the serving have been + * shut down. + */ + protected abstract void waitForShutdown(); + + /** + * Have the server transport start accepting connections. + * + * @return true if we started listening successfully, false if something went + * wrong. + */ + protected boolean startListening() { + try { + serverTransport_.listen(); + return true; + } catch (TTransportException ttx) { + LOGGER.error("Failed to start listening on server socket!", ttx); + return false; + } + } + + /** + * Stop listening for connections. + */ + protected void stopListening() { + serverTransport_.close(); + } + + /** + * Perform an invocation. This method could behave several different ways - + * invoke immediately inline, queue for separate execution, etc. + * + * @return true if invocation was successfully requested, which is not a + * guarantee that invocation has completed. False if the request + * failed. + */ + protected abstract boolean requestInvoke(FrameBuffer frameBuffer); + + /** + * An abstract thread that handles selecting on a set of transports and + * {@link FrameBuffer FrameBuffers} associated with selected keys + * corresponding to requests. + */ + protected abstract class AbstractSelectThread extends Thread { + protected Selector selector; + + // List of FrameBuffers that want to change their selection interests. + protected final Set selectInterestChanges = new HashSet(); + + public AbstractSelectThread() throws IOException { + this.selector = SelectorProvider.provider().openSelector(); + } + + /** + * If the selector is blocked, wake it up. + */ + public void wakeupSelector() { + selector.wakeup(); + } + + /** + * Add FrameBuffer to the list of select interest changes and wake up the + * selector if it's blocked. When the select() call exits, it'll give the + * FrameBuffer a chance to change its interests. + */ + public void requestSelectInterestChange(FrameBuffer frameBuffer) { + synchronized (selectInterestChanges) { + selectInterestChanges.add(frameBuffer); + } + // wakeup the selector, if it's currently blocked. + selector.wakeup(); + } + + /** + * Check to see if there are any FrameBuffers that have switched their + * interest type from read to write or vice versa. + */ + protected void processInterestChanges() { + synchronized (selectInterestChanges) { + for (FrameBuffer fb : selectInterestChanges) { + fb.changeSelectInterests(); + } + selectInterestChanges.clear(); + } + } + + /** + * Do the work required to read from a readable client. If the frame is + * fully read, then invoke the method call. + */ + protected void handleRead(SelectionKey key) { + FrameBuffer buffer = (FrameBuffer) key.attachment(); + if (!buffer.read()) { + cleanupSelectionKey(key); + return; + } + + // if the buffer's frame read is complete, invoke the method. + if (buffer.isFrameFullyRead()) { + if (!requestInvoke(buffer)) { + cleanupSelectionKey(key); + } + } + } + + /** + * Let a writable client get written, if there's data to be written. + */ + protected void handleWrite(SelectionKey key) { + FrameBuffer buffer = (FrameBuffer) key.attachment(); + if (!buffer.write()) { + cleanupSelectionKey(key); + } + } + + /** + * Do connection-close cleanup on a given SelectionKey. + */ + protected void cleanupSelectionKey(SelectionKey key) { + // remove the records from the two maps + FrameBuffer buffer = (FrameBuffer) key.attachment(); + if (buffer != null) { + // close the buffer + buffer.close(); + } + // cancel the selection key + key.cancel(); + } + } // SelectThread + + /** + * Possible states for the FrameBuffer state machine. + */ + private enum FrameBufferState { + // in the midst of reading the frame size off the wire + READING_FRAME_SIZE, + // reading the actual frame data now, but not all the way done yet + READING_FRAME, + // completely read the frame, so an invocation can now happen + READ_FRAME_COMPLETE, + // waiting to get switched to listening for write events + AWAITING_REGISTER_WRITE, + // started writing response data, not fully complete yet + WRITING, + // another thread wants this framebuffer to go back to reading + AWAITING_REGISTER_READ, + // we want our transport and selection key invalidated in the selector + // thread + AWAITING_CLOSE + } + + /** + * Class that implements a sort of state machine around the interaction with a + * client and an invoker. It manages reading the frame size and frame data, + * getting it handed off as wrapped transports, and then the writing of + * response data back to the client. In the process it manages flipping the + * read and write bits on the selection key for its client. + */ + public class FrameBuffer { + private final Logger LOGGER = LoggerFactory.getLogger(getClass().getName()); + + // the actual transport hooked up to the client. + protected final TNonblockingTransport trans_; + + // the SelectionKey that corresponds to our transport + protected final SelectionKey selectionKey_; + + // the SelectThread that owns the registration of our transport + protected final AbstractSelectThread selectThread_; + + // where in the process of reading/writing are we? + protected FrameBufferState state_ = FrameBufferState.READING_FRAME_SIZE; + + // the ByteBuffer we'll be using to write and read, depending on the state + protected ByteBuffer buffer_; + + protected final TByteArrayOutputStream response_; + + // the frame that the TTransport should wrap. + protected final TMemoryInputTransport frameTrans_; + + // the transport that should be used to connect to clients + protected final TTransport inTrans_; + + protected final TTransport outTrans_; + + // the input protocol to use on frames + protected final TProtocol inProt_; + + // the output protocol to use on frames + protected final TProtocol outProt_; + + // context associated with this connection + protected final ServerContext context_; + + public FrameBuffer(final TNonblockingTransport trans, + final SelectionKey selectionKey, + final AbstractSelectThread selectThread) { + trans_ = trans; + selectionKey_ = selectionKey; + selectThread_ = selectThread; + buffer_ = ByteBuffer.allocate(4); + + frameTrans_ = new TMemoryInputTransport(); + response_ = new TByteArrayOutputStream(); + inTrans_ = inputTransportFactory_.getTransport(frameTrans_); + outTrans_ = outputTransportFactory_.getTransport(new TIOStreamTransport(response_)); + inProt_ = inputProtocolFactory_.getProtocol(inTrans_); + outProt_ = outputProtocolFactory_.getProtocol(outTrans_); + + if (eventHandler_ != null) { + context_ = eventHandler_.createContext(inProt_, outProt_); + } else { + context_ = null; + } + } + + /** + * Give this FrameBuffer a chance to read. The selector loop should have + * received a read event for this FrameBuffer. + * + * @return true if the connection should live on, false if it should be + * closed + */ + public boolean read() { + if (state_ == FrameBufferState.READING_FRAME_SIZE) { + // try to read the frame size completely + if (!internalRead()) { + return false; + } + + // if the frame size has been read completely, then prepare to read the + // actual frame. + if (buffer_.remaining() == 0) { + // pull out the frame size as an integer. + int frameSize = buffer_.getInt(0); + if (frameSize <= 0) { + LOGGER.error("Read an invalid frame size of " + frameSize + + ". Are you using TFramedTransport on the client side?"); + return false; + } + + // if this frame will always be too large for this server, log the + // error and close the connection. + if (frameSize > MAX_READ_BUFFER_BYTES) { + LOGGER.error("Read a frame size of " + frameSize + + ", which is bigger than the maximum allowable buffer size for ALL connections."); + return false; + } + + // if this frame will push us over the memory limit, then return. + // with luck, more memory will free up the next time around. + if (readBufferBytesAllocated.get() + frameSize > MAX_READ_BUFFER_BYTES) { + return true; + } + + // increment the amount of memory allocated to read buffers + readBufferBytesAllocated.addAndGet(frameSize + 4); + + // reallocate the readbuffer as a frame-sized buffer + buffer_ = ByteBuffer.allocate(frameSize + 4); + buffer_.putInt(frameSize); + + state_ = FrameBufferState.READING_FRAME; + } else { + // this skips the check of READING_FRAME state below, since we can't + // possibly go on to that state if there's data left to be read at + // this one. + return true; + } + } + + // it is possible to fall through from the READING_FRAME_SIZE section + // to READING_FRAME if there's already some frame data available once + // READING_FRAME_SIZE is complete. + + if (state_ == FrameBufferState.READING_FRAME) { + if (!internalRead()) { + return false; + } + + // since we're already in the select loop here for sure, we can just + // modify our selection key directly. + if (buffer_.remaining() == 0) { + // get rid of the read select interests + selectionKey_.interestOps(0); + state_ = FrameBufferState.READ_FRAME_COMPLETE; + } + + return true; + } + + // if we fall through to this point, then the state must be invalid. + LOGGER.error("Read was called but state is invalid (" + state_ + ")"); + return false; + } + + /** + * Give this FrameBuffer a chance to write its output to the final client. + */ + public boolean write() { + if (state_ == FrameBufferState.WRITING) { + try { + if (trans_.write(buffer_) < 0) { + return false; + } + } catch (IOException e) { + LOGGER.warn("Got an IOException during write!", e); + return false; + } + + // we're done writing. now we need to switch back to reading. + if (buffer_.remaining() == 0) { + prepareRead(); + } + return true; + } + + LOGGER.error("Write was called, but state is invalid (" + state_ + ")"); + return false; + } + + /** + * Give this FrameBuffer a chance to set its interest to write, once data + * has come in. + */ + public void changeSelectInterests() { + if (state_ == FrameBufferState.AWAITING_REGISTER_WRITE) { + // set the OP_WRITE interest + selectionKey_.interestOps(SelectionKey.OP_WRITE); + state_ = FrameBufferState.WRITING; + } else if (state_ == FrameBufferState.AWAITING_REGISTER_READ) { + prepareRead(); + } else if (state_ == FrameBufferState.AWAITING_CLOSE) { + close(); + selectionKey_.cancel(); + } else { + LOGGER.error("changeSelectInterest was called, but state is invalid (" + state_ + ")"); + } + } + + /** + * Shut the connection down. + */ + public void close() { + // if we're being closed due to an error, we might have allocated a + // buffer that we need to subtract for our memory accounting. + if (state_ == FrameBufferState.READING_FRAME || + state_ == FrameBufferState.READ_FRAME_COMPLETE || + state_ == FrameBufferState.AWAITING_CLOSE) { + readBufferBytesAllocated.addAndGet(-buffer_.array().length); + } + trans_.close(); + if (eventHandler_ != null) { + eventHandler_.deleteContext(context_, inProt_, outProt_); + } + } + + /** + * Check if this FrameBuffer has a full frame read. + */ + public boolean isFrameFullyRead() { + return state_ == FrameBufferState.READ_FRAME_COMPLETE; + } + + /** + * After the processor has processed the invocation, whatever thread is + * managing invocations should call this method on this FrameBuffer so we + * know it's time to start trying to write again. Also, if it turns out that + * there actually isn't any data in the response buffer, we'll skip trying + * to write and instead go back to reading. + */ + public void responseReady() { + // the read buffer is definitely no longer in use, so we will decrement + // our read buffer count. we do this here as well as in close because + // we'd like to free this read memory up as quickly as possible for other + // clients. + readBufferBytesAllocated.addAndGet(-buffer_.array().length); + + if (response_.len() == 0) { + // go straight to reading again. this was probably an oneway method + state_ = FrameBufferState.AWAITING_REGISTER_READ; + buffer_ = null; + } else { + buffer_ = ByteBuffer.wrap(response_.get(), 0, response_.len()); + + // set state that we're waiting to be switched to write. we do this + // asynchronously through requestSelectInterestChange() because there is + // a possibility that we're not in the main thread, and thus currently + // blocked in select(). (this functionality is in place for the sake of + // the HsHa server.) + state_ = FrameBufferState.AWAITING_REGISTER_WRITE; + } + requestSelectInterestChange(); + } + + /** + * Actually invoke the method signified by this FrameBuffer. + */ + public void invoke() { + frameTrans_.reset(buffer_.array()); + response_.reset(); + + try { + if (eventHandler_ != null) { + eventHandler_.processContext(context_, inTrans_, outTrans_); + } + processorFactory_.getProcessor(inTrans_).process(inProt_, outProt_); + responseReady(); + return; + } catch (TException te) { + LOGGER.warn("Exception while invoking!", te); + } catch (Throwable t) { + LOGGER.error("Unexpected throwable while invoking!", t); + } + // This will only be reached when there is a throwable. + state_ = FrameBufferState.AWAITING_CLOSE; + requestSelectInterestChange(); + } + + /** + * Perform a read into buffer. + * + * @return true if the read succeeded, false if there was an error or the + * connection closed. + */ + private boolean internalRead() { + try { + if (trans_.read(buffer_) < 0) { + return false; + } + return true; + } catch (IOException e) { + LOGGER.warn("Got an IOException in internalRead!", e); + return false; + } + } + + /** + * We're done writing, so reset our interest ops and change state + * accordingly. + */ + private void prepareRead() { + // we can set our interest directly without using the queue because + // we're in the select thread. + selectionKey_.interestOps(SelectionKey.OP_READ); + // get ready for another go-around + buffer_ = ByteBuffer.allocate(4); + state_ = FrameBufferState.READING_FRAME_SIZE; + } + + /** + * When this FrameBuffer needs to change its select interests and execution + * might not be in its select thread, then this method will make sure the + * interest change gets done when the select thread wakes back up. When the + * current thread is this FrameBuffer's select thread, then it just does the + * interest change immediately. + */ + protected void requestSelectInterestChange() { + if (Thread.currentThread() == this.selectThread_) { + changeSelectInterests(); + } else { + this.selectThread_.requestSelectInterestChange(this); + } + } + } // FrameBuffer + + public class AsyncFrameBuffer extends FrameBuffer { + public AsyncFrameBuffer(TNonblockingTransport trans, SelectionKey selectionKey, AbstractSelectThread selectThread) { + super(trans, selectionKey, selectThread); + } + + public TProtocol getInputProtocol() { + return inProt_; + } + + public TProtocol getOutputProtocol() { + return outProt_; + } + + + public void invoke() { + frameTrans_.reset(buffer_.array()); + response_.reset(); + + try { + if (eventHandler_ != null) { + eventHandler_.processContext(context_, inTrans_, outTrans_); + } + ((TAsyncProcessor)processorFactory_.getProcessor(inTrans_)).process(this); + return; + } catch (TException te) { + LOGGER.warn("Exception while invoking!", te); + } catch (Throwable t) { + LOGGER.error("Unexpected throwable while invoking!", t); + } + // This will only be reached when there is a throwable. + state_ = FrameBufferState.AWAITING_CLOSE; + requestSelectInterestChange(); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/Invocation.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/Invocation.java new file mode 100644 index 00000000..762dc79c --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/Invocation.java @@ -0,0 +1,20 @@ +package com.xiaomi.infra.pegasus.thrift.server; + +import com.xiaomi.infra.pegasus.thrift.server.AbstractNonblockingServer.FrameBuffer; + +/** + * An Invocation represents a method call that is prepared to execute, given + * an idle worker thread. It contains the input and output protocols the + * thread's processor should use to perform the usual Thrift invocation. + */ +class Invocation implements Runnable { + private final FrameBuffer frameBuffer; + + public Invocation(final FrameBuffer frameBuffer) { + this.frameBuffer = frameBuffer; + } + + public void run() { + frameBuffer.invoke(); + } +} \ No newline at end of file diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/ServerContext.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/ServerContext.java new file mode 100644 index 00000000..59960ed1 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/ServerContext.java @@ -0,0 +1,26 @@ +/* + * 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. + */ + +/** + * Interface for storing server's connection context + */ + +package com.xiaomi.infra.pegasus.thrift.server; + +public interface ServerContext {} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TExtensibleServlet.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TExtensibleServlet.java new file mode 100644 index 00000000..be9d7df5 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TExtensibleServlet.java @@ -0,0 +1,171 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.server; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.TProcessor; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory; +import com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * Servlet implementation class ThriftServer, that allows {@link TProcessor} and + * {@link TProtocolFactory} to be supplied after the {@link #init()} method has + * finished.
+ * Subclasses must implement the abstract methods that return the TProcessor and + * two TProtocolFactory. Those methods are guaranteed to be called exactly once, + * and that {@link ServletContext} is available. + */ +public abstract class TExtensibleServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + private TProcessor processor; + + private TProtocolFactory inFactory; + + private TProtocolFactory outFactory; + + private Collection> customHeaders; + + /** + * Returns the appropriate {@link TProcessor}. This will be called once just + * after the {@link #init()} method + * + * @return + */ + protected abstract TProcessor getProcessor(); + + /** + * Returns the appropriate in {@link TProtocolFactory}. This will be called + * once just after the {@link #init()} method + * + * @return + */ + protected abstract TProtocolFactory getInProtocolFactory(); + + /** + * Returns the appropriate out {@link TProtocolFactory}. This will be called + * once just after the {@link #init()} method + * + * @return + */ + protected abstract TProtocolFactory getOutProtocolFactory(); + + @Override + public final void init(ServletConfig config) throws ServletException { + super.init(config); //no-args init() happens here + this.processor = getProcessor(); + this.inFactory = getInProtocolFactory(); + this.outFactory = getOutProtocolFactory(); + this.customHeaders = new ArrayList>(); + + if (processor == null) { + throw new ServletException("processor must be set"); + } + if (inFactory == null) { + throw new ServletException("inFactory must be set"); + } + if (outFactory == null) { + throw new ServletException("outFactory must be set"); + } + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse + * response) + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + TTransport inTransport = null; + TTransport outTransport = null; + + try { + response.setContentType("application/x-thrift"); + + if (null != this.customHeaders) { + for (Map.Entry header : this.customHeaders) { + response.addHeader(header.getKey(), header.getValue()); + } + } + + InputStream in = request.getInputStream(); + OutputStream out = response.getOutputStream(); + + TTransport transport = new TIOStreamTransport(in, out); + inTransport = transport; + outTransport = transport; + + TProtocol inProtocol = inFactory.getProtocol(inTransport); + TProtocol outProtocol = inFactory.getProtocol(outTransport); + + processor.process(inProtocol, outProtocol); + out.flush(); + } catch (TException te) { + throw new ServletException(te); + } + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse + * response) + */ + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + doPost(req, resp); + } + + public void addCustomHeader(final String key, final String value) { + this.customHeaders.add(new Map.Entry() { + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + public String setValue(String value) { + return null; + } + }); + } + + public void setCustomHeaders(Collection> headers) { + this.customHeaders.clear(); + this.customHeaders.addAll(headers); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/THsHaServer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/THsHaServer.java new file mode 100644 index 00000000..a02880c0 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/THsHaServer.java @@ -0,0 +1,204 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.server; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import com.xiaomi.infra.pegasus.thrift.transport.TNonblockingServerTransport; + +/** + * An extension of the TNonblockingServer to a Half-Sync/Half-Async server. + * Like TNonblockingServer, it relies on the use of TFramedTransport. + */ +public class THsHaServer extends TNonblockingServer { + + public static class Args extends AbstractNonblockingServerArgs { + public int minWorkerThreads = 5; + public int maxWorkerThreads = Integer.MAX_VALUE; + private int stopTimeoutVal = 60; + private TimeUnit stopTimeoutUnit = TimeUnit.SECONDS; + private ExecutorService executorService = null; + + public Args(TNonblockingServerTransport transport) { + super(transport); + } + + + /** + * Sets the min and max threads. + * + * @deprecated use {@link #minWorkerThreads(int)} and {@link #maxWorkerThreads(int)} instead. + */ + @Deprecated + public Args workerThreads(int n) { + minWorkerThreads = n; + maxWorkerThreads = n; + return this; + } + + /** + * @return what the min threads was set to. + * @deprecated use {@link #getMinWorkerThreads()} and {@link #getMaxWorkerThreads()} instead. + */ + @Deprecated + public int getWorkerThreads() { + return minWorkerThreads; + } + + public Args minWorkerThreads(int n) { + minWorkerThreads = n; + return this; + } + + public Args maxWorkerThreads(int n) { + maxWorkerThreads = n; + return this; + } + + public int getMinWorkerThreads() { + return minWorkerThreads; + } + + public int getMaxWorkerThreads() { + return maxWorkerThreads; + } + + public int getStopTimeoutVal() { + return stopTimeoutVal; + } + + public Args stopTimeoutVal(int stopTimeoutVal) { + this.stopTimeoutVal = stopTimeoutVal; + return this; + } + + public TimeUnit getStopTimeoutUnit() { + return stopTimeoutUnit; + } + + public Args stopTimeoutUnit(TimeUnit stopTimeoutUnit) { + this.stopTimeoutUnit = stopTimeoutUnit; + return this; + } + + public ExecutorService getExecutorService() { + return executorService; + } + + public Args executorService(ExecutorService executorService) { + this.executorService = executorService; + return this; + } + } + + + // This wraps all the functionality of queueing and thread pool management + // for the passing of Invocations from the Selector to workers. + private final ExecutorService invoker; + + private final Args args; + + /** + * Create the server with the specified Args configuration + */ + public THsHaServer(Args args) { + super(args); + + invoker = args.executorService == null ? createInvokerPool(args) : args.executorService; + this.args = args; + } + + /** + * {@inheritDoc} + */ + @Override + protected void waitForShutdown() { + joinSelector(); + gracefullyShutdownInvokerPool(); + } + + /** + * Helper to create an invoker pool + */ + protected static ExecutorService createInvokerPool(Args options) { + int minWorkerThreads = options.minWorkerThreads; + int maxWorkerThreads = options.maxWorkerThreads; + int stopTimeoutVal = options.stopTimeoutVal; + TimeUnit stopTimeoutUnit = options.stopTimeoutUnit; + + LinkedBlockingQueue queue = new LinkedBlockingQueue(); + ExecutorService invoker = new ThreadPoolExecutor(minWorkerThreads, + maxWorkerThreads, stopTimeoutVal, stopTimeoutUnit, queue); + + return invoker; + } + + protected ExecutorService getInvoker() { + return invoker; + } + + protected void gracefullyShutdownInvokerPool() { + // try to gracefully shut down the executor service + invoker.shutdown(); + + // Loop until awaitTermination finally does return without a interrupted + // exception. If we don't do this, then we'll shut down prematurely. We want + // to let the executorService clear it's task queue, closing client sockets + // appropriately. + long timeoutMS = args.stopTimeoutUnit.toMillis(args.stopTimeoutVal); + long now = System.currentTimeMillis(); + while (timeoutMS >= 0) { + try { + invoker.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS); + break; + } catch (InterruptedException ix) { + long newnow = System.currentTimeMillis(); + timeoutMS -= (newnow - now); + now = newnow; + } + } + } + + /** + * We override the standard invoke method here to queue the invocation for + * invoker service instead of immediately invoking. The thread pool takes care + * of the rest. + */ + @Override + protected boolean requestInvoke(FrameBuffer frameBuffer) { + try { + Runnable invocation = getRunnable(frameBuffer); + invoker.execute(invocation); + return true; + } catch (RejectedExecutionException rx) { + LOGGER.warn("ExecutorService rejected execution!", rx); + return false; + } + } + + protected Runnable getRunnable(FrameBuffer frameBuffer){ + return new Invocation(frameBuffer); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TNonblockingServer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TNonblockingServer.java new file mode 100644 index 00000000..22b9c98a --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TNonblockingServer.java @@ -0,0 +1,248 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.server; + +import com.xiaomi.infra.pegasus.thrift.transport.TNonblockingServerTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransportException; + +import java.io.IOException; +import java.nio.channels.SelectionKey; +import java.util.Iterator; + +/** + * A nonblocking TServer implementation. This allows for fairness amongst all + * connected clients in terms of invocations. + * + * This server is inherently single-threaded. If you want a limited thread pool + * coupled with invocation-fairness, see THsHaServer. + * + * To use this server, you MUST use a TFramedTransport at the outermost + * transport, otherwise this server will be unable to determine when a whole + * method call has been read off the wire. Clients must also use TFramedTransport. + */ +public class TNonblockingServer extends AbstractNonblockingServer { + + public static class Args extends AbstractNonblockingServerArgs { + public Args(TNonblockingServerTransport transport) { + super(transport); + } + } + + private SelectAcceptThread selectAcceptThread_; + + public TNonblockingServer(AbstractNonblockingServerArgs args) { + super(args); + } + + + /** + * Start the selector thread to deal with accepts and client messages. + * + * @return true if everything went ok, false if we couldn't start for some + * reason. + */ + @Override + protected boolean startThreads() { + // start the selector + try { + selectAcceptThread_ = new SelectAcceptThread((TNonblockingServerTransport)serverTransport_); + selectAcceptThread_.start(); + return true; + } catch (IOException e) { + LOGGER.error("Failed to start selector thread!", e); + return false; + } + } + + @Override + protected void waitForShutdown() { + joinSelector(); + } + + /** + * Block until the selector thread exits. + */ + protected void joinSelector() { + // wait until the selector thread exits + try { + selectAcceptThread_.join(); + } catch (InterruptedException e) { + // for now, just silently ignore. technically this means we'll have less of + // a graceful shutdown as a result. + } + } + + /** + * Stop serving and shut everything down. + */ + @Override + public void stop() { + stopped_ = true; + if (selectAcceptThread_ != null) { + selectAcceptThread_.wakeupSelector(); + } + } + + /** + * Perform an invocation. This method could behave several different ways + * - invoke immediately inline, queue for separate execution, etc. + */ + @Override + protected boolean requestInvoke(FrameBuffer frameBuffer) { + frameBuffer.invoke(); + return true; + } + + + public boolean isStopped() { + return selectAcceptThread_.isStopped(); + } + + /** + * The thread that will be doing all the selecting, managing new connections + * and those that still need to be read. + */ + protected class SelectAcceptThread extends AbstractSelectThread { + + // The server transport on which new client transports will be accepted + private final TNonblockingServerTransport serverTransport; + + /** + * Set up the thread that will handle the non-blocking accepts, reads, and + * writes. + */ + public SelectAcceptThread(final TNonblockingServerTransport serverTransport) + throws IOException { + this.serverTransport = serverTransport; + serverTransport.registerSelector(selector); + } + + public boolean isStopped() { + return stopped_; + } + + /** + * The work loop. Handles both selecting (all IO operations) and managing + * the selection preferences of all existing connections. + */ + public void run() { + try { + if (eventHandler_ != null) { + eventHandler_.preServe(); + } + + while (!stopped_) { + select(); + processInterestChanges(); + } + for (SelectionKey selectionKey : selector.keys()) { + cleanupSelectionKey(selectionKey); + } + } catch (Throwable t) { + LOGGER.error("run() exiting due to uncaught error", t); + } finally { + try { + selector.close(); + } catch (IOException e) { + LOGGER.error("Got an IOException while closing selector!", e); + } + stopped_ = true; + } + } + + /** + * Select and process IO events appropriately: + * If there are connections to be accepted, accept them. + * If there are existing connections with data waiting to be read, read it, + * buffering until a whole frame has been read. + * If there are any pending responses, buffer them until their target client + * is available, and then send the data. + */ + private void select() { + try { + // wait for io events. + selector.select(); + + // process the io events we received + Iterator selectedKeys = selector.selectedKeys().iterator(); + while (!stopped_ && selectedKeys.hasNext()) { + SelectionKey key = selectedKeys.next(); + selectedKeys.remove(); + + // skip if not valid + if (!key.isValid()) { + cleanupSelectionKey(key); + continue; + } + + // if the key is marked Accept, then it has to be the server + // transport. + if (key.isAcceptable()) { + handleAccept(); + } else if (key.isReadable()) { + // deal with reads + handleRead(key); + } else if (key.isWritable()) { + // deal with writes + handleWrite(key); + } else { + LOGGER.warn("Unexpected state in select! " + key.interestOps()); + } + } + } catch (IOException e) { + LOGGER.warn("Got an IOException while selecting!", e); + } + } + + protected FrameBuffer createFrameBuffer(final TNonblockingTransport trans, + final SelectionKey selectionKey, + final AbstractSelectThread selectThread) { + return processorFactory_.isAsyncProcessor() ? + new AsyncFrameBuffer(trans, selectionKey, selectThread) : + new FrameBuffer(trans, selectionKey, selectThread); + } + + /** + * Accept a new connection. + */ + private void handleAccept() throws IOException { + SelectionKey clientKey = null; + TNonblockingTransport client = null; + try { + // accept the connection + client = (TNonblockingTransport)serverTransport.accept(); + clientKey = client.registerSelector(selector, SelectionKey.OP_READ); + + // add this key to the map + FrameBuffer frameBuffer = createFrameBuffer(client, clientKey, SelectAcceptThread.this); + + clientKey.attach(frameBuffer); + } catch (TTransportException tte) { + // something went wrong accepting. + LOGGER.warn("Exception trying to accept!", tte); + tte.printStackTrace(); + if (clientKey != null) cleanupSelectionKey(clientKey); + if (client != null) client.close(); + } + } + } // SelectAcceptThread +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServer.java new file mode 100644 index 00000000..a9305721 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServer.java @@ -0,0 +1,177 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.server; + +import com.xiaomi.infra.pegasus.thrift.TProcessor; +import com.xiaomi.infra.pegasus.thrift.TProcessorFactory; +import com.xiaomi.infra.pegasus.thrift.protocol.TBinaryProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory; +import com.xiaomi.infra.pegasus.thrift.transport.TServerTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransportFactory; + +/** + * Generic interface for a Thrift server. + * + */ +public abstract class TServer { + + public static class Args extends AbstractServerArgs { + public Args(TServerTransport transport) { + super(transport); + } + } + + public static abstract class AbstractServerArgs> { + final TServerTransport serverTransport; + TProcessorFactory processorFactory; + TTransportFactory inputTransportFactory = new TTransportFactory(); + TTransportFactory outputTransportFactory = new TTransportFactory(); + TProtocolFactory inputProtocolFactory = new TBinaryProtocol.Factory(); + TProtocolFactory outputProtocolFactory = new TBinaryProtocol.Factory(); + + public AbstractServerArgs(TServerTransport transport) { + serverTransport = transport; + } + + public T processorFactory(TProcessorFactory factory) { + this.processorFactory = factory; + return (T) this; + } + + public T processor(TProcessor processor) { + this.processorFactory = new TProcessorFactory(processor); + return (T) this; + } + + public T transportFactory(TTransportFactory factory) { + this.inputTransportFactory = factory; + this.outputTransportFactory = factory; + return (T) this; + } + + public T inputTransportFactory(TTransportFactory factory) { + this.inputTransportFactory = factory; + return (T) this; + } + + public T outputTransportFactory(TTransportFactory factory) { + this.outputTransportFactory = factory; + return (T) this; + } + + public T protocolFactory(TProtocolFactory factory) { + this.inputProtocolFactory = factory; + this.outputProtocolFactory = factory; + return (T) this; + } + + public T inputProtocolFactory(TProtocolFactory factory) { + this.inputProtocolFactory = factory; + return (T) this; + } + + public T outputProtocolFactory(TProtocolFactory factory) { + this.outputProtocolFactory = factory; + return (T) this; + } + } + + /** + * Core processor + */ + protected TProcessorFactory processorFactory_; + + /** + * Server transport + */ + protected TServerTransport serverTransport_; + + /** + * Input Transport Factory + */ + protected TTransportFactory inputTransportFactory_; + + /** + * Output Transport Factory + */ + protected TTransportFactory outputTransportFactory_; + + /** + * Input Protocol Factory + */ + protected TProtocolFactory inputProtocolFactory_; + + /** + * Output Protocol Factory + */ + protected TProtocolFactory outputProtocolFactory_; + + private boolean isServing; + + protected TServerEventHandler eventHandler_; + + // Flag for stopping the server + // Please see THRIFT-1795 for the usage of this flag + protected volatile boolean stopped_ = false; + + protected TServer(AbstractServerArgs args) { + processorFactory_ = args.processorFactory; + serverTransport_ = args.serverTransport; + inputTransportFactory_ = args.inputTransportFactory; + outputTransportFactory_ = args.outputTransportFactory; + inputProtocolFactory_ = args.inputProtocolFactory; + outputProtocolFactory_ = args.outputProtocolFactory; + } + + /** + * The run method fires up the server and gets things going. + */ + public abstract void serve(); + + /** + * Stop the server. This is optional on a per-implementation basis. Not + * all servers are required to be cleanly stoppable. + */ + public void stop() {} + + public boolean isServing() { + return isServing; + } + + protected void setServing(boolean serving) { + isServing = serving; + } + + public void setServerEventHandler(TServerEventHandler eventHandler) { + eventHandler_ = eventHandler; + } + + public TServerEventHandler getEventHandler() { + return eventHandler_; + } + + public boolean getShouldStop() { + return this.stopped_; + } + + public void setShouldStop(boolean shouldStop) { + this.stopped_ = shouldStop; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServerEventHandler.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServerEventHandler.java new file mode 100644 index 00000000..fdff5586 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServerEventHandler.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.server; + +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * Interface that can handle events from the server core. To + * use this you should subclass it and implement the methods that you care + * about. Your subclass can also store local data that you may care about, + * such as additional "arguments" to these methods (stored in the object + * instance's state). + */ +public interface TServerEventHandler { + + /** + * Called before the server begins. + */ + void preServe(); + + /** + * Called when a new client has connected and is about to being processing. + */ + ServerContext createContext(TProtocol input, + TProtocol output); + + /** + * Called when a client has finished request-handling to delete server + * context. + */ + void deleteContext(ServerContext serverContext, + TProtocol input, + TProtocol output); + + /** + * Called when a client is about to call the processor. + */ + void processContext(ServerContext serverContext, + TTransport inputTransport, TTransport outputTransport); + +} \ No newline at end of file diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServlet.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServlet.java new file mode 100644 index 00000000..056d0512 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TServlet.java @@ -0,0 +1,119 @@ +package com.xiaomi.infra.pegasus.thrift.server; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.TProcessor; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory; +import com.xiaomi.infra.pegasus.thrift.transport.TIOStreamTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; + +/** + * Servlet implementation class ThriftServer + */ +public class TServlet extends HttpServlet { + + private final TProcessor processor; + + private final TProtocolFactory inProtocolFactory; + + private final TProtocolFactory outProtocolFactory; + + private final Collection> customHeaders; + + /** + * @see HttpServlet#HttpServlet() + */ + public TServlet(TProcessor processor, TProtocolFactory inProtocolFactory, + TProtocolFactory outProtocolFactory) { + super(); + this.processor = processor; + this.inProtocolFactory = inProtocolFactory; + this.outProtocolFactory = outProtocolFactory; + this.customHeaders = new ArrayList>(); + } + + /** + * @see HttpServlet#HttpServlet() + */ + public TServlet(TProcessor processor, TProtocolFactory protocolFactory) { + this(processor, protocolFactory, protocolFactory); + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse + * response) + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + TTransport inTransport = null; + TTransport outTransport = null; + + try { + response.setContentType("application/x-thrift"); + + if (null != this.customHeaders) { + for (Map.Entry header : this.customHeaders) { + response.addHeader(header.getKey(), header.getValue()); + } + } + InputStream in = request.getInputStream(); + OutputStream out = response.getOutputStream(); + + TTransport transport = new TIOStreamTransport(in, out); + inTransport = transport; + outTransport = transport; + + TProtocol inProtocol = inProtocolFactory.getProtocol(inTransport); + TProtocol outProtocol = outProtocolFactory.getProtocol(outTransport); + + processor.process(inProtocol, outProtocol); + out.flush(); + } catch (TException te) { + throw new ServletException(te); + } + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + doPost(request, response); + } + + public void addCustomHeader(final String key, final String value) { + this.customHeaders.add(new Map.Entry() { + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + public String setValue(String value) { + return null; + } + }); + } + + public void setCustomHeaders(Collection> headers) { + this.customHeaders.clear(); + this.customHeaders.addAll(headers); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TSimpleServer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TSimpleServer.java new file mode 100644 index 00000000..fb3f3bf3 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TSimpleServer.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.server; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.TProcessor; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Simple singlethreaded server for testing. + * + */ +public class TSimpleServer extends TServer { + + private static final Logger LOGGER = LoggerFactory.getLogger(TSimpleServer.class.getName()); + + public TSimpleServer(AbstractServerArgs args) { + super(args); + } + + public void serve() { + try { + serverTransport_.listen(); + } catch (TTransportException ttx) { + LOGGER.error("Error occurred during listening.", ttx); + return; + } + + // Run the preServe event + if (eventHandler_ != null) { + eventHandler_.preServe(); + } + + setServing(true); + + while (!stopped_) { + TTransport client = null; + TProcessor processor = null; + TTransport inputTransport = null; + TTransport outputTransport = null; + TProtocol inputProtocol = null; + TProtocol outputProtocol = null; + ServerContext connectionContext = null; + try { + client = serverTransport_.accept(); + if (client != null) { + processor = processorFactory_.getProcessor(client); + inputTransport = inputTransportFactory_.getTransport(client); + outputTransport = outputTransportFactory_.getTransport(client); + inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); + outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); + if (eventHandler_ != null) { + connectionContext = eventHandler_.createContext(inputProtocol, outputProtocol); + } + while (true) { + if (eventHandler_ != null) { + eventHandler_.processContext(connectionContext, inputTransport, outputTransport); + } + if(!processor.process(inputProtocol, outputProtocol)) { + break; + } + } + } + } catch (TTransportException ttx) { + // Client died, just move on + } catch (TException tx) { + if (!stopped_) { + LOGGER.error("Thrift error occurred during processing of message.", tx); + } + } catch (Exception x) { + if (!stopped_) { + LOGGER.error("Error occurred during processing of message.", x); + } + } + + if (eventHandler_ != null) { + eventHandler_.deleteContext(connectionContext, inputProtocol, outputProtocol); + } + + if (inputTransport != null) { + inputTransport.close(); + } + + if (outputTransport != null) { + outputTransport.close(); + } + + } + setServing(false); + } + + public void stop() { + stopped_ = true; + serverTransport_.interrupt(); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TThreadPoolServer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TThreadPoolServer.java new file mode 100644 index 00000000..0f3bdb07 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TThreadPoolServer.java @@ -0,0 +1,319 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.server; + +import java.util.Random; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.TProcessor; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.transport.TSaslTransportException; +import com.xiaomi.infra.pegasus.thrift.transport.TServerTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Server which uses Java's built in ThreadPool management to spawn off + * a worker pool that + * + */ +public class TThreadPoolServer extends TServer { + private static final Logger LOGGER = LoggerFactory.getLogger(TThreadPoolServer.class.getName()); + + public static class Args extends AbstractServerArgs { + public int minWorkerThreads = 5; + public int maxWorkerThreads = Integer.MAX_VALUE; + public ExecutorService executorService; + public int stopTimeoutVal = 60; + public TimeUnit stopTimeoutUnit = TimeUnit.SECONDS; + public int requestTimeout = 20; + public TimeUnit requestTimeoutUnit = TimeUnit.SECONDS; + public int beBackoffSlotLength = 100; + public TimeUnit beBackoffSlotLengthUnit = TimeUnit.MILLISECONDS; + + public Args(TServerTransport transport) { + super(transport); + } + + public Args minWorkerThreads(int n) { + minWorkerThreads = n; + return this; + } + + public Args maxWorkerThreads(int n) { + maxWorkerThreads = n; + return this; + } + + public Args stopTimeoutVal(int n) { + stopTimeoutVal = n; + return this; + } + + public Args stopTimeoutUnit(TimeUnit tu) { + stopTimeoutUnit = tu; + return this; + } + + public Args requestTimeout(int n) { + requestTimeout = n; + return this; + } + + public Args requestTimeoutUnit(TimeUnit tu) { + requestTimeoutUnit = tu; + return this; + } + //Binary exponential backoff slot length + public Args beBackoffSlotLength(int n) { + beBackoffSlotLength = n; + return this; + } + + //Binary exponential backoff slot time unit + public Args beBackoffSlotLengthUnit(TimeUnit tu) { + beBackoffSlotLengthUnit = tu; + return this; + } + + public Args executorService(ExecutorService executorService) { + this.executorService = executorService; + return this; + } + } + + // Executor service for handling client connections + private ExecutorService executorService_; + + private final TimeUnit stopTimeoutUnit; + + private final long stopTimeoutVal; + + private final TimeUnit requestTimeoutUnit; + + private final long requestTimeout; + + private final long beBackoffSlotInMillis; + + private Random random = new Random(System.currentTimeMillis()); + + public TThreadPoolServer(Args args) { + super(args); + + stopTimeoutUnit = args.stopTimeoutUnit; + stopTimeoutVal = args.stopTimeoutVal; + requestTimeoutUnit = args.requestTimeoutUnit; + requestTimeout = args.requestTimeout; + beBackoffSlotInMillis = args.beBackoffSlotLengthUnit.toMillis(args.beBackoffSlotLength); + + executorService_ = args.executorService != null ? + args.executorService : createDefaultExecutorService(args); + } + + private static ExecutorService createDefaultExecutorService(Args args) { + SynchronousQueue executorQueue = + new SynchronousQueue(); + return new ThreadPoolExecutor(args.minWorkerThreads, + args.maxWorkerThreads, + args.stopTimeoutVal, + args.stopTimeoutUnit, + executorQueue); + } + + + public void serve() { + try { + serverTransport_.listen(); + } catch (TTransportException ttx) { + LOGGER.error("Error occurred during listening.", ttx); + return; + } + + // Run the preServe event + if (eventHandler_ != null) { + eventHandler_.preServe(); + } + + stopped_ = false; + setServing(true); + int failureCount = 0; + while (!stopped_) { + try { + TTransport client = serverTransport_.accept(); + WorkerProcess wp = new WorkerProcess(client); + + int retryCount = 0; + long remainTimeInMillis = requestTimeoutUnit.toMillis(requestTimeout); + while(true) { + try { + executorService_.execute(wp); + break; + } catch(Throwable t) { + if (t instanceof RejectedExecutionException) { + retryCount++; + try { + if (remainTimeInMillis > 0) { + //do a truncated 20 binary exponential backoff sleep + long sleepTimeInMillis = ((long) (random.nextDouble() * + (1L << Math.min(retryCount, 20)))) * beBackoffSlotInMillis; + sleepTimeInMillis = Math.min(sleepTimeInMillis, remainTimeInMillis); + TimeUnit.MILLISECONDS.sleep(sleepTimeInMillis); + remainTimeInMillis = remainTimeInMillis - sleepTimeInMillis; + } else { + client.close(); + wp = null; + LOGGER.warn("Task has been rejected by ExecutorService " + retryCount + + " times till timedout, reason: " + t); + break; + } + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while waiting to place client on executor queue."); + Thread.currentThread().interrupt(); + break; + } + } else if (t instanceof Error) { + LOGGER.error("ExecutorService threw error: " + t, t); + throw (Error)t; + } else { + //for other possible runtime errors from ExecutorService, should also not kill serve + LOGGER.warn("ExecutorService threw error: " + t, t); + break; + } + } + } + } catch (TTransportException ttx) { + if (!stopped_) { + ++failureCount; + LOGGER.warn("Transport error occurred during acceptance of message.", ttx); + } + } + } + + executorService_.shutdown(); + + // Loop until awaitTermination finally does return without a interrupted + // exception. If we don't do this, then we'll shut down prematurely. We want + // to let the executorService clear it's task queue, closing client sockets + // appropriately. + long timeoutMS = stopTimeoutUnit.toMillis(stopTimeoutVal); + long now = System.currentTimeMillis(); + while (timeoutMS >= 0) { + try { + executorService_.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS); + break; + } catch (InterruptedException ix) { + long newnow = System.currentTimeMillis(); + timeoutMS -= (newnow - now); + now = newnow; + } + } + setServing(false); + } + + public void stop() { + stopped_ = true; + serverTransport_.interrupt(); + } + + private class WorkerProcess implements Runnable { + + /** + * Client that this services. + */ + private TTransport client_; + + /** + * Default constructor. + * + * @param client Transport to process + */ + private WorkerProcess(TTransport client) { + client_ = client; + } + + /** + * Loops on processing a client forever + */ + public void run() { + TProcessor processor = null; + TTransport inputTransport = null; + TTransport outputTransport = null; + TProtocol inputProtocol = null; + TProtocol outputProtocol = null; + + TServerEventHandler eventHandler = null; + ServerContext connectionContext = null; + + try { + processor = processorFactory_.getProcessor(client_); + inputTransport = inputTransportFactory_.getTransport(client_); + outputTransport = outputTransportFactory_.getTransport(client_); + inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); + outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); + + eventHandler = getEventHandler(); + if (eventHandler != null) { + connectionContext = eventHandler.createContext(inputProtocol, outputProtocol); + } + // we check stopped_ first to make sure we're not supposed to be shutting + // down. this is necessary for graceful shutdown. + while (true) { + + if (eventHandler != null) { + eventHandler.processContext(connectionContext, inputTransport, outputTransport); + } + + if(stopped_ || !processor.process(inputProtocol, outputProtocol)) { + break; + } + } + } catch (TSaslTransportException ttx) { + // Something thats not SASL was in the stream, continue silently + } catch (TTransportException ttx) { + // Assume the client died and continue silently + } catch (TException tx) { + LOGGER.error("Thrift error occurred during processing of message.", tx); + } catch (Exception x) { + LOGGER.error("Error occurred during processing of message.", x); + } finally { + if (eventHandler != null) { + eventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol); + } + if (inputTransport != null) { + inputTransport.close(); + } + if (outputTransport != null) { + outputTransport.close(); + } + if (client_.isOpen()) { + client_.close(); + } + } + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TThreadedSelectorServer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TThreadedSelectorServer.java new file mode 100644 index 00000000..1537d68c --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/server/TThreadedSelectorServer.java @@ -0,0 +1,744 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.server; + +import com.xiaomi.infra.pegasus.thrift.transport.TNonblockingServerTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TNonblockingTransport; +import com.xiaomi.infra.pegasus.thrift.transport.TTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.spi.SelectorProvider; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.TimeUnit; + +/** + * A Half-Sync/Half-Async server with a separate pool of threads to handle + * non-blocking I/O. Accepts are handled on a single thread, and a configurable + * number of nonblocking selector threads manage reading and writing of client + * connections. A synchronous worker thread pool handles processing of requests. + * + * Performs better than TNonblockingServer/THsHaServer in multi-core + * environments when the the bottleneck is CPU on the single selector thread + * handling I/O. In addition, because the accept handling is decoupled from + * reads/writes and invocation, the server has better ability to handle back- + * pressure from new connections (e.g. stop accepting when busy). + * + * Like TNonblockingServer, it relies on the use of TFramedTransport. + */ +public class TThreadedSelectorServer extends AbstractNonblockingServer { + private static final Logger LOGGER = LoggerFactory.getLogger(TThreadedSelectorServer.class.getName()); + + public static class Args extends AbstractNonblockingServerArgs { + + /** The number of threads for selecting on already-accepted connections */ + public int selectorThreads = 2; + /** + * The size of the executor service (if none is specified) that will handle + * invocations. This may be set to 0, in which case invocations will be + * handled directly on the selector threads (as is in TNonblockingServer) + */ + private int workerThreads = 5; + /** Time to wait for server to stop gracefully */ + private int stopTimeoutVal = 60; + private TimeUnit stopTimeoutUnit = TimeUnit.SECONDS; + /** The ExecutorService for handling dispatched requests */ + private ExecutorService executorService = null; + /** + * The size of the blocking queue per selector thread for passing accepted + * connections to the selector thread + */ + private int acceptQueueSizePerThread = 4; + + /** + * Determines the strategy for handling new accepted connections. + */ + public static enum AcceptPolicy { + /** + * Require accepted connection registration to be handled by the executor. + * If the worker pool is saturated, further accepts will be closed + * immediately. Slightly increases latency due to an extra scheduling. + */ + FAIR_ACCEPT, + /** + * Handle the accepts as fast as possible, disregarding the status of the + * executor service. + */ + FAST_ACCEPT + } + + private AcceptPolicy acceptPolicy = AcceptPolicy.FAST_ACCEPT; + + public Args(TNonblockingServerTransport transport) { + super(transport); + } + + public Args selectorThreads(int i) { + selectorThreads = i; + return this; + } + + public int getSelectorThreads() { + return selectorThreads; + } + + public Args workerThreads(int i) { + workerThreads = i; + return this; + } + + public int getWorkerThreads() { + return workerThreads; + } + + public int getStopTimeoutVal() { + return stopTimeoutVal; + } + + public Args stopTimeoutVal(int stopTimeoutVal) { + this.stopTimeoutVal = stopTimeoutVal; + return this; + } + + public TimeUnit getStopTimeoutUnit() { + return stopTimeoutUnit; + } + + public Args stopTimeoutUnit(TimeUnit stopTimeoutUnit) { + this.stopTimeoutUnit = stopTimeoutUnit; + return this; + } + + public ExecutorService getExecutorService() { + return executorService; + } + + public Args executorService(ExecutorService executorService) { + this.executorService = executorService; + return this; + } + + public int getAcceptQueueSizePerThread() { + return acceptQueueSizePerThread; + } + + public Args acceptQueueSizePerThread(int acceptQueueSizePerThread) { + this.acceptQueueSizePerThread = acceptQueueSizePerThread; + return this; + } + + public AcceptPolicy getAcceptPolicy() { + return acceptPolicy; + } + + public Args acceptPolicy(AcceptPolicy acceptPolicy) { + this.acceptPolicy = acceptPolicy; + return this; + } + + public void validate() { + if (selectorThreads <= 0) { + throw new IllegalArgumentException("selectorThreads must be positive."); + } + if (workerThreads < 0) { + throw new IllegalArgumentException("workerThreads must be non-negative."); + } + if (acceptQueueSizePerThread <= 0) { + throw new IllegalArgumentException("acceptQueueSizePerThread must be positive."); + } + } + } + + // The thread handling all accepts + private AcceptThread acceptThread; + + // Threads handling events on client transports + private final Set selectorThreads = new HashSet(); + + // This wraps all the functionality of queueing and thread pool management + // for the passing of Invocations from the selector thread(s) to the workers + // (if any). + private final ExecutorService invoker; + + private final Args args; + + /** + * Create the server with the specified Args configuration + */ + public TThreadedSelectorServer(Args args) { + super(args); + args.validate(); + invoker = args.executorService == null ? createDefaultExecutor(args) : args.executorService; + this.args = args; + } + + /** + * Start the accept and selector threads running to deal with clients. + * + * @return true if everything went ok, false if we couldn't start for some + * reason. + */ + @Override + protected boolean startThreads() { + try { + for (int i = 0; i < args.selectorThreads; ++i) { + selectorThreads.add(new SelectorThread(args.acceptQueueSizePerThread)); + } + acceptThread = new AcceptThread((TNonblockingServerTransport) serverTransport_, + createSelectorThreadLoadBalancer(selectorThreads)); + for (SelectorThread thread : selectorThreads) { + thread.start(); + } + acceptThread.start(); + return true; + } catch (IOException e) { + LOGGER.error("Failed to start threads!", e); + return false; + } + } + + /** + * Joins the accept and selector threads and shuts down the executor service. + */ + @Override + protected void waitForShutdown() { + try { + joinThreads(); + } catch (InterruptedException e) { + // Non-graceful shutdown occurred + LOGGER.error("Interrupted while joining threads!", e); + } + gracefullyShutdownInvokerPool(); + } + + protected void joinThreads() throws InterruptedException { + // wait until the io threads exit + acceptThread.join(); + for (SelectorThread thread : selectorThreads) { + thread.join(); + } + } + + /** + * Stop serving and shut everything down. + */ + @Override + public void stop() { + stopped_ = true; + + // Stop queuing connect attempts asap + stopListening(); + + if (acceptThread != null) { + acceptThread.wakeupSelector(); + } + if (selectorThreads != null) { + for (SelectorThread thread : selectorThreads) { + if (thread != null) + thread.wakeupSelector(); + } + } + } + + protected void gracefullyShutdownInvokerPool() { + // try to gracefully shut down the executor service + invoker.shutdown(); + + // Loop until awaitTermination finally does return without a interrupted + // exception. If we don't do this, then we'll shut down prematurely. We want + // to let the executorService clear it's task queue, closing client sockets + // appropriately. + long timeoutMS = args.stopTimeoutUnit.toMillis(args.stopTimeoutVal); + long now = System.currentTimeMillis(); + while (timeoutMS >= 0) { + try { + invoker.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS); + break; + } catch (InterruptedException ix) { + long newnow = System.currentTimeMillis(); + timeoutMS -= (newnow - now); + now = newnow; + } + } + } + + /** + * We override the standard invoke method here to queue the invocation for + * invoker service instead of immediately invoking. If there is no thread + * pool, handle the invocation inline on this thread + */ + @Override + protected boolean requestInvoke(FrameBuffer frameBuffer) { + Runnable invocation = getRunnable(frameBuffer); + if (invoker != null) { + try { + invoker.execute(invocation); + return true; + } catch (RejectedExecutionException rx) { + LOGGER.warn("ExecutorService rejected execution!", rx); + return false; + } + } else { + // Invoke on the caller's thread + invocation.run(); + return true; + } + } + + protected Runnable getRunnable(FrameBuffer frameBuffer) { + return new Invocation(frameBuffer); + } + + /** + * Helper to create the invoker if one is not specified + */ + protected static ExecutorService createDefaultExecutor(Args options) { + return (options.workerThreads > 0) ? Executors.newFixedThreadPool(options.workerThreads) : null; + } + + private static BlockingQueue createDefaultAcceptQueue(int queueSize) { + if (queueSize == 0) { + // Unbounded queue + return new LinkedBlockingQueue(); + } + return new ArrayBlockingQueue(queueSize); + } + + /** + * The thread that selects on the server transport (listen socket) and accepts + * new connections to hand off to the IO selector threads + */ + protected class AcceptThread extends Thread { + + // The listen socket to accept on + private final TNonblockingServerTransport serverTransport; + private final Selector acceptSelector; + + private final SelectorThreadLoadBalancer threadChooser; + + /** + * Set up the AcceptThead + * + * @throws IOException + */ + public AcceptThread(TNonblockingServerTransport serverTransport, + SelectorThreadLoadBalancer threadChooser) throws IOException { + this.serverTransport = serverTransport; + this.threadChooser = threadChooser; + this.acceptSelector = SelectorProvider.provider().openSelector(); + this.serverTransport.registerSelector(acceptSelector); + } + + /** + * The work loop. Selects on the server transport and accepts. If there was + * a server transport that had blocking accepts, and returned on blocking + * client transports, that should be used instead + */ + public void run() { + try { + if (eventHandler_ != null) { + eventHandler_.preServe(); + } + + while (!stopped_) { + select(); + } + } catch (Throwable t) { + LOGGER.error("run() on AcceptThread exiting due to uncaught error", t); + } finally { + try { + acceptSelector.close(); + } catch (IOException e) { + LOGGER.error("Got an IOException while closing accept selector!", e); + } + // This will wake up the selector threads + TThreadedSelectorServer.this.stop(); + } + } + + /** + * If the selector is blocked, wake it up. + */ + public void wakeupSelector() { + acceptSelector.wakeup(); + } + + /** + * Select and process IO events appropriately: If there are connections to + * be accepted, accept them. + */ + private void select() { + try { + // wait for connect events. + acceptSelector.select(); + + // process the io events we received + Iterator selectedKeys = acceptSelector.selectedKeys().iterator(); + while (!stopped_ && selectedKeys.hasNext()) { + SelectionKey key = selectedKeys.next(); + selectedKeys.remove(); + + // skip if not valid + if (!key.isValid()) { + continue; + } + + if (key.isAcceptable()) { + handleAccept(); + } else { + LOGGER.warn("Unexpected state in select! " + key.interestOps()); + } + } + } catch (IOException e) { + LOGGER.warn("Got an IOException while selecting!", e); + } + } + + /** + * Accept a new connection. + */ + private void handleAccept() { + final TNonblockingTransport client = doAccept(); + if (client != null) { + // Pass this connection to a selector thread + final SelectorThread targetThread = threadChooser.nextThread(); + + if (args.acceptPolicy == Args.AcceptPolicy.FAST_ACCEPT || invoker == null) { + doAddAccept(targetThread, client); + } else { + // FAIR_ACCEPT + try { + invoker.submit(new Runnable() { + public void run() { + doAddAccept(targetThread, client); + } + }); + } catch (RejectedExecutionException rx) { + LOGGER.warn("ExecutorService rejected accept registration!", rx); + // close immediately + client.close(); + } + } + } + } + + private TNonblockingTransport doAccept() { + try { + return (TNonblockingTransport) serverTransport.accept(); + } catch (TTransportException tte) { + // something went wrong accepting. + LOGGER.warn("Exception trying to accept!", tte); + return null; + } + } + + private void doAddAccept(SelectorThread thread, TNonblockingTransport client) { + if (!thread.addAcceptedConnection(client)) { + client.close(); + } + } + } // AcceptThread + + /** + * The SelectorThread(s) will be doing all the selecting on accepted active + * connections. + */ + protected class SelectorThread extends AbstractSelectThread { + + // Accepted connections added by the accept thread. + private final BlockingQueue acceptedQueue; + private int SELECTOR_AUTO_REBUILD_THRESHOLD = 512; + private long MONITOR_PERIOD = 1000L; + private int jvmBug = 0; + + /** + * Set up the SelectorThread with an unbounded queue for incoming accepts. + * + * @throws IOException + * if a selector cannot be created + */ + public SelectorThread() throws IOException { + this(new LinkedBlockingQueue()); + } + + /** + * Set up the SelectorThread with an bounded queue for incoming accepts. + * + * @throws IOException + * if a selector cannot be created + */ + public SelectorThread(int maxPendingAccepts) throws IOException { + this(createDefaultAcceptQueue(maxPendingAccepts)); + } + + /** + * Set up the SelectorThread with a specified queue for connections. + * + * @param acceptedQueue + * The BlockingQueue implementation for holding incoming accepted + * connections. + * @throws IOException + * if a selector cannot be created. + */ + public SelectorThread(BlockingQueue acceptedQueue) throws IOException { + this.acceptedQueue = acceptedQueue; + } + + /** + * Hands off an accepted connection to be handled by this thread. This + * method will block if the queue for new connections is at capacity. + * + * @param accepted + * The connection that has been accepted. + * @return true if the connection has been successfully added. + */ + public boolean addAcceptedConnection(TNonblockingTransport accepted) { + try { + acceptedQueue.put(accepted); + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while adding accepted connection!", e); + return false; + } + selector.wakeup(); + return true; + } + + /** + * The work loop. Handles selecting (read/write IO), dispatching, and + * managing the selection preferences of all existing connections. + */ + public void run() { + try { + while (!stopped_) { + select(); + processAcceptedConnections(); + processInterestChanges(); + } + for (SelectionKey selectionKey : selector.keys()) { + cleanupSelectionKey(selectionKey); + } + } catch (Throwable t) { + LOGGER.error("run() on SelectorThread exiting due to uncaught error", t); + } finally { + try { + selector.close(); + } catch (IOException e) { + LOGGER.error("Got an IOException while closing selector!", e); + } + // This will wake up the accept thread and the other selector threads + TThreadedSelectorServer.this.stop(); + } + } + + /** + * Select and process IO events appropriately: If there are existing + * connections with data waiting to be read, read it, buffering until a + * whole frame has been read. If there are any pending responses, buffer + * them until their target client is available, and then send the data. + */ + private void select() { + try { + + doSelect(); + + // process the io events we received + Iterator selectedKeys = selector.selectedKeys().iterator(); + while (!stopped_ && selectedKeys.hasNext()) { + SelectionKey key = selectedKeys.next(); + selectedKeys.remove(); + + // skip if not valid + if (!key.isValid()) { + cleanupSelectionKey(key); + continue; + } + + if (key.isReadable()) { + // deal with reads + handleRead(key); + } else if (key.isWritable()) { + // deal with writes + handleWrite(key); + } else { + LOGGER.warn("Unexpected state in select! " + key.interestOps()); + } + } + } catch (IOException e) { + LOGGER.warn("Got an IOException while selecting!", e); + } + } + + /** + * Do select and judge epoll bug happen. + * See : https://issues.apache.org/jira/browse/THRIFT-4251 + */ + private void doSelect() throws IOException { + long beforeSelect = System.currentTimeMillis(); + int selectedNums = selector.select(); + long afterSelect = System.currentTimeMillis(); + + if (selectedNums == 0) { + jvmBug++; + } else { + jvmBug = 0; + } + + long selectedTime = afterSelect - beforeSelect; + if (selectedTime >= MONITOR_PERIOD) { + jvmBug = 0; + } else if (jvmBug > SELECTOR_AUTO_REBUILD_THRESHOLD) { + LOGGER.warn("In {} ms happen {} times jvm bug; rebuilding selector.", MONITOR_PERIOD, jvmBug); + rebuildSelector(); + selector.selectNow(); + jvmBug = 0; + } + + } + + /** + * Replaces the current Selector of this SelectorThread with newly created Selector to work + * around the infamous epoll 100% CPU bug. + */ + private synchronized void rebuildSelector() { + final Selector oldSelector = selector; + if (oldSelector == null) { + return; + } + Selector newSelector = null; + try { + newSelector = Selector.open(); + LOGGER.warn("Created new Selector."); + } catch (IOException e) { + LOGGER.error("Create new Selector error.", e); + } + + for (SelectionKey key : oldSelector.selectedKeys()) { + if (!key.isValid() && key.readyOps() == 0) + continue; + SelectableChannel channel = key.channel(); + Object attachment = key.attachment(); + + try { + if (attachment == null) { + channel.register(newSelector, key.readyOps()); + } else { + channel.register(newSelector, key.readyOps(), attachment); + } + } catch (ClosedChannelException e) { + LOGGER.error("Register new selector key error.", e); + } + + } + + selector = newSelector; + try { + oldSelector.close(); + } catch (IOException e) { + LOGGER.error("Close old selector error.", e); + } + LOGGER.warn("Replace new selector success."); + } + + private void processAcceptedConnections() { + // Register accepted connections + while (!stopped_) { + TNonblockingTransport accepted = acceptedQueue.poll(); + if (accepted == null) { + break; + } + registerAccepted(accepted); + } + } + + protected FrameBuffer createFrameBuffer(final TNonblockingTransport trans, + final SelectionKey selectionKey, + final AbstractSelectThread selectThread) { + return processorFactory_.isAsyncProcessor() ? + new AsyncFrameBuffer(trans, selectionKey, selectThread) : + new FrameBuffer(trans, selectionKey, selectThread); + } + + private void registerAccepted(TNonblockingTransport accepted) { + SelectionKey clientKey = null; + try { + clientKey = accepted.registerSelector(selector, SelectionKey.OP_READ); + + FrameBuffer frameBuffer = createFrameBuffer(accepted, clientKey, SelectorThread.this); + + clientKey.attach(frameBuffer); + } catch (IOException e) { + LOGGER.warn("Failed to register accepted connection to selector!", e); + if (clientKey != null) { + cleanupSelectionKey(clientKey); + } + accepted.close(); + } + } + } // SelectorThread + + /** + * Creates a SelectorThreadLoadBalancer to be used by the accept thread for + * assigning newly accepted connections across the threads. + */ + protected SelectorThreadLoadBalancer createSelectorThreadLoadBalancer(Collection threads) { + return new SelectorThreadLoadBalancer(threads); + } + + /** + * A round robin load balancer for choosing selector threads for new + * connections. + */ + protected static class SelectorThreadLoadBalancer { + private final Collection threads; + private Iterator nextThreadIterator; + + public SelectorThreadLoadBalancer(Collection threads) { + if (threads.isEmpty()) { + throw new IllegalArgumentException("At least one selector thread is required"); + } + this.threads = Collections.unmodifiableList(new ArrayList(threads)); + nextThreadIterator = this.threads.iterator(); + } + + public SelectorThread nextThread() { + // Choose a selector thread (round robin) + if (!nextThreadIterator.hasNext()) { + nextThreadIterator = threads.iterator(); + } + return nextThreadIterator.next(); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBuffer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBuffer.java new file mode 100644 index 00000000..562174b3 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBuffer.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.xiaomi.infra.pegasus.thrift.transport; + +/** + * Helper class that wraps a byte[] so that it can expand and be reused. Users + * should call resizeIfNecessary to make sure the buffer has suitable capacity, + * and then use the array as needed. Note that the internal array will grow at a + * rate slightly faster than the requested capacity with the (untested) + * objective of avoiding expensive buffer allocations and copies. + */ +public class AutoExpandingBuffer { + private byte[] array; + + private final double growthCoefficient; + + public AutoExpandingBuffer(int initialCapacity, double growthCoefficient) { + if (growthCoefficient < 1.0) { + throw new IllegalArgumentException("Growth coefficient must be >= 1.0"); + } + array = new byte[initialCapacity]; + this.growthCoefficient = growthCoefficient; + } + + public void resizeIfNecessary(int size) { + if (array.length < size) { + byte[] newBuf = new byte[(int)(size * growthCoefficient)]; + System.arraycopy(array, 0, newBuf, 0, array.length); + array = newBuf; + } + } + + public byte[] array() { + return array; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBufferReadTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBufferReadTransport.java new file mode 100644 index 00000000..7867b355 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBufferReadTransport.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.xiaomi.infra.pegasus.thrift.transport; + +/** + * TTransport for reading from an AutoExpandingBuffer. + */ +public class AutoExpandingBufferReadTransport extends TTransport { + + private final AutoExpandingBuffer buf; + + private int pos = 0; + private int limit = 0; + + public AutoExpandingBufferReadTransport(int initialCapacity, double overgrowthCoefficient) { + this.buf = new AutoExpandingBuffer(initialCapacity, overgrowthCoefficient); + } + + public void fill(TTransport inTrans, int length) throws TTransportException { + buf.resizeIfNecessary(length); + inTrans.readAll(buf.array(), 0, length); + pos = 0; + limit = length; + } + + @Override + public void close() {} + + @Override + public boolean isOpen() { return true; } + + @Override + public void open() throws TTransportException {} + + @Override + public final int read(byte[] target, int off, int len) throws TTransportException { + int amtToRead = Math.min(len, getBytesRemainingInBuffer()); + System.arraycopy(buf.array(), pos, target, off, amtToRead); + consumeBuffer(amtToRead); + return amtToRead; + } + + @Override + public void write(byte[] buf, int off, int len) throws TTransportException { + throw new UnsupportedOperationException(); + } + + @Override + public final void consumeBuffer(int len) { + pos += len; + } + + @Override + public final byte[] getBuffer() { + return buf.array(); + } + + @Override + public final int getBufferPosition() { + return pos; + } + + @Override + public final int getBytesRemainingInBuffer() { + return limit - pos; + } +} + \ No newline at end of file diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBufferWriteTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBufferWriteTransport.java new file mode 100644 index 00000000..b246cf49 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/AutoExpandingBufferWriteTransport.java @@ -0,0 +1,66 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +/** + * TTransport for writing to an AutoExpandingBuffer. + */ +public final class AutoExpandingBufferWriteTransport extends TTransport { + + private final AutoExpandingBuffer buf; + private int pos; + + public AutoExpandingBufferWriteTransport(int initialCapacity, double growthCoefficient) { + this.buf = new AutoExpandingBuffer(initialCapacity, growthCoefficient); + this.pos = 0; + } + + @Override + public void close() {} + + @Override + public boolean isOpen() {return true;} + + @Override + public void open() throws TTransportException {} + + @Override + public int read(byte[] buf, int off, int len) throws TTransportException { + throw new UnsupportedOperationException(); + } + + @Override + public void write(byte[] toWrite, int off, int len) throws TTransportException { + buf.resizeIfNecessary(pos + len); + System.arraycopy(toWrite, off, buf.array(), pos, len); + pos += len; + } + + public AutoExpandingBuffer getBuf() { + return buf; + } + + public int getPos() { + return pos; + } + + public void reset() { + pos = 0; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TByteBuffer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TByteBuffer.java new file mode 100644 index 00000000..5f9e1e47 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TByteBuffer.java @@ -0,0 +1,87 @@ +package com.xiaomi.infra.pegasus.thrift.transport; + +import java.nio.BufferOverflowException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; + +/** + * ByteBuffer-backed implementation of TTransport. + */ +public final class TByteBuffer extends TTransport { + private final ByteBuffer byteBuffer; + + /** + * Creates a new TByteBuffer wrapping a given NIO ByteBuffer. + */ + public TByteBuffer(ByteBuffer byteBuffer) { + this.byteBuffer = byteBuffer; + } + + @Override + public boolean isOpen() { + return true; + } + + @Override + public void open() { + } + + @Override + public void close() { + } + + @Override + public int read(byte[] buf, int off, int len) throws TTransportException { + final int n = Math.min(byteBuffer.remaining(), len); + if (n > 0) { + try { + byteBuffer.get(buf, off, n); + } catch (BufferUnderflowException e) { + throw new TTransportException("Unexpected end of input buffer", e); + } + } + return n; + } + + @Override + public void write(byte[] buf, int off, int len) throws TTransportException { + try { + byteBuffer.put(buf, off, len); + } catch (BufferOverflowException e) { + throw new TTransportException("Not enough room in output buffer", e); + } + } + + /** + * Get the underlying NIO ByteBuffer. + */ + public ByteBuffer getByteBuffer() { + return byteBuffer; + } + + /** + * Convenience method to call clear() on the underlying NIO ByteBuffer. + */ + public TByteBuffer clear() { + byteBuffer.clear(); + return this; + } + + /** + * Convenience method to call flip() on the underlying NIO ByteBuffer. + */ + public TByteBuffer flip() { + byteBuffer.flip(); + return this; + } + + /** + * Convenience method to convert the underlying NIO ByteBuffer to a + * plain old byte array. + */ + public byte[] toByteArray() { + final byte[] data = new byte[byteBuffer.remaining()]; + byteBuffer.slice().get(data); + return data; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFastFramedTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFastFramedTransport.java new file mode 100644 index 00000000..7eccea67 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFastFramedTransport.java @@ -0,0 +1,197 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +/** + * This transport is wire compatible with {@link TFramedTransport}, but makes + * use of reusable, expanding read and write buffers in order to avoid + * allocating new byte[]s all the time. Since the buffers only expand, you + * should probably only use this transport if your messages are not too variably + * large, unless the persistent memory cost is not an issue. + * + * This implementation is NOT threadsafe. + */ +public class TFastFramedTransport extends TTransport { + + public static class Factory extends TTransportFactory { + private final int initialCapacity; + private final int maxLength; + + public Factory() { + this(DEFAULT_BUF_CAPACITY, DEFAULT_MAX_LENGTH); + } + + public Factory(int initialCapacity) { + this(initialCapacity, DEFAULT_MAX_LENGTH); + } + + public Factory(int initialCapacity, int maxLength) { + this.initialCapacity = initialCapacity; + this.maxLength = maxLength; + } + + @Override + public TTransport getTransport(TTransport trans) { + return new TFastFramedTransport(trans, + initialCapacity, + maxLength); + } + } + + /** + * How big should the default read and write buffers be? + */ + public static final int DEFAULT_BUF_CAPACITY = 1024; + /** + * How big is the largest allowable frame? Defaults to 16MB. + */ + public static final int DEFAULT_MAX_LENGTH = 16384000; + + private final TTransport underlying; + private final AutoExpandingBufferWriteTransport writeBuffer; + private AutoExpandingBufferReadTransport readBuffer; + private final int initialBufferCapacity; + private final byte[] i32buf = new byte[4]; + private final int maxLength; + + /** + * Create a new {@link TFastFramedTransport}. Use the defaults + * for initial buffer size and max frame length. + * @param underlying Transport that real reads and writes will go through to. + */ + public TFastFramedTransport(TTransport underlying) { + this(underlying, DEFAULT_BUF_CAPACITY, DEFAULT_MAX_LENGTH); + } + + /** + * Create a new {@link TFastFramedTransport}. Use the specified + * initial buffer capacity and the default max frame length. + * @param underlying Transport that real reads and writes will go through to. + * @param initialBufferCapacity The initial size of the read and write buffers. + * In practice, it's not critical to set this unless you know in advance that + * your messages are going to be very large. + */ + public TFastFramedTransport(TTransport underlying, int initialBufferCapacity) { + this(underlying, initialBufferCapacity, DEFAULT_MAX_LENGTH); + } + + /** + * + * @param underlying Transport that real reads and writes will go through to. + * @param initialBufferCapacity The initial size of the read and write buffers. + * In practice, it's not critical to set this unless you know in advance that + * your messages are going to be very large. (You can pass + * TFramedTransportWithReusableBuffer.DEFAULT_BUF_CAPACITY if you're only + * using this constructor because you want to set the maxLength.) + * @param maxLength The max frame size you are willing to read. You can use + * this parameter to limit how much memory can be allocated. + */ + public TFastFramedTransport(TTransport underlying, int initialBufferCapacity, int maxLength) { + this.underlying = underlying; + this.maxLength = maxLength; + this.initialBufferCapacity = initialBufferCapacity; + writeBuffer = new AutoExpandingBufferWriteTransport(initialBufferCapacity, 1.5); + readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity, 1.5); + } + + @Override + public void close() { + underlying.close(); + } + + @Override + public boolean isOpen() { + return underlying.isOpen(); + } + + @Override + public void open() throws TTransportException { + underlying.open(); + } + + @Override + public int read(byte[] buf, int off, int len) throws TTransportException { + int got = readBuffer.read(buf, off, len); + if (got > 0) { + return got; + } + + // Read another frame of data + readFrame(); + + return readBuffer.read(buf, off, len); + } + + private void readFrame() throws TTransportException { + underlying.readAll(i32buf , 0, 4); + int size = TFramedTransport.decodeFrameSize(i32buf); + + if (size < 0) { + close(); + throw new TTransportException(TTransportException.CORRUPTED_DATA, "Read a negative frame size (" + size + ")!"); + } + + if (size > maxLength) { + close(); + throw new TTransportException(TTransportException.CORRUPTED_DATA, + "Frame size (" + size + ") larger than max length (" + maxLength + ")!"); + } + + readBuffer.fill(underlying, size); + } + + @Override + public void write(byte[] buf, int off, int len) throws TTransportException { + writeBuffer.write(buf, off, len); + } + + @Override + public void consumeBuffer(int len) { + readBuffer.consumeBuffer(len); + } + + public void clear() { + readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity, 1.5); + } + + @Override + public void flush() throws TTransportException { + int length = writeBuffer.getPos(); + TFramedTransport.encodeFrameSize(length, i32buf); + underlying.write(i32buf, 0, 4); + underlying.write(writeBuffer.getBuf().array(), 0, length); + writeBuffer.reset(); + underlying.flush(); + } + + @Override + public byte[] getBuffer() { + return readBuffer.getBuffer(); + } + + @Override + public int getBufferPosition() { + return readBuffer.getBufferPosition(); + } + + @Override + public int getBytesRemainingInBuffer() { + return readBuffer.getBytesRemainingInBuffer(); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFileProcessor.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFileProcessor.java new file mode 100644 index 00000000..f5d7aae1 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFileProcessor.java @@ -0,0 +1,118 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import com.xiaomi.infra.pegasus.thrift.TProcessor; +import com.xiaomi.infra.pegasus.thrift.TException; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocol; +import com.xiaomi.infra.pegasus.thrift.protocol.TProtocolFactory; + +/** + * FileProcessor: helps in processing files generated by TFileTransport. + * Port of original cpp implementation + */ +public class TFileProcessor { + + private TProcessor processor_; + private TProtocolFactory inputProtocolFactory_; + private TProtocolFactory outputProtocolFactory_; + private TFileTransport inputTransport_; + private TTransport outputTransport_; + + public TFileProcessor(TProcessor processor, TProtocolFactory protocolFactory, + TFileTransport inputTransport, + TTransport outputTransport) { + processor_ = processor; + inputProtocolFactory_ = outputProtocolFactory_ = protocolFactory; + inputTransport_ = inputTransport; + outputTransport_ = outputTransport; + } + + public TFileProcessor(TProcessor processor, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, + TFileTransport inputTransport, + TTransport outputTransport) { + processor_ = processor; + inputProtocolFactory_ = inputProtocolFactory; + outputProtocolFactory_ = outputProtocolFactory; + inputTransport_ = inputTransport; + outputTransport_ = outputTransport; + } + + private void processUntil(int lastChunk) throws TException { + TProtocol ip = inputProtocolFactory_.getProtocol(inputTransport_); + TProtocol op = outputProtocolFactory_.getProtocol(outputTransport_); + int curChunk = inputTransport_.getCurChunk(); + + try { + while (lastChunk >= curChunk) { + processor_.process(ip, op); + int newChunk = inputTransport_.getCurChunk(); + curChunk = newChunk; + } + } catch (TTransportException e) { + // if we are processing the last chunk - we could have just hit EOF + // on EOF - trap the error and stop processing. + if(e.getType() != TTransportException.END_OF_FILE) + throw e; + else { + return; + } + } + } + + /** + * Process from start to last chunk both inclusive where chunks begin from 0 + + * @param startChunkNum first chunk to be processed + * @param endChunkNum last chunk to be processed + */ + public void processChunk(int startChunkNum, int endChunkNum) throws TException { + int numChunks = inputTransport_.getNumChunks(); + if(endChunkNum < 0) + endChunkNum += numChunks; + + if(startChunkNum < 0) + startChunkNum += numChunks; + + if(endChunkNum < startChunkNum) + throw new TException("endChunkNum " + endChunkNum + " is less than " + startChunkNum); + + inputTransport_.seekToChunk(startChunkNum); + processUntil(endChunkNum); + } + + /** + * Process a single chunk + * + * @param chunkNum chunk to be processed + */ + public void processChunk(int chunkNum) throws TException { + processChunk(chunkNum, chunkNum); + } + + /** + * Process a current chunk + */ + public void processChunk() throws TException { + processChunk(inputTransport_.getCurChunk()); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFileTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFileTransport.java new file mode 100644 index 00000000..3ccd0cb1 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFileTransport.java @@ -0,0 +1,621 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.util.Random; + +/** + * FileTransport implementation of the TTransport interface. + * Currently this is a straightforward port of the cpp implementation + * + * It may make better sense to provide a basic stream access on top of the framed file format + * The FileTransport can then be a user of this framed file format with some additional logic + * for chunking. + */ +public class TFileTransport extends TTransport { + + public static class TruncableBufferedInputStream extends BufferedInputStream { + public void trunc() { + pos = count = 0; + } + public TruncableBufferedInputStream(InputStream in) { + super(in); + } + public TruncableBufferedInputStream(InputStream in, int size) { + super(in, size); + } + } + + + public static class Event { + private byte[] buf_; + private int nread_; + private int navailable_; + + /** + * Initialize an event. Initially, it has no valid contents + * + * @param buf byte array buffer to store event + */ + public Event(byte[] buf) { + buf_ = buf; + nread_ = navailable_ = 0; + } + + public byte[] getBuf() { return buf_;} + public int getSize() { return buf_.length; } + + + public void setAvailable(int sz) { nread_ = 0; navailable_=sz;} + public int getRemaining() { return (navailable_ - nread_); } + + public int emit(byte[] buf, int offset, int ndesired) { + if((ndesired == 0) || (ndesired > getRemaining())) + ndesired = getRemaining(); + + if(ndesired <= 0) + return (ndesired); + + System.arraycopy(buf_, nread_, buf, offset, ndesired); + nread_ += ndesired; + + return(ndesired); + } + }; + + public static class ChunkState { + /** + * Chunk Size. Must be same across all implementations + */ + public static final int DEFAULT_CHUNK_SIZE = 16 * 1024 * 1024; + + private int chunk_size_ = DEFAULT_CHUNK_SIZE; + private long offset_ = 0; + + public ChunkState() {} + public ChunkState(int chunk_size) { chunk_size_ = chunk_size; } + + public void skip(int size) {offset_ += size; } + public void seek(long offset) {offset_ = offset;} + + public int getChunkSize() { return chunk_size_;} + public int getChunkNum() { return ((int)(offset_/chunk_size_));} + public int getRemaining() { return (chunk_size_ - ((int)(offset_ % chunk_size_)));} + public long getOffset() { return (offset_);} + } + + public static enum TailPolicy { + + NOWAIT(0, 0), + WAIT_FOREVER(500, -1); + + /** + * Time in milliseconds to sleep before next read + * If 0, no sleep + */ + public final int timeout_; + + /** + * Number of retries before giving up + * if 0, no retries + * if -1, retry forever + */ + public final int retries_; + + /** + * ctor for policy + * + * @param timeout sleep time for this particular policy + * @param retries number of retries + */ + + TailPolicy(int timeout, int retries) { + timeout_ = timeout; + retries_ = retries; + } + } + + /** + * Current tailing policy + */ + TailPolicy currentPolicy_ = TailPolicy.NOWAIT; + + + /** + * Underlying file being read + */ + protected TSeekableFile inputFile_ = null; + + /** + * Underlying outputStream + */ + protected OutputStream outputStream_ = null; + + + /** + * Event currently read in + */ + Event currentEvent_ = null; + + /** + * InputStream currently being used for reading + */ + InputStream inputStream_ = null; + + /** + * current Chunk state + */ + ChunkState cs = null; + + /** + * is read only? + */ + private boolean readOnly_ = false; + + /** + * Get File Tailing Policy + * + * @return current read policy + */ + public TailPolicy getTailPolicy() { + return (currentPolicy_); + } + + /** + * Set file Tailing Policy + * + * @param policy New policy to set + * @return Old policy + */ + public TailPolicy setTailPolicy(TailPolicy policy) { + TailPolicy old = currentPolicy_; + currentPolicy_ = policy; + return (old); + } + + + /** + * Initialize read input stream + * + * @return input stream to read from file + */ + private InputStream createInputStream() throws TTransportException { + InputStream is; + try { + if(inputStream_ != null) { + ((TruncableBufferedInputStream)inputStream_).trunc(); + is = inputStream_; + } else { + is = new TruncableBufferedInputStream(inputFile_.getInputStream()); + } + } catch (IOException iox) { + System.err.println("createInputStream: "+iox.getMessage()); + throw new TTransportException(iox.getMessage(), iox); + } + return(is); + } + + /** + * Read (potentially tailing) an input stream + * + * @param is InputStream to read from + * @param buf Buffer to read into + * @param off Offset in buffer to read into + * @param len Number of bytes to read + * @param tp policy to use if we hit EOF + * + * @return number of bytes read + */ + private int tailRead(InputStream is, byte[] buf, + int off, int len, TailPolicy tp) throws TTransportException { + int orig_len = len; + try { + int retries = 0; + while(len > 0) { + int cnt = is.read(buf, off, len); + if(cnt > 0) { + off += cnt; + len -= cnt; + retries = 0; + cs.skip(cnt); // remember that we read so many bytes + } else if (cnt == -1) { + // EOF + retries++; + + if((tp.retries_ != -1) && tp.retries_ < retries) + return (orig_len - len); + + if(tp.timeout_ > 0) { + try {Thread.sleep(tp.timeout_);} catch(InterruptedException e) {} + } + } else { + // either non-zero or -1 is what the contract says! + throw new + TTransportException("Unexpected return from InputStream.read = " + + cnt); + } + } + } catch (IOException iox) { + throw new TTransportException(iox.getMessage(), iox); + } + + return(orig_len - len); + } + + /** + * Event is corrupted. Do recovery + * + * @return true if recovery could be performed and we can read more data + * false is returned only when nothing more can be read + */ + private boolean performRecovery() throws TTransportException { + int numChunks = getNumChunks(); + int curChunk = cs.getChunkNum(); + + if(curChunk >= (numChunks-1)) { + return false; + } + seekToChunk(curChunk+1); + return true; + } + + /** + * Read event from underlying file + * + * @return true if event could be read, false otherwise (on EOF) + */ + private boolean readEvent() throws TTransportException { + byte[] ebytes = new byte[4]; + int esize; + int nread; + int nrequested; + + retry: + do { + // corner case. read to end of chunk + nrequested = cs.getRemaining(); + if(nrequested < 4) { + nread = tailRead(inputStream_, ebytes, 0, nrequested, currentPolicy_); + if(nread != nrequested) { + return(false); + } + } + + // assuming serialized on little endian machine + nread = tailRead(inputStream_, ebytes, 0, 4, currentPolicy_); + if(nread != 4) { + return(false); + } + + esize=0; + for(int i=3; i>=0; i--) { + int val = (0x000000ff & (int)ebytes[i]); + esize |= (val << (i*8)); + } + + // check if event is corrupted and do recovery as required + if(esize > cs.getRemaining()) { + throw new TTransportException("FileTransport error: bad event size"); + /* + if(performRecovery()) { + esize=0; + } else { + return false; + } + */ + } + } while (esize == 0); + + // reset existing event or get a larger one + if(currentEvent_.getSize() < esize) + currentEvent_ = new Event(new byte [esize]); + + // populate the event + byte[] buf = currentEvent_.getBuf(); + nread = tailRead(inputStream_, buf, 0, esize, currentPolicy_); + if(nread != esize) { + return(false); + } + currentEvent_.setAvailable(esize); + return(true); + } + + /** + * open if both input/output open unless readonly + * + * @return true + */ + public boolean isOpen() { + return ((inputStream_ != null) && (readOnly_ || (outputStream_ != null))); + } + + + /** + * Diverging from the cpp model and sticking to the TSocket model + * Files are not opened in ctor - but in explicit open call + */ + public void open() throws TTransportException { + if (isOpen()) + throw new TTransportException(TTransportException.ALREADY_OPEN); + + try { + inputStream_ = createInputStream(); + cs = new ChunkState(); + currentEvent_ = new Event(new byte [256]); + + if(!readOnly_) + outputStream_ = new BufferedOutputStream(inputFile_.getOutputStream(), 8192); + } catch (IOException iox) { + throw new TTransportException(TTransportException.NOT_OPEN, iox); + } + } + + /** + * Closes the transport. + */ + public void close() { + if (inputFile_ != null) { + try { + inputFile_.close(); + } catch (IOException iox) { + System.err.println("WARNING: Error closing input file: " + + iox.getMessage()); + } + inputFile_ = null; + } + if (outputStream_ != null) { + try { + outputStream_.close(); + } catch (IOException iox) { + System.err.println("WARNING: Error closing output stream: " + + iox.getMessage()); + } + outputStream_ = null; + } + } + + + /** + * File Transport ctor + * + * @param path File path to read and write from + * @param readOnly Whether this is a read-only transport + */ + public TFileTransport(final String path, boolean readOnly) throws IOException { + inputFile_ = new TStandardFile(path); + readOnly_ = readOnly; + } + + /** + * File Transport ctor + * + * @param inputFile open TSeekableFile to read/write from + * @param readOnly Whether this is a read-only transport + */ + public TFileTransport(TSeekableFile inputFile, boolean readOnly) { + inputFile_ = inputFile; + readOnly_ = readOnly; + } + + + /** + * Cloned from TTransport.java:readAll(). Only difference is throwing an EOF exception + * where one is detected. + */ + public int readAll(byte[] buf, int off, int len) + throws TTransportException { + int got = 0; + int ret = 0; + while (got < len) { + ret = read(buf, off+got, len-got); + if (ret < 0) { + throw new TTransportException("Error in reading from file"); + } + if(ret == 0) { + throw new TTransportException(TTransportException.END_OF_FILE, + "End of File reached"); + } + got += ret; + } + return got; + } + + + /** + * Reads up to len bytes into buffer buf, starting at offset off. + * + * @param buf Array to read into + * @param off Index to start reading at + * @param len Maximum number of bytes to read + * @return The number of bytes actually read + * @throws TTransportException if there was an error reading data + */ + public int read(byte[] buf, int off, int len) throws TTransportException { + if(!isOpen()) + throw new TTransportException(TTransportException.NOT_OPEN, + "Must open before reading"); + + if(currentEvent_.getRemaining() == 0) { + if(!readEvent()) + return(0); + } + + int nread = currentEvent_.emit(buf, off, len); + return nread; + } + + public int getNumChunks() throws TTransportException { + if(!isOpen()) + throw new TTransportException(TTransportException.NOT_OPEN, + "Must open before getNumChunks"); + try { + long len = inputFile_.length(); + if(len == 0) + return 0; + else + return (((int)(len/cs.getChunkSize())) + 1); + + } catch (IOException iox) { + throw new TTransportException(iox.getMessage(), iox); + } + } + + public int getCurChunk() throws TTransportException { + if(!isOpen()) + throw new TTransportException(TTransportException.NOT_OPEN, + "Must open before getCurChunk"); + return (cs.getChunkNum()); + + } + + + public void seekToChunk(int chunk) throws TTransportException { + if(!isOpen()) + throw new TTransportException(TTransportException.NOT_OPEN, + "Must open before seeking"); + + int numChunks = getNumChunks(); + + // file is empty, seeking to chunk is pointless + if (numChunks == 0) { + return; + } + + // negative indicates reverse seek (from the end) + if (chunk < 0) { + chunk += numChunks; + } + + // too large a value for reverse seek, just seek to beginning + if (chunk < 0) { + chunk = 0; + } + + long eofOffset=0; + boolean seekToEnd = (chunk >= numChunks); + if(seekToEnd) { + chunk = chunk - 1; + try { eofOffset = inputFile_.length(); } + catch (IOException iox) {throw new TTransportException(iox.getMessage(), + iox);} + } + + if(chunk*cs.getChunkSize() != cs.getOffset()) { + try { inputFile_.seek((long)chunk*cs.getChunkSize()); } + catch (IOException iox) { + System.err.println("createInputStream: "+iox.getMessage()); + throw new TTransportException("Seek to chunk " + + chunk + " " +iox.getMessage(), iox); + } + + cs.seek((long)chunk*cs.getChunkSize()); + currentEvent_.setAvailable(0); + inputStream_ = createInputStream(); + } + + if(seekToEnd) { + // waiting forever here - otherwise we can hit EOF and end up + // having consumed partial data from the data stream. + TailPolicy old = setTailPolicy(TailPolicy.WAIT_FOREVER); + while(cs.getOffset() < eofOffset) { readEvent(); } + currentEvent_.setAvailable(0); + setTailPolicy(old); + } + } + + public void seekToEnd() throws TTransportException { + if(!isOpen()) + throw new TTransportException(TTransportException.NOT_OPEN, + "Must open before seeking"); + seekToChunk(getNumChunks()); + } + + + /** + * Writes up to len bytes from the buffer. + * + * @param buf The output data buffer + * @param off The offset to start writing from + * @param len The number of bytes to write + * @throws TTransportException if there was an error writing data + */ + public void write(byte[] buf, int off, int len) throws TTransportException { + throw new TTransportException("Not Supported"); + } + + /** + * Flush any pending data out of a transport buffer. + * + * @throws TTransportException if there was an error writing out data. + */ + public void flush() throws TTransportException { + throw new TTransportException("Not Supported"); + } + + /** + * test program + * + */ + public static void main(String[] args) throws Exception { + + int num_chunks = 10; + + if((args.length < 1) || args[0].equals("--help") + || args[0].equals("-h") || args[0].equals("-?")) { + printUsage(); + } + + if(args.length > 1) { + try { + num_chunks = Integer.parseInt(args[1]); + } catch (Exception e) { + System.err.println("Cannot parse " + args[1]); + printUsage(); + } + } + + TFileTransport t = new TFileTransport(args[0], true); + t.open(); + System.out.println("NumChunks="+t.getNumChunks()); + + Random r = new Random(); + for(int j=0; j [num_chunks]"); + System.err.println(" (Opens and reads num_chunks chunks from file randomly)"); + System.exit(1); + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFramedTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFramedTransport.java new file mode 100644 index 00000000..fd09c5e9 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TFramedTransport.java @@ -0,0 +1,181 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import com.xiaomi.infra.pegasus.thrift.TByteArrayOutputStream; + +/** + * TFramedTransport is a buffered TTransport that ensures a fully read message + * every time by preceding messages with a 4-byte frame size. + */ +public class TFramedTransport extends TTransport { + + protected static final int DEFAULT_MAX_LENGTH = 16384000; + + private int maxLength_; + + /** + * Underlying transport + */ + private TTransport transport_ = null; + + /** + * Buffer for output + */ + private final TByteArrayOutputStream writeBuffer_ = + new TByteArrayOutputStream(1024); + + /** + * Buffer for input + */ + private final TMemoryInputTransport readBuffer_ = + new TMemoryInputTransport(new byte[0]); + + public static class Factory extends TTransportFactory { + private int maxLength_; + + public Factory() { + maxLength_ = TFramedTransport.DEFAULT_MAX_LENGTH; + } + + public Factory(int maxLength) { + maxLength_ = maxLength; + } + + @Override + public TTransport getTransport(TTransport base) { + return new TFramedTransport(base, maxLength_); + } + } + + /** + * Constructor wraps around another transport + */ + public TFramedTransport(TTransport transport, int maxLength) { + transport_ = transport; + maxLength_ = maxLength; + } + + public TFramedTransport(TTransport transport) { + transport_ = transport; + maxLength_ = TFramedTransport.DEFAULT_MAX_LENGTH; + } + + public void open() throws TTransportException { + transport_.open(); + } + + public boolean isOpen() { + return transport_.isOpen(); + } + + public void close() { + transport_.close(); + } + + public int read(byte[] buf, int off, int len) throws TTransportException { + int got = readBuffer_.read(buf, off, len); + if (got > 0) { + return got; + } + + // Read another frame of data + readFrame(); + + return readBuffer_.read(buf, off, len); + } + + @Override + public byte[] getBuffer() { + return readBuffer_.getBuffer(); + } + + @Override + public int getBufferPosition() { + return readBuffer_.getBufferPosition(); + } + + @Override + public int getBytesRemainingInBuffer() { + return readBuffer_.getBytesRemainingInBuffer(); + } + + @Override + public void consumeBuffer(int len) { + readBuffer_.consumeBuffer(len); + } + + public void clear() { + readBuffer_.clear(); + } + + private final byte[] i32buf = new byte[4]; + + private void readFrame() throws TTransportException { + transport_.readAll(i32buf, 0, 4); + int size = decodeFrameSize(i32buf); + + if (size < 0) { + close(); + throw new TTransportException(TTransportException.CORRUPTED_DATA, "Read a negative frame size (" + size + ")!"); + } + + if (size > maxLength_) { + close(); + throw new TTransportException(TTransportException.CORRUPTED_DATA, + "Frame size (" + size + ") larger than max length (" + maxLength_ + ")!"); + } + + byte[] buff = new byte[size]; + transport_.readAll(buff, 0, size); + readBuffer_.reset(buff); + } + + public void write(byte[] buf, int off, int len) throws TTransportException { + writeBuffer_.write(buf, off, len); + } + + @Override + public void flush() throws TTransportException { + byte[] buf = writeBuffer_.get(); + int len = writeBuffer_.len(); + writeBuffer_.reset(); + + encodeFrameSize(len, i32buf); + transport_.write(i32buf, 0, 4); + transport_.write(buf, 0, len); + transport_.flush(); + } + + public static final void encodeFrameSize(final int frameSize, final byte[] buf) { + buf[0] = (byte)(0xff & (frameSize >> 24)); + buf[1] = (byte)(0xff & (frameSize >> 16)); + buf[2] = (byte)(0xff & (frameSize >> 8)); + buf[3] = (byte)(0xff & (frameSize)); + } + + public static final int decodeFrameSize(final byte[] buf) { + return + ((buf[0] & 0xff) << 24) | + ((buf[1] & 0xff) << 16) | + ((buf[2] & 0xff) << 8) | + ((buf[3] & 0xff)); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/THttpClient.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/THttpClient.java new file mode 100644 index 00000000..5ae1ec52 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/THttpClient.java @@ -0,0 +1,362 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; + +import java.net.URL; +import java.net.HttpURLConnection; +import java.util.HashMap; +import java.util.Map; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.params.CoreConnectionPNames; + +/** + * HTTP implementation of the TTransport interface. Used for working with a + * Thrift web services implementation (using for example TServlet). + * + * This class offers two implementations of the HTTP transport. + * One uses HttpURLConnection instances, the other HttpClient from Apache + * Http Components. + * The chosen implementation depends on the constructor used to + * create the THttpClient instance. + * Using the THttpClient(String url) constructor or passing null as the + * HttpClient to THttpClient(String url, HttpClient client) will create an + * instance which will use HttpURLConnection. + * + * When using HttpClient, the following configuration leads to 5-15% + * better performance than the HttpURLConnection implementation: + * + * http.protocol.version=HttpVersion.HTTP_1_1 + * http.protocol.content-charset=UTF-8 + * http.protocol.expect-continue=false + * http.connection.stalecheck=false + * + * Also note that under high load, the HttpURLConnection implementation + * may exhaust the open file descriptor limit. + * + * @see THRIFT-970 + */ + +public class THttpClient extends TTransport { + + private URL url_ = null; + + private final ByteArrayOutputStream requestBuffer_ = new ByteArrayOutputStream(); + + private InputStream inputStream_ = null; + + private int connectTimeout_ = 0; + + private int readTimeout_ = 0; + + private Map customHeaders_ = null; + + private final HttpHost host; + + private final HttpClient client; + + public static class Factory extends TTransportFactory { + + private final String url; + private final HttpClient client; + + public Factory(String url) { + this.url = url; + this.client = null; + } + + public Factory(String url, HttpClient client) { + this.url = url; + this.client = client; + } + + @Override + public TTransport getTransport(TTransport trans) { + try { + if (null != client) { + return new THttpClient(url, client); + } else { + return new THttpClient(url); + } + } catch (TTransportException tte) { + return null; + } + } + } + + public THttpClient(String url) throws TTransportException { + try { + url_ = new URL(url); + this.client = null; + this.host = null; + } catch (IOException iox) { + throw new TTransportException(iox); + } + } + + public THttpClient(String url, HttpClient client) throws TTransportException { + try { + url_ = new URL(url); + this.client = client; + this.host = new HttpHost(url_.getHost(), -1 == url_.getPort() ? url_.getDefaultPort() : url_.getPort(), url_.getProtocol()); + } catch (IOException iox) { + throw new TTransportException(iox); + } + } + + public void setConnectTimeout(int timeout) { + connectTimeout_ = timeout; + if (null != this.client) { + // WARNING, this modifies the HttpClient params, this might have an impact elsewhere if the + // same HttpClient is used for something else. + client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connectTimeout_); + } + } + + public void setReadTimeout(int timeout) { + readTimeout_ = timeout; + if (null != this.client) { + // WARNING, this modifies the HttpClient params, this might have an impact elsewhere if the + // same HttpClient is used for something else. + client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, readTimeout_); + } + } + + public void setCustomHeaders(Map headers) { + customHeaders_ = headers; + } + + public void setCustomHeader(String key, String value) { + if (customHeaders_ == null) { + customHeaders_ = new HashMap(); + } + customHeaders_.put(key, value); + } + + public void open() {} + + public void close() { + if (null != inputStream_) { + try { + inputStream_.close(); + } catch (IOException ioe) { + ; + } + inputStream_ = null; + } + } + + public boolean isOpen() { + return true; + } + + public int read(byte[] buf, int off, int len) throws TTransportException { + if (inputStream_ == null) { + throw new TTransportException("Response buffer is empty, no request."); + } + try { + int ret = inputStream_.read(buf, off, len); + if (ret == -1) { + throw new TTransportException("No more data available."); + } + return ret; + } catch (IOException iox) { + throw new TTransportException(iox); + } + } + + public void write(byte[] buf, int off, int len) { + requestBuffer_.write(buf, off, len); + } + + /** + * copy from org.apache.http.util.EntityUtils#consume. Android has it's own httpcore + * that doesn't have a consume. + */ + private static void consume(final HttpEntity entity) throws IOException { + if (entity == null) { + return; + } + if (entity.isStreaming()) { + InputStream instream = entity.getContent(); + if (instream != null) { + instream.close(); + } + } + } + + private void flushUsingHttpClient() throws TTransportException { + + if (null == this.client) { + throw new TTransportException("Null HttpClient, aborting."); + } + + // Extract request and reset buffer + byte[] data = requestBuffer_.toByteArray(); + requestBuffer_.reset(); + + HttpPost post = null; + + InputStream is = null; + + try { + // Set request to path + query string + post = new HttpPost(this.url_.getFile()); + + // + // Headers are added to the HttpPost instance, not + // to HttpClient. + // + + post.setHeader("Content-Type", "application/x-thrift"); + post.setHeader("Accept", "application/x-thrift"); + post.setHeader("User-Agent", "Java/THttpClient/HC"); + + if (null != customHeaders_) { + for (Map.Entry header : customHeaders_.entrySet()) { + post.setHeader(header.getKey(), header.getValue()); + } + } + + post.setEntity(new ByteArrayEntity(data)); + + HttpResponse response = this.client.execute(this.host, post); + int responseCode = response.getStatusLine().getStatusCode(); + + // + // Retrieve the inputstream BEFORE checking the status code so + // resources get freed in the finally clause. + // + + is = response.getEntity().getContent(); + + if (responseCode != HttpStatus.SC_OK) { + throw new TTransportException("HTTP Response code: " + responseCode); + } + + // Read the responses into a byte array so we can release the connection + // early. This implies that the whole content will have to be read in + // memory, and that momentarily we might use up twice the memory (while the + // thrift struct is being read up the chain). + // Proceeding differently might lead to exhaustion of connections and thus + // to app failure. + + byte[] buf = new byte[1024]; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + int len = 0; + do { + len = is.read(buf); + if (len > 0) { + baos.write(buf, 0, len); + } + } while (-1 != len); + + try { + // Indicate we're done with the content. + consume(response.getEntity()); + } catch (IOException ioe) { + // We ignore this exception, it might only mean the server has no + // keep-alive capability. + } + + inputStream_ = new ByteArrayInputStream(baos.toByteArray()); + } catch (IOException ioe) { + // Abort method so the connection gets released back to the connection manager + if (null != post) { + post.abort(); + } + throw new TTransportException(ioe); + } finally { + if (null != is) { + // Close the entity's input stream, this will release the underlying connection + try { + is.close(); + } catch (IOException ioe) { + throw new TTransportException(ioe); + } + } + if (post != null) { + post.releaseConnection(); + } + } + } + + public void flush() throws TTransportException { + + if (null != this.client) { + flushUsingHttpClient(); + return; + } + + // Extract request and reset buffer + byte[] data = requestBuffer_.toByteArray(); + requestBuffer_.reset(); + + try { + // Create connection object + HttpURLConnection connection = (HttpURLConnection)url_.openConnection(); + + // Timeouts, only if explicitly set + if (connectTimeout_ > 0) { + connection.setConnectTimeout(connectTimeout_); + } + if (readTimeout_ > 0) { + connection.setReadTimeout(readTimeout_); + } + + // Make the request + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/x-thrift"); + connection.setRequestProperty("Accept", "application/x-thrift"); + connection.setRequestProperty("User-Agent", "Java/THttpClient"); + if (customHeaders_ != null) { + for (Map.Entry header : customHeaders_.entrySet()) { + connection.setRequestProperty(header.getKey(), header.getValue()); + } + } + connection.setDoOutput(true); + connection.connect(); + connection.getOutputStream().write(data); + + int responseCode = connection.getResponseCode(); + if (responseCode != HttpURLConnection.HTTP_OK) { + throw new TTransportException("HTTP Response code: " + responseCode); + } + + // Read the responses + inputStream_ = connection.getInputStream(); + + } catch (IOException iox) { + throw new TTransportException(iox); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TIOStreamTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TIOStreamTransport.java new file mode 100644 index 00000000..13c4702e --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TIOStreamTransport.java @@ -0,0 +1,164 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * This is the most commonly used base transport. It takes an InputStream + * and an OutputStream and uses those to perform all transport operations. + * This allows for compatibility with all the nice constructs Java already + * has to provide a variety of types of streams. + * + */ +public class TIOStreamTransport extends TTransport { + + private static final Logger LOGGER = LoggerFactory.getLogger(TIOStreamTransport.class.getName()); + + /** Underlying inputStream */ + protected InputStream inputStream_ = null; + + /** Underlying outputStream */ + protected OutputStream outputStream_ = null; + + /** + * Subclasses can invoke the default constructor and then assign the input + * streams in the open method. + */ + protected TIOStreamTransport() {} + + /** + * Input stream constructor. + * + * @param is Input stream to read from + */ + public TIOStreamTransport(InputStream is) { + inputStream_ = is; + } + + /** + * Output stream constructor. + * + * @param os Output stream to read from + */ + public TIOStreamTransport(OutputStream os) { + outputStream_ = os; + } + + /** + * Two-way stream constructor. + * + * @param is Input stream to read from + * @param os Output stream to read from + */ + public TIOStreamTransport(InputStream is, OutputStream os) { + inputStream_ = is; + outputStream_ = os; + } + + /** + * The streams must already be open at construction time, so this should + * always return true. + * + * @return true + */ + public boolean isOpen() { + return true; + } + + /** + * The streams must already be open. This method does nothing. + */ + public void open() throws TTransportException {} + + /** + * Closes both the input and output streams. + */ + public void close() { + if (inputStream_ != null) { + try { + inputStream_.close(); + } catch (IOException iox) { + LOGGER.warn("Error closing input stream.", iox); + } + inputStream_ = null; + } + if (outputStream_ != null) { + try { + outputStream_.close(); + } catch (IOException iox) { + LOGGER.warn("Error closing output stream.", iox); + } + outputStream_ = null; + } + } + + /** + * Reads from the underlying input stream if not null. + */ + public int read(byte[] buf, int off, int len) throws TTransportException { + if (inputStream_ == null) { + throw new TTransportException(TTransportException.NOT_OPEN, "Cannot read from null inputStream"); + } + int bytesRead; + try { + bytesRead = inputStream_.read(buf, off, len); + } catch (IOException iox) { + throw new TTransportException(TTransportException.UNKNOWN, iox); + } + if (bytesRead < 0) { + throw new TTransportException(TTransportException.END_OF_FILE); + } + return bytesRead; + } + + /** + * Writes to the underlying output stream if not null. + */ + public void write(byte[] buf, int off, int len) throws TTransportException { + if (outputStream_ == null) { + throw new TTransportException(TTransportException.NOT_OPEN, "Cannot write to null outputStream"); + } + try { + outputStream_.write(buf, off, len); + } catch (IOException iox) { + throw new TTransportException(TTransportException.UNKNOWN, iox); + } + } + + /** + * Flushes the underlying output stream if not null. + */ + public void flush() throws TTransportException { + if (outputStream_ == null) { + throw new TTransportException(TTransportException.NOT_OPEN, "Cannot flush null outputStream"); + } + try { + outputStream_.flush(); + } catch (IOException iox) { + throw new TTransportException(TTransportException.UNKNOWN, iox); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TMemoryBuffer.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TMemoryBuffer.java new file mode 100644 index 00000000..90d2f67f --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TMemoryBuffer.java @@ -0,0 +1,102 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import com.xiaomi.infra.pegasus.thrift.TByteArrayOutputStream; +import java.io.UnsupportedEncodingException; + +/** + * Memory buffer-based implementation of the TTransport interface. + */ +public class TMemoryBuffer extends TTransport { + /** + * Create a TMemoryBuffer with an initial buffer size of size. The + * internal buffer will grow as necessary to accommodate the size of the data + * being written to it. + */ + public TMemoryBuffer(int size) { + arr_ = new TByteArrayOutputStream(size); + } + + @Override + public boolean isOpen() { + return true; + } + + @Override + public void open() { + /* Do nothing */ + } + + @Override + public void close() { + /* Do nothing */ + } + + @Override + public int read(byte[] buf, int off, int len) { + byte[] src = arr_.get(); + int amtToRead = (len > arr_.len() - pos_ ? arr_.len() - pos_ : len); + if (amtToRead > 0) { + System.arraycopy(src, pos_, buf, off, amtToRead); + pos_ += amtToRead; + } + return amtToRead; + } + + @Override + public void write(byte[] buf, int off, int len) { + arr_.write(buf, off, len); + } + + /** + * Output the contents of the memory buffer as a String, using the supplied + * encoding + * @param enc the encoding to use + * @return the contents of the memory buffer as a String + */ + public String toString(String enc) throws UnsupportedEncodingException { + return arr_.toString(enc); + } + + public String inspect() { + StringBuilder buf = new StringBuilder(); + byte[] bytes = arr_.toByteArray(); + for (int i = 0; i < bytes.length; i++) { + buf.append(pos_ == i ? "==>" : "" ).append(Integer.toHexString(bytes[i] & 0xff)).append(" "); + } + return buf.toString(); + } + + // The contents of the buffer + private TByteArrayOutputStream arr_; + + // Position to read next byte from + private int pos_; + + public int length() { + return arr_.size(); + } + + public byte[] getArray() { + return arr_.get(); + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TMemoryInputTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TMemoryInputTransport.java new file mode 100644 index 00000000..ae0f9955 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TMemoryInputTransport.java @@ -0,0 +1,96 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +public final class TMemoryInputTransport extends TTransport { + + private byte[] buf_; + private int pos_; + private int endPos_; + + public TMemoryInputTransport() { + } + + public TMemoryInputTransport(byte[] buf) { + reset(buf); + } + + public TMemoryInputTransport(byte[] buf, int offset, int length) { + reset(buf, offset, length); + } + + public void reset(byte[] buf) { + reset(buf, 0, buf.length); + } + + public void reset(byte[] buf, int offset, int length) { + buf_ = buf; + pos_ = offset; + endPos_ = offset + length; + } + + public void clear() { + buf_ = null; + } + + @Override + public void close() {} + + @Override + public boolean isOpen() { + return true; + } + + @Override + public void open() throws TTransportException {} + + @Override + public int read(byte[] buf, int off, int len) throws TTransportException { + int bytesRemaining = getBytesRemainingInBuffer(); + int amtToRead = (len > bytesRemaining ? bytesRemaining : len); + if (amtToRead > 0) { + System.arraycopy(buf_, pos_, buf, off, amtToRead); + consumeBuffer(amtToRead); + } + return amtToRead; + } + + @Override + public void write(byte[] buf, int off, int len) throws TTransportException { + throw new UnsupportedOperationException("No writing allowed!"); + } + + @Override + public byte[] getBuffer() { + return buf_; + } + + public int getBufferPosition() { + return pos_; + } + + public int getBytesRemainingInBuffer() { + return endPos_ - pos_; + } + + public void consumeBuffer(int len) { + pos_ += len; + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingServerSocket.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingServerSocket.java new file mode 100644 index 00000000..7447b9ab --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingServerSocket.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.SocketException; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Wrapper around ServerSocketChannel + */ +public class TNonblockingServerSocket extends TNonblockingServerTransport { + private static final Logger LOGGER = LoggerFactory.getLogger(TNonblockingServerSocket.class.getName()); + + /** + * This channel is where all the nonblocking magic happens. + */ + private ServerSocketChannel serverSocketChannel = null; + + /** + * Underlying ServerSocket object + */ + private ServerSocket serverSocket_ = null; + + /** + * Timeout for client sockets from accept + */ + private int clientTimeout_ = 0; + + public static class NonblockingAbstractServerSocketArgs extends + AbstractServerTransportArgs {} + + /** + * Creates just a port listening server socket + */ + public TNonblockingServerSocket(int port) throws TTransportException { + this(port, 0); + } + + /** + * Creates just a port listening server socket + */ + public TNonblockingServerSocket(int port, int clientTimeout) throws TTransportException { + this(new NonblockingAbstractServerSocketArgs().port(port).clientTimeout(clientTimeout)); + } + + public TNonblockingServerSocket(InetSocketAddress bindAddr) throws TTransportException { + this(bindAddr, 0); + } + + public TNonblockingServerSocket(InetSocketAddress bindAddr, int clientTimeout) throws TTransportException { + this(new NonblockingAbstractServerSocketArgs().bindAddr(bindAddr).clientTimeout(clientTimeout)); + } + + public TNonblockingServerSocket(NonblockingAbstractServerSocketArgs args) throws TTransportException { + clientTimeout_ = args.clientTimeout; + try { + serverSocketChannel = ServerSocketChannel.open(); + serverSocketChannel.configureBlocking(false); + + // Make server socket + serverSocket_ = serverSocketChannel.socket(); + // Prevent 2MSL delay problem on server restarts + serverSocket_.setReuseAddress(true); + // Bind to listening port + serverSocket_.bind(args.bindAddr, args.backlog); + } catch (IOException ioe) { + serverSocket_ = null; + throw new TTransportException("Could not create ServerSocket on address " + args.bindAddr.toString() + ".", ioe); + } + } + + public void listen() throws TTransportException { + // Make sure not to block on accept + if (serverSocket_ != null) { + try { + serverSocket_.setSoTimeout(0); + } catch (SocketException sx) { + sx.printStackTrace(); + } + } + } + + protected TNonblockingSocket acceptImpl() throws TTransportException { + if (serverSocket_ == null) { + throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket."); + } + try { + SocketChannel socketChannel = serverSocketChannel.accept(); + if (socketChannel == null) { + return null; + } + + TNonblockingSocket tsocket = new TNonblockingSocket(socketChannel); + tsocket.setTimeout(clientTimeout_); + return tsocket; + } catch (IOException iox) { + throw new TTransportException(iox); + } + } + + public void registerSelector(Selector selector) { + try { + // Register the server socket channel, indicating an interest in + // accepting new connections + serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); + } catch (ClosedChannelException e) { + // this shouldn't happen, ideally... + // TODO: decide what to do with this. + } + } + + public void close() { + if (serverSocket_ != null) { + try { + serverSocket_.close(); + } catch (IOException iox) { + LOGGER.warn("WARNING: Could not close server socket: " + iox.getMessage()); + } + serverSocket_ = null; + } + } + + public void interrupt() { + // The thread-safeness of this is dubious, but Java documentation suggests + // that it is safe to do this from a different thread context + close(); + } + + public int getPort() { + if (serverSocket_ == null) + return -1; + return serverSocket_.getLocalPort(); + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingServerTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingServerTransport.java new file mode 100644 index 00000000..d4f25aed --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingServerTransport.java @@ -0,0 +1,31 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.nio.channels.Selector; + +/** + * Server transport that can be operated in a nonblocking fashion. + */ +public abstract class TNonblockingServerTransport extends TServerTransport { + + public abstract void registerSelector(Selector selector); +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingSocket.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingSocket.java new file mode 100644 index 00000000..cf22c890 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingSocket.java @@ -0,0 +1,210 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Transport for use with async client. + */ +public class TNonblockingSocket extends TNonblockingTransport { + + private static final Logger LOGGER = LoggerFactory.getLogger(TNonblockingSocket.class.getName()); + + /** + * Host and port if passed in, used for lazy non-blocking connect. + */ + private final SocketAddress socketAddress_; + + private final SocketChannel socketChannel_; + + public TNonblockingSocket(String host, int port) throws IOException { + this(host, port, 0); + } + + /** + * Create a new nonblocking socket transport that will be connected to host:port. + * @param host + * @param port + * @throws IOException + */ + public TNonblockingSocket(String host, int port, int timeout) throws IOException { + this(SocketChannel.open(), timeout, new InetSocketAddress(host, port)); + } + + /** + * Constructor that takes an already created socket. + * + * @param socketChannel Already created SocketChannel object + * @throws IOException if there is an error setting up the streams + */ + public TNonblockingSocket(SocketChannel socketChannel) throws IOException { + this(socketChannel, 0, null); + if (!socketChannel.isConnected()) throw new IOException("Socket must already be connected"); + } + + private TNonblockingSocket(SocketChannel socketChannel, int timeout, SocketAddress socketAddress) + throws IOException { + socketChannel_ = socketChannel; + socketAddress_ = socketAddress; + + // make it a nonblocking channel + socketChannel.configureBlocking(false); + + // set options + Socket socket = socketChannel.socket(); + socket.setSoLinger(false, 0); + socket.setTcpNoDelay(true); + socket.setKeepAlive(true); + setTimeout(timeout); + } + + /** + * Register the new SocketChannel with our Selector, indicating + * we'd like to be notified when it's ready for I/O. + * + * @param selector + * @return the selection key for this socket. + */ + public SelectionKey registerSelector(Selector selector, int interests) throws IOException { + return socketChannel_.register(selector, interests); + } + + /** + * Sets the socket timeout, although this implementation never uses blocking operations so it is unused. + * + * @param timeout Milliseconds timeout + */ + public void setTimeout(int timeout) { + try { + socketChannel_.socket().setSoTimeout(timeout); + } catch (SocketException sx) { + LOGGER.warn("Could not set socket timeout.", sx); + } + } + + /** + * Returns a reference to the underlying SocketChannel. + */ + public SocketChannel getSocketChannel() { + return socketChannel_; + } + + /** + * Checks whether the socket is connected. + */ + public boolean isOpen() { + // isConnected() does not return false after close(), but isOpen() does + return socketChannel_.isOpen() && socketChannel_.isConnected(); + } + + /** + * Do not call, the implementation provides its own lazy non-blocking connect. + */ + public void open() throws TTransportException { + throw new RuntimeException("open() is not implemented for TNonblockingSocket"); + } + + /** + * Perform a nonblocking read into buffer. + */ + public int read(ByteBuffer buffer) throws IOException { + return socketChannel_.read(buffer); + } + + + /** + * Reads from the underlying input stream if not null. + */ + public int read(byte[] buf, int off, int len) throws TTransportException { + if ((socketChannel_.validOps() & SelectionKey.OP_READ) != SelectionKey.OP_READ) { + throw new TTransportException(TTransportException.NOT_OPEN, + "Cannot read from write-only socket channel"); + } + try { + return socketChannel_.read(ByteBuffer.wrap(buf, off, len)); + } catch (IOException iox) { + throw new TTransportException(TTransportException.UNKNOWN, iox); + } + } + + /** + * Perform a nonblocking write of the data in buffer; + */ + public int write(ByteBuffer buffer) throws IOException { + return socketChannel_.write(buffer); + } + + /** + * Writes to the underlying output stream if not null. + */ + public void write(byte[] buf, int off, int len) throws TTransportException { + if ((socketChannel_.validOps() & SelectionKey.OP_WRITE) != SelectionKey.OP_WRITE) { + throw new TTransportException(TTransportException.NOT_OPEN, + "Cannot write to write-only socket channel"); + } + try { + socketChannel_.write(ByteBuffer.wrap(buf, off, len)); + } catch (IOException iox) { + throw new TTransportException(TTransportException.UNKNOWN, iox); + } + } + + /** + * Noop. + */ + public void flush() throws TTransportException { + // Not supported by SocketChannel. + } + + /** + * Closes the socket. + */ + public void close() { + try { + socketChannel_.close(); + } catch (IOException iox) { + LOGGER.warn("Could not close socket.", iox); + } + } + + /** {@inheritDoc} */ + public boolean startConnect() throws IOException { + return socketChannel_.connect(socketAddress_); + } + + /** {@inheritDoc} */ + public boolean finishConnect() throws IOException { + return socketChannel_.finishConnect(); + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingTransport.java new file mode 100644 index 00000000..a579c2a5 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TNonblockingTransport.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.IOException; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; + +public abstract class TNonblockingTransport extends TTransport { + + /** + * Non-blocking connection initialization. + * @see java.nio.channels.SocketChannel#connect(SocketAddress remote) + */ + public abstract boolean startConnect() throws IOException; + + /** + * Non-blocking connection completion. + * @see java.nio.channels.SocketChannel#finishConnect() + */ + public abstract boolean finishConnect() throws IOException; + + public abstract SelectionKey registerSelector(Selector selector, int interests) throws IOException; + + public abstract int read(ByteBuffer buffer) throws IOException; + + public abstract int write(ByteBuffer buffer) throws IOException; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSSLTransportFactory.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSSLTransportFactory.java new file mode 100644 index 00000000..2e330e39 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSSLTransportFactory.java @@ -0,0 +1,385 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.URL; +import java.net.MalformedURLException; +import java.security.KeyStore; +import java.util.Arrays; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; + +/** + * A Factory for providing and setting up Client and Server SSL wrapped + * TSocket and TServerSocket + */ +public class TSSLTransportFactory { + + /** + * Get a SSL wrapped TServerSocket bound to the specified port. In this + * configuration the default settings are used. Default settings are retrieved + * from System properties that are set. + * + * Example system properties: + * -Djavax.net.ssl.trustStore=<truststore location> + * -Djavax.net.ssl.trustStorePassword=password + * -Djavax.net.ssl.keyStore=<keystore location> + * -Djavax.net.ssl.keyStorePassword=password + * + * @param port + * @return A SSL wrapped TServerSocket + * @throws TTransportException + */ + public static TServerSocket getServerSocket(int port) throws TTransportException { + return getServerSocket(port, 0); + } + + /** + * Get a default SSL wrapped TServerSocket bound to the specified port + * + * @param port + * @param clientTimeout + * @return A SSL wrapped TServerSocket + * @throws TTransportException + */ + public static TServerSocket getServerSocket(int port, int clientTimeout) throws TTransportException { + return getServerSocket(port, clientTimeout, false, null); + } + + /** + * Get a default SSL wrapped TServerSocket bound to the specified port and interface + * + * @param port + * @param clientTimeout + * @param ifAddress + * @return A SSL wrapped TServerSocket + * @throws TTransportException + */ + public static TServerSocket getServerSocket(int port, int clientTimeout, boolean clientAuth, InetAddress ifAddress) throws TTransportException { + SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + return createServer(factory, port, clientTimeout, clientAuth, ifAddress, null); + } + + /** + * Get a configured SSL wrapped TServerSocket bound to the specified port and interface. + * Here the TSSLTransportParameters are used to set the values for the algorithms, keystore, + * truststore and other settings + * + * @param port + * @param clientTimeout + * @param ifAddress + * @param params + * @return A SSL wrapped TServerSocket + * @throws TTransportException + */ + public static TServerSocket getServerSocket(int port, int clientTimeout, InetAddress ifAddress, TSSLTransportParameters params) throws TTransportException { + if (params == null || !(params.isKeyStoreSet || params.isTrustStoreSet)) { + throw new TTransportException("Either one of the KeyStore or TrustStore must be set for SSLTransportParameters"); + } + + SSLContext ctx = createSSLContext(params); + return createServer(ctx.getServerSocketFactory(), port, clientTimeout, params.clientAuth, ifAddress, params); + } + + private static TServerSocket createServer(SSLServerSocketFactory factory, int port, int timeout, boolean clientAuth, + InetAddress ifAddress, TSSLTransportParameters params) throws TTransportException { + try { + SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(port, 100, ifAddress); + serverSocket.setSoTimeout(timeout); + serverSocket.setNeedClientAuth(clientAuth); + if (params != null && params.cipherSuites != null) { + serverSocket.setEnabledCipherSuites(params.cipherSuites); + } + return new TServerSocket(new TServerSocket.ServerSocketTransportArgs(). + serverSocket(serverSocket).clientTimeout(timeout)); + } catch (Exception e) { + throw new TTransportException("Could not bind to port " + port, e); + } + } + + /** + * Get a default SSL wrapped TSocket connected to the specified host and port. All + * the client methods return a bound connection. So there is no need to call open() on the + * TTransport. + * + * @param host + * @param port + * @param timeout + * @return A SSL wrapped TSocket + * @throws TTransportException + */ + public static TSocket getClientSocket(String host, int port, int timeout) throws TTransportException { + SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); + return createClient(factory, host, port, timeout); + } + + /** + * Get a default SSL wrapped TSocket connected to the specified host and port. + * + * @param host + * @param port + * @return A SSL wrapped TSocket + * @throws TTransportException + */ + public static TSocket getClientSocket(String host, int port) throws TTransportException { + return getClientSocket(host, port, 0); + } + + /** + * Get a custom configured SSL wrapped TSocket. The SSL settings are obtained from the + * passed in TSSLTransportParameters. + * + * @param host + * @param port + * @param timeout + * @param params + * @return A SSL wrapped TSocket + * @throws TTransportException + */ + public static TSocket getClientSocket(String host, int port, int timeout, TSSLTransportParameters params) throws TTransportException { + if (params == null || !(params.isKeyStoreSet || params.isTrustStoreSet)) { + throw new TTransportException("Either one of the KeyStore or TrustStore must be set for SSLTransportParameters"); + } + + SSLContext ctx = createSSLContext(params); + return createClient(ctx.getSocketFactory(), host, port, timeout); + } + + private static SSLContext createSSLContext(TSSLTransportParameters params) throws TTransportException { + SSLContext ctx; + InputStream in = null; + InputStream is = null; + + try { + ctx = SSLContext.getInstance(params.protocol); + TrustManagerFactory tmf = null; + KeyManagerFactory kmf = null; + + if (params.isTrustStoreSet) { + tmf = TrustManagerFactory.getInstance(params.trustManagerType); + KeyStore ts = KeyStore.getInstance(params.trustStoreType); + in = getStoreAsStream(params.trustStore); + ts.load(in, + (params.trustPass != null ? params.trustPass.toCharArray() : null)); + tmf.init(ts); + } + + if (params.isKeyStoreSet) { + kmf = KeyManagerFactory.getInstance(params.keyManagerType); + KeyStore ks = KeyStore.getInstance(params.keyStoreType); + is = getStoreAsStream(params.keyStore); + ks.load(is, params.keyPass.toCharArray()); + kmf.init(ks, params.keyPass.toCharArray()); + } + + if (params.isKeyStoreSet && params.isTrustStoreSet) { + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } + else if (params.isKeyStoreSet) { + ctx.init(kmf.getKeyManagers(), null, null); + } + else { + ctx.init(null, tmf.getTrustManagers(), null); + } + + } catch (Exception e) { + throw new TTransportException("Error creating the transport", e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (is != null) { + try { + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + return ctx; + } + + private static InputStream getStoreAsStream(String store) throws IOException { + try { + return new FileInputStream(store); + } catch(FileNotFoundException e) { + } + + InputStream storeStream = null; + try { + storeStream = new URL(store).openStream(); + if (storeStream != null) { + return storeStream; + } + } catch(MalformedURLException e) { + } + + storeStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(store); + + if (storeStream != null) { + return storeStream; + } else { + throw new IOException("Could not load file: " + store); + } + } + + private static TSocket createClient(SSLSocketFactory factory, String host, int port, int timeout) throws TTransportException { + try { + SSLSocket socket = (SSLSocket) factory.createSocket(host, port); + socket.setSoTimeout(timeout); + return new TSocket(socket); + } catch (Exception e) { + throw new TTransportException("Could not connect to " + host + " on port " + port, e); + } + } + + + /** + * A Class to hold all the SSL parameters + */ + public static class TSSLTransportParameters { + protected String protocol = "TLS"; + protected String keyStore; + protected String keyPass; + protected String keyManagerType = KeyManagerFactory.getDefaultAlgorithm(); + protected String keyStoreType = "JKS"; + protected String trustStore; + protected String trustPass; + protected String trustManagerType = TrustManagerFactory.getDefaultAlgorithm(); + protected String trustStoreType = "JKS"; + protected String[] cipherSuites; + protected boolean clientAuth = false; + protected boolean isKeyStoreSet = false; + protected boolean isTrustStoreSet = false; + + public TSSLTransportParameters() {} + + /** + * Create parameters specifying the protocol and cipher suites + * + * @param protocol The specific protocol (TLS/SSL) can be specified with versions + * @param cipherSuites + */ + public TSSLTransportParameters(String protocol, String[] cipherSuites) { + this(protocol, cipherSuites, false); + } + + /** + * Create parameters specifying the protocol, cipher suites and if client authentication + * is required + * + * @param protocol The specific protocol (TLS/SSL) can be specified with versions + * @param cipherSuites + * @param clientAuth + */ + public TSSLTransportParameters(String protocol, String[] cipherSuites, boolean clientAuth) { + if (protocol != null) { + this.protocol = protocol; + } + this.cipherSuites = cipherSuites != null ? Arrays.copyOf(cipherSuites, cipherSuites.length) : null; + this.clientAuth = clientAuth; + } + + /** + * Set the keystore, password, certificate type and the store type + * + * @param keyStore Location of the Keystore on disk + * @param keyPass Keystore password + * @param keyManagerType The default is X509 + * @param keyStoreType The default is JKS + */ + public void setKeyStore(String keyStore, String keyPass, String keyManagerType, String keyStoreType) { + this.keyStore = keyStore; + this.keyPass = keyPass; + if (keyManagerType != null) { + this.keyManagerType = keyManagerType; + } + if (keyStoreType != null) { + this.keyStoreType = keyStoreType; + } + isKeyStoreSet = true; + } + + /** + * Set the keystore and password + * + * @param keyStore Location of the Keystore on disk + * @param keyPass Keystore password + */ + public void setKeyStore(String keyStore, String keyPass) { + setKeyStore(keyStore, keyPass, null, null); + } + + /** + * Set the truststore, password, certificate type and the store type + * + * @param trustStore Location of the Truststore on disk + * @param trustPass Truststore password + * @param trustManagerType The default is X509 + * @param trustStoreType The default is JKS + */ + public void setTrustStore(String trustStore, String trustPass, String trustManagerType, String trustStoreType) { + this.trustStore = trustStore; + this.trustPass = trustPass; + if (trustManagerType != null) { + this.trustManagerType = trustManagerType; + } + if (trustStoreType != null) { + this.trustStoreType = trustStoreType; + } + isTrustStoreSet = true; + } + + /** + * Set the truststore and password + * + * @param trustStore Location of the Truststore on disk + * @param trustPass Truststore password + */ + public void setTrustStore(String trustStore, String trustPass) { + setTrustStore(trustStore, trustPass, null, null); + } + + /** + * Set if client authentication is required + * + * @param clientAuth + */ + public void requireClientAuth(boolean clientAuth) { + this.clientAuth = clientAuth; + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslClientTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslClientTransport.java new file mode 100644 index 00000000..b862d55c --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslClientTransport.java @@ -0,0 +1,113 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.UnsupportedEncodingException; +import java.util.Map; + +import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Wraps another Thrift TTransport, but performs SASL client + * negotiation on the call to open(). This class will wrap ensuing + * communication over it, if a SASL QOP is negotiated with the other party. + */ +public class TSaslClientTransport extends TSaslTransport { + + private static final Logger LOGGER = LoggerFactory.getLogger(TSaslClientTransport.class); + + /** + * The name of the mechanism this client supports. + */ + private final String mechanism; + + /** + * Uses the given SaslClient. + * + * @param saslClient + * The SaslClient to use for the subsequent SASL + * negotiation. + * @param transport + * Transport underlying this one. + */ + public TSaslClientTransport(SaslClient saslClient, TTransport transport) { + super(saslClient, transport); + mechanism = saslClient.getMechanismName(); + } + + /** + * Creates a SaslClient using the given SASL-specific parameters. + * See the Java documentation for Sasl.createSaslClient for the + * details of the parameters. + * + * @param transport + * The underlying Thrift transport. + * @throws SaslException + */ + public TSaslClientTransport(String mechanism, String authorizationId, String protocol, + String serverName, Map props, CallbackHandler cbh, TTransport transport) + throws SaslException { + super(Sasl.createSaslClient(new String[] { mechanism }, authorizationId, protocol, serverName, + props, cbh), transport); + this.mechanism = mechanism; + } + + + @Override + protected SaslRole getRole() { + return SaslRole.CLIENT; + } + + /** + * Performs the client side of the initial portion of the Thrift SASL + * protocol. Generates and sends the initial response to the server, including + * which mechanism this client wants to use. + */ + @Override + protected void handleSaslStartMessage() throws TTransportException, SaslException { + SaslClient saslClient = getSaslClient(); + + byte[] initialResponse = new byte[0]; + if (saslClient.hasInitialResponse()) + initialResponse = saslClient.evaluateChallenge(initialResponse); + + LOGGER.debug("Sending mechanism name {} and initial response of length {}", mechanism, + initialResponse.length); + + byte[] mechanismBytes; + try { + mechanismBytes = mechanism.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new TTransportException(e); + } + sendSaslMessage(NegotiationStatus.START, + mechanismBytes); + // Send initial response + sendSaslMessage(saslClient.isComplete() ? NegotiationStatus.COMPLETE : NegotiationStatus.OK, + initialResponse); + underlyingTransport.flush(); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslServerTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslServerTransport.java new file mode 100644 index 00000000..77c3d67f --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslServerTransport.java @@ -0,0 +1,236 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.UnsupportedEncodingException; +import java.lang.ref.WeakReference; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.WeakHashMap; + +import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import com.xiaomi.infra.pegasus.thrift.TException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Wraps another Thrift TTransport, but performs SASL server + * negotiation on the call to open(). This class will wrap ensuing + * communication over it, if a SASL QOP is negotiated with the other party. + */ +public class TSaslServerTransport extends TSaslTransport { + + private static final Logger LOGGER = LoggerFactory.getLogger(TSaslServerTransport.class); + + /** + * Mapping from SASL mechanism name -> all the parameters required to + * instantiate a SASL server. + */ + private Map serverDefinitionMap = new HashMap(); + + /** + * Contains all the parameters used to define a SASL server implementation. + */ + private static class TSaslServerDefinition { + public String mechanism; + public String protocol; + public String serverName; + public Map props; + public CallbackHandler cbh; + + public TSaslServerDefinition(String mechanism, String protocol, String serverName, + Map props, CallbackHandler cbh) { + this.mechanism = mechanism; + this.protocol = protocol; + this.serverName = serverName; + this.props = props; + this.cbh = cbh; + } + } + + /** + * Uses the given underlying transport. Assumes that addServerDefinition is + * called later. + * + * @param transport + * Transport underlying this one. + */ + public TSaslServerTransport(TTransport transport) { + super(transport); + } + + /** + * Creates a SaslServer using the given SASL-specific parameters. + * See the Java documentation for Sasl.createSaslServer for the + * details of the parameters. + * + * @param transport + * The underlying Thrift transport. + */ + public TSaslServerTransport(String mechanism, String protocol, String serverName, + Map props, CallbackHandler cbh, TTransport transport) { + super(transport); + addServerDefinition(mechanism, protocol, serverName, props, cbh); + } + + private TSaslServerTransport(Map serverDefinitionMap, TTransport transport) { + super(transport); + this.serverDefinitionMap.putAll(serverDefinitionMap); + } + + /** + * Add a supported server definition to this transport. See the Java + * documentation for Sasl.createSaslServer for the details of the + * parameters. + */ + public void addServerDefinition(String mechanism, String protocol, String serverName, + Map props, CallbackHandler cbh) { + serverDefinitionMap.put(mechanism, new TSaslServerDefinition(mechanism, protocol, serverName, + props, cbh)); + } + + @Override + protected SaslRole getRole() { + return SaslRole.SERVER; + } + + /** + * Performs the server side of the initial portion of the Thrift SASL protocol. + * Receives the initial response from the client, creates a SASL server using + * the mechanism requested by the client (if this server supports it), and + * sends the first challenge back to the client. + */ + @Override + protected void handleSaslStartMessage() throws TTransportException, SaslException { + SaslResponse message = receiveSaslMessage(); + + LOGGER.debug("Received start message with status {}", message.status); + if (message.status != NegotiationStatus.START) { + throw sendAndThrowMessage(NegotiationStatus.ERROR, "Expecting START status, received " + message.status); + } + + // Get the mechanism name. + String mechanismName; + try { + mechanismName = new String(message.payload, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new TTransportException("JVM DOES NOT SUPPORT UTF-8"); + } + TSaslServerDefinition serverDefinition = serverDefinitionMap.get(mechanismName); + LOGGER.debug("Received mechanism name '{}'", mechanismName); + + if (serverDefinition == null) { + throw sendAndThrowMessage(NegotiationStatus.BAD, "Unsupported mechanism type " + mechanismName); + } + SaslServer saslServer = Sasl.createSaslServer(serverDefinition.mechanism, + serverDefinition.protocol, serverDefinition.serverName, serverDefinition.props, + serverDefinition.cbh); + setSaslServer(saslServer); + } + + /** + * TTransportFactory to create + * TSaslServerTransports. Ensures that a given + * underlying TTransport instance receives the same + * TSaslServerTransport. This is kind of an awful hack to work + * around the fact that Thrift is designed assuming that + * TTransport instances are stateless, and thus the existing + * TServers use different TTransport instances for + * input and output. + */ + public static class Factory extends TTransportFactory { + + /** + * This is the implementation of the awful hack described above. + * WeakHashMap is used to ensure that we don't leak memory. + */ + private static Map> transportMap = + Collections.synchronizedMap(new WeakHashMap>()); + + /** + * Mapping from SASL mechanism name -> all the parameters required to + * instantiate a SASL server. + */ + private Map serverDefinitionMap = new HashMap(); + + /** + * Create a new Factory. Assumes that addServerDefinition will + * be called later. + */ + public Factory() { + super(); + } + + /** + * Create a new Factory, initially with the single server + * definition given. You may still call addServerDefinition + * later. See the Java documentation for Sasl.createSaslServer + * for the details of the parameters. + */ + public Factory(String mechanism, String protocol, String serverName, + Map props, CallbackHandler cbh) { + super(); + addServerDefinition(mechanism, protocol, serverName, props, cbh); + } + + /** + * Add a supported server definition to the transports created by this + * factory. See the Java documentation for + * Sasl.createSaslServer for the details of the parameters. + */ + public void addServerDefinition(String mechanism, String protocol, String serverName, + Map props, CallbackHandler cbh) { + serverDefinitionMap.put(mechanism, new TSaslServerDefinition(mechanism, protocol, serverName, + props, cbh)); + } + + /** + * Get a new TSaslServerTransport instance, or reuse the + * existing one if a TSaslServerTransport has already been + * created before using the given TTransport as an underlying + * transport. This ensures that a given underlying transport instance + * receives the same TSaslServerTransport. + */ + @Override + public TTransport getTransport(TTransport base) { + WeakReference ret = transportMap.get(base); + if (ret == null || ret.get() == null) { + LOGGER.debug("transport map does not contain key", base); + ret = new WeakReference(new TSaslServerTransport(serverDefinitionMap, base)); + try { + ret.get().open(); + } catch (TTransportException e) { + LOGGER.debug("failed to open server transport", e); + throw new RuntimeException(e); + } + transportMap.put(base, ret); // No need for putIfAbsent(). + // Concurrent calls to getTransport() will pass in different TTransports. + } else { + LOGGER.debug("transport map does contain key {}", base); + } + return ret.get(); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslTransport.java new file mode 100644 index 00000000..ce1f675f --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslTransport.java @@ -0,0 +1,578 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Map; + +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import com.xiaomi.infra.pegasus.thrift.EncodingUtils; +import com.xiaomi.infra.pegasus.thrift.TByteArrayOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A superclass for SASL client/server thrift transports. A subclass need only + * implement the open method. + */ +abstract class TSaslTransport extends TTransport { + + private static final Logger LOGGER = LoggerFactory.getLogger(TSaslTransport.class); + + protected static final int DEFAULT_MAX_LENGTH = 0x7FFFFFFF; + + protected static final int MECHANISM_NAME_BYTES = 1; + protected static final int STATUS_BYTES = 1; + protected static final int PAYLOAD_LENGTH_BYTES = 4; + + protected static enum SaslRole { + SERVER, CLIENT; + } + + /** + * Status bytes used during the initial Thrift SASL handshake. + */ + protected static enum NegotiationStatus { + START((byte)0x01), + OK((byte)0x02), + BAD((byte)0x03), + ERROR((byte)0x04), + COMPLETE((byte)0x05); + + private final byte value; + + private static final Map reverseMap = + new HashMap(); + static { + for (NegotiationStatus s : NegotiationStatus.class.getEnumConstants()) { + reverseMap.put(s.getValue(), s); + } + } + + private NegotiationStatus(byte val) { + this.value = val; + } + + public byte getValue() { + return value; + } + + public static NegotiationStatus byValue(byte val) { + return reverseMap.get(val); + } + } + + /** + * Transport underlying this one. + */ + protected TTransport underlyingTransport; + + /** + * Either a SASL client or a SASL server. + */ + private SaslParticipant sasl; + + /** + * Whether or not we should wrap/unwrap reads/writes. Determined by whether or + * not a QOP is negotiated during the SASL handshake. + */ + private boolean shouldWrap = false; + + /** + * Buffer for input. + */ + private TMemoryInputTransport readBuffer = new TMemoryInputTransport(); + + /** + * Buffer for output. + */ + private final TByteArrayOutputStream writeBuffer = new TByteArrayOutputStream(1024); + + /** + * Create a TSaslTransport. It's assumed that setSaslServer will be called + * later to initialize the SASL endpoint underlying this transport. + * + * @param underlyingTransport + * The thrift transport which this transport is wrapping. + */ + protected TSaslTransport(TTransport underlyingTransport) { + this.underlyingTransport = underlyingTransport; + } + + /** + * Create a TSaslTransport which acts as a client. + * + * @param saslClient + * The SaslClient which this transport will use for SASL + * negotiation. + * @param underlyingTransport + * The thrift transport which this transport is wrapping. + */ + protected TSaslTransport(SaslClient saslClient, TTransport underlyingTransport) { + sasl = new SaslParticipant(saslClient); + this.underlyingTransport = underlyingTransport; + } + + protected void setSaslServer(SaslServer saslServer) { + sasl = new SaslParticipant(saslServer); + } + + // Used to read the status byte and payload length. + private final byte[] messageHeader = new byte[STATUS_BYTES + PAYLOAD_LENGTH_BYTES]; + + /** + * Send a complete Thrift SASL message. + * + * @param status + * The status to send. + * @param payload + * The data to send as the payload of this message. + * @throws TTransportException + */ + protected void sendSaslMessage(NegotiationStatus status, byte[] payload) throws TTransportException { + if (payload == null) + payload = new byte[0]; + + messageHeader[0] = status.getValue(); + EncodingUtils.encodeBigEndian(payload.length, messageHeader, STATUS_BYTES); + + if (LOGGER.isDebugEnabled()) + LOGGER.debug(getRole() + ": Writing message with status {} and payload length {}", + status, payload.length); + underlyingTransport.write(messageHeader); + underlyingTransport.write(payload); + underlyingTransport.flush(); + } + + /** + * Read a complete Thrift SASL message. + * + * @return The SASL status and payload from this message. + * @throws TTransportException + * Thrown if there is a failure reading from the underlying + * transport, or if a status code of BAD or ERROR is encountered. + */ + protected SaslResponse receiveSaslMessage() throws TTransportException { + underlyingTransport.readAll(messageHeader, 0, messageHeader.length); + + byte statusByte = messageHeader[0]; + + NegotiationStatus status = NegotiationStatus.byValue(statusByte); + if (status == null) { + throw sendAndThrowMessage(NegotiationStatus.ERROR, "Invalid status " + statusByte); + } + + int payloadBytes = EncodingUtils.decodeBigEndian(messageHeader, STATUS_BYTES); + if (payloadBytes < 0 || payloadBytes > 104857600 /* 100 MB */) { + throw sendAndThrowMessage( + NegotiationStatus.ERROR, "Invalid payload header length: " + payloadBytes); + } + + byte[] payload = new byte[payloadBytes]; + underlyingTransport.readAll(payload, 0, payload.length); + + if (status == NegotiationStatus.BAD || status == NegotiationStatus.ERROR) { + try { + String remoteMessage = new String(payload, "UTF-8"); + throw new TTransportException("Peer indicated failure: " + remoteMessage); + } catch (UnsupportedEncodingException e) { + throw new TTransportException(e); + } + } + + if (LOGGER.isDebugEnabled()) + LOGGER.debug(getRole() + ": Received message with status {} and payload length {}", + status, payload.length); + return new SaslResponse(status, payload); + } + + /** + * Send a Thrift SASL message with the given status (usually BAD or ERROR) and + * string message, and then throw a TTransportException with the given + * message. + * + * @param status + * The Thrift SASL status code to send. Usually BAD or ERROR. + * @param message + * The optional message to send to the other side. + * @throws TTransportException + * Always thrown with the message provided. + * @return always throws TTransportException but declares return type to allow + * throw sendAndThrowMessage(...) to inform compiler control flow + */ + protected TTransportException sendAndThrowMessage(NegotiationStatus status, String message) throws TTransportException { + try { + sendSaslMessage(status, message.getBytes("UTF-8")); + } catch (Exception e) { + LOGGER.warn("Could not send failure response", e); + message += "\nAlso, could not send response: " + e.toString(); + } + throw new TTransportException(message); + } + + /** + * Implemented by subclasses to start the Thrift SASL handshake process. When + * this method completes, the SaslParticipant in this class is + * assumed to be initialized. + * + * @throws TTransportException + * @throws SaslException + */ + abstract protected void handleSaslStartMessage() throws TTransportException, SaslException; + + protected abstract SaslRole getRole(); + + /** + * Opens the underlying transport if it's not already open and then performs + * SASL negotiation. If a QOP is negotiated during this SASL handshake, it used + * for all communication on this transport after this call is complete. + */ + @Override + public void open() throws TTransportException { + /* + * readSaslHeader is used to tag whether the SASL header has been read properly. + * If there is a problem in reading the header, there might not be any + * data in the stream, possibly a TCP health check from load balancer. + */ + boolean readSaslHeader = false; + + LOGGER.debug("opening transport {}", this); + if (sasl != null && sasl.isComplete()) + throw new TTransportException("SASL transport already open"); + + if (!underlyingTransport.isOpen()) + underlyingTransport.open(); + + try { + // Negotiate a SASL mechanism. The client also sends its + // initial response, or an empty one. + handleSaslStartMessage(); + readSaslHeader = true; + LOGGER.debug("{}: Start message handled", getRole()); + + SaslResponse message = null; + while (!sasl.isComplete()) { + message = receiveSaslMessage(); + if (message.status != NegotiationStatus.COMPLETE && + message.status != NegotiationStatus.OK) { + throw new TTransportException("Expected COMPLETE or OK, got " + message.status); + } + + byte[] challenge = sasl.evaluateChallengeOrResponse(message.payload); + + // If we are the client, and the server indicates COMPLETE, we don't need to + // send back any further response. + if (message.status == NegotiationStatus.COMPLETE && + getRole() == SaslRole.CLIENT) { + LOGGER.debug("{}: All done!", getRole()); + break; + } + + sendSaslMessage(sasl.isComplete() ? NegotiationStatus.COMPLETE : NegotiationStatus.OK, + challenge); + } + LOGGER.debug("{}: Main negotiation loop complete", getRole()); + + assert sasl.isComplete(); + + // If we're the client, and we're complete, but the server isn't + // complete yet, we need to wait for its response. This will occur + // with ANONYMOUS auth, for example, where we send an initial response + // and are immediately complete. + if (getRole() == SaslRole.CLIENT && + (message == null || message.status == NegotiationStatus.OK)) { + LOGGER.debug("{}: SASL Client receiving last message", getRole()); + message = receiveSaslMessage(); + if (message.status != NegotiationStatus.COMPLETE) { + throw new TTransportException( + "Expected SASL COMPLETE, but got " + message.status); + } + } + } catch (SaslException e) { + try { + LOGGER.error("SASL negotiation failure", e); + throw sendAndThrowMessage(NegotiationStatus.BAD, e.getMessage()); + } finally { + underlyingTransport.close(); + } + } catch (TTransportException e) { + /* + * If there is no-data or no-sasl header in the stream, throw a different + * type of exception so we can handle this scenario differently. + */ + if (!readSaslHeader && e.getType() == TTransportException.END_OF_FILE) { + underlyingTransport.close(); + LOGGER.debug("No data or no sasl data in the stream"); + throw new TSaslTransportException("No data or no sasl data in the stream"); + } + throw e; + } + + String qop = (String) sasl.getNegotiatedProperty(Sasl.QOP); + if (qop != null && !qop.equalsIgnoreCase("auth")) + shouldWrap = true; + } + + /** + * Get the underlying SaslClient. + * + * @return The SaslClient, or null if this transport + * is backed by a SaslServer. + */ + public SaslClient getSaslClient() { + return sasl.saslClient; + } + + /** + * Get the underlying transport that Sasl is using. + * @return The TTransport transport + */ + public TTransport getUnderlyingTransport() { + return underlyingTransport; + } + + /** + * Get the underlying SaslServer. + * + * @return The SaslServer, or null if this transport + * is backed by a SaslClient. + */ + public SaslServer getSaslServer() { + return sasl.saslServer; + } + + /** + * Read a 4-byte word from the underlying transport and interpret it as an + * integer. + * + * @return The length prefix of the next SASL message to read. + * @throws TTransportException + * Thrown if reading from the underlying transport fails. + */ + protected int readLength() throws TTransportException { + byte[] lenBuf = new byte[4]; + underlyingTransport.readAll(lenBuf, 0, lenBuf.length); + return EncodingUtils.decodeBigEndian(lenBuf); + } + + /** + * Write the given integer as 4 bytes to the underlying transport. + * + * @param length + * The length prefix of the next SASL message to write. + * @throws TTransportException + * Thrown if writing to the underlying transport fails. + */ + protected void writeLength(int length) throws TTransportException { + byte[] lenBuf = new byte[4]; + TFramedTransport.encodeFrameSize(length, lenBuf); + underlyingTransport.write(lenBuf); + } + + // Below is the SASL implementation of the TTransport interface. + + /** + * Closes the underlying transport and disposes of the SASL implementation + * underlying this transport. + */ + @Override + public void close() { + underlyingTransport.close(); + try { + sasl.dispose(); + } catch (SaslException e) { + // Not much we can do here. + } + } + + /** + * True if the underlying transport is open and the SASL handshake is + * complete. + */ + @Override + public boolean isOpen() { + return underlyingTransport.isOpen() && sasl != null && sasl.isComplete(); + } + + /** + * Read from the underlying transport. Unwraps the contents if a QOP was + * negotiated during the SASL handshake. + */ + @Override + public int read(byte[] buf, int off, int len) throws TTransportException { + if (!isOpen()) + throw new TTransportException("SASL authentication not complete"); + + int got = readBuffer.read(buf, off, len); + if (got > 0) { + return got; + } + + // Read another frame of data + try { + readFrame(); + } catch (SaslException e) { + throw new TTransportException(e); + } + + return readBuffer.read(buf, off, len); + } + + /** + * Read a single frame of data from the underlying transport, unwrapping if + * necessary. + * + * @throws TTransportException + * Thrown if there's an error reading from the underlying transport. + * @throws SaslException + * Thrown if there's an error unwrapping the data. + */ + private void readFrame() throws TTransportException, SaslException { + int dataLength = readLength(); + + if (dataLength < 0) + throw new TTransportException("Read a negative frame size (" + dataLength + ")!"); + + byte[] buff = new byte[dataLength]; + LOGGER.debug("{}: reading data length: {}", getRole(), dataLength); + underlyingTransport.readAll(buff, 0, dataLength); + if (shouldWrap) { + buff = sasl.unwrap(buff, 0, buff.length); + LOGGER.debug("data length after unwrap: {}", buff.length); + } + readBuffer.reset(buff); + } + + /** + * Write to the underlying transport. + */ + @Override + public void write(byte[] buf, int off, int len) throws TTransportException { + if (!isOpen()) + throw new TTransportException("SASL authentication not complete"); + + writeBuffer.write(buf, off, len); + } + + /** + * Flushes to the underlying transport. Wraps the contents if a QOP was + * negotiated during the SASL handshake. + */ + @Override + public void flush() throws TTransportException { + byte[] buf = writeBuffer.get(); + int dataLength = writeBuffer.len(); + writeBuffer.reset(); + + if (shouldWrap) { + LOGGER.debug("data length before wrap: {}", dataLength); + try { + buf = sasl.wrap(buf, 0, dataLength); + } catch (SaslException e) { + throw new TTransportException(e); + } + dataLength = buf.length; + } + LOGGER.debug("writing data length: {}", dataLength); + writeLength(dataLength); + underlyingTransport.write(buf, 0, dataLength); + underlyingTransport.flush(); + } + + /** + * Used exclusively by readSaslMessage to return both a status and data. + */ + protected static class SaslResponse { + public NegotiationStatus status; + public byte[] payload; + + public SaslResponse(NegotiationStatus status, byte[] payload) { + this.status = status; + this.payload = payload; + } + } + + /** + * Used to abstract over the SaslServer and + * SaslClient classes, which share a lot of their interface, but + * unfortunately don't share a common superclass. + */ + private static class SaslParticipant { + // One of these will always be null. + public SaslServer saslServer; + public SaslClient saslClient; + + public SaslParticipant(SaslServer saslServer) { + this.saslServer = saslServer; + } + + public SaslParticipant(SaslClient saslClient) { + this.saslClient = saslClient; + } + + public byte[] evaluateChallengeOrResponse(byte[] challengeOrResponse) throws SaslException { + if (saslClient != null) { + return saslClient.evaluateChallenge(challengeOrResponse); + } else { + return saslServer.evaluateResponse(challengeOrResponse); + } + } + + public boolean isComplete() { + if (saslClient != null) + return saslClient.isComplete(); + else + return saslServer.isComplete(); + } + + public void dispose() throws SaslException { + if (saslClient != null) + saslClient.dispose(); + else + saslServer.dispose(); + } + + public byte[] unwrap(byte[] buf, int off, int len) throws SaslException { + if (saslClient != null) + return saslClient.unwrap(buf, off, len); + else + return saslServer.unwrap(buf, off, len); + } + + public byte[] wrap(byte[] buf, int off, int len) throws SaslException { + if (saslClient != null) + return saslClient.wrap(buf, off, len); + else + return saslServer.wrap(buf, off, len); + } + + public Object getNegotiatedProperty(String propName) { + if (saslClient != null) + return saslClient.getNegotiatedProperty(propName); + else + return saslServer.getNegotiatedProperty(propName); + } + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslTransportException.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslTransportException.java new file mode 100644 index 00000000..14fdea93 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSaslTransportException.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.transport; + +/* + * This exception is used to track exceptions in TSaslTransport + * that does not have Sasl signature in their stream. + */ +public class TSaslTransportException extends TTransportException { + + public TSaslTransportException() { + super(); + } + + public TSaslTransportException(String message) { + super(message); + } + + public TSaslTransportException(Throwable cause) { + super(cause); + } + + public TSaslTransportException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSeekableFile.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSeekableFile.java new file mode 100644 index 00000000..e053b995 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSeekableFile.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; + +public interface TSeekableFile { + + public InputStream getInputStream() throws IOException; + public OutputStream getOutputStream() throws IOException; + public void close() throws IOException; + public long length() throws IOException; + public void seek(long pos) throws IOException; +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TServerSocket.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TServerSocket.java new file mode 100644 index 00000000..d9917199 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TServerSocket.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.transport; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; + +/** + * Wrapper around ServerSocket for Thrift. + * + */ +public class TServerSocket extends TServerTransport { + + private static final Logger LOGGER = LoggerFactory.getLogger(TServerSocket.class.getName()); + + /** + * Underlying ServerSocket object + */ + private ServerSocket serverSocket_ = null; + + /** + * Timeout for client sockets from accept + */ + private int clientTimeout_ = 0; + + public static class ServerSocketTransportArgs extends AbstractServerTransportArgs { + ServerSocket serverSocket; + + public ServerSocketTransportArgs serverSocket(ServerSocket serverSocket) { + this.serverSocket = serverSocket; + return this; + } + } + + /** + * Creates a server socket from underlying socket object + */ + public TServerSocket(ServerSocket serverSocket) throws TTransportException { + this(serverSocket, 0); + } + + /** + * Creates a server socket from underlying socket object + */ + public TServerSocket(ServerSocket serverSocket, int clientTimeout) throws TTransportException { + this(new ServerSocketTransportArgs().serverSocket(serverSocket).clientTimeout(clientTimeout)); + } + + /** + * Creates just a port listening server socket + */ + public TServerSocket(int port) throws TTransportException { + this(port, 0); + } + + /** + * Creates just a port listening server socket + */ + public TServerSocket(int port, int clientTimeout) throws TTransportException { + this(new InetSocketAddress(port), clientTimeout); + } + + public TServerSocket(InetSocketAddress bindAddr) throws TTransportException { + this(bindAddr, 0); + } + + public TServerSocket(InetSocketAddress bindAddr, int clientTimeout) throws TTransportException { + this(new ServerSocketTransportArgs().bindAddr(bindAddr).clientTimeout(clientTimeout)); + } + + public TServerSocket(ServerSocketTransportArgs args) throws TTransportException { + clientTimeout_ = args.clientTimeout; + if (args.serverSocket != null) { + this.serverSocket_ = args.serverSocket; + return; + } + try { + // Make server socket + serverSocket_ = new ServerSocket(); + // Prevent 2MSL delay problem on server restarts + serverSocket_.setReuseAddress(true); + // Bind to listening port + serverSocket_.bind(args.bindAddr, args.backlog); + } catch (IOException ioe) { + close(); + throw new TTransportException("Could not create ServerSocket on address " + args.bindAddr.toString() + ".", ioe); + } + } + + public void listen() throws TTransportException { + // Make sure to block on accept + if (serverSocket_ != null) { + try { + serverSocket_.setSoTimeout(0); + } catch (SocketException sx) { + LOGGER.error("Could not set socket timeout.", sx); + } + } + } + + protected TSocket acceptImpl() throws TTransportException { + if (serverSocket_ == null) { + throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket."); + } + try { + Socket result = serverSocket_.accept(); + TSocket result2 = new TSocket(result); + result2.setTimeout(clientTimeout_); + return result2; + } catch (IOException iox) { + throw new TTransportException(iox); + } + } + + public void close() { + if (serverSocket_ != null) { + try { + serverSocket_.close(); + } catch (IOException iox) { + LOGGER.warn("Could not close server socket.", iox); + } + serverSocket_ = null; + } + } + + public void interrupt() { + // The thread-safeness of this is dubious, but Java documentation suggests + // that it is safe to do this from a different thread context + close(); + } + + public ServerSocket getServerSocket() { + return serverSocket_; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TServerTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TServerTransport.java new file mode 100644 index 00000000..bdcb6de0 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TServerTransport.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.Closeable; +import java.net.InetSocketAddress; + +/** + * Server transport. Object which provides client transports. + * + */ +public abstract class TServerTransport implements Closeable { + + public static abstract class AbstractServerTransportArgs> { + int backlog = 0; // A value of 0 means the default value will be used (currently set at 50) + int clientTimeout = 0; + InetSocketAddress bindAddr; + + public T backlog(int backlog) { + this.backlog = backlog; + return (T) this; + } + + public T clientTimeout(int clientTimeout) { + this.clientTimeout = clientTimeout; + return (T) this; + } + + public T port(int port) { + this.bindAddr = new InetSocketAddress(port); + return (T) this; + } + + public T bindAddr(InetSocketAddress bindAddr) { + this.bindAddr = bindAddr; + return (T) this; + } + } + + public abstract void listen() throws TTransportException; + + public final TTransport accept() throws TTransportException { + TTransport transport = acceptImpl(); + if (transport == null) { + throw new TTransportException("accept() may not return NULL"); + } + return transport; + } + + public abstract void close(); + + protected abstract TTransport acceptImpl() throws TTransportException; + + /** + * Optional method implementation. This signals to the server transport + * that it should break out of any accept() or listen() that it is currently + * blocked on. This method, if implemented, MUST be thread safe, as it may + * be called from a different thread context than the other TServerTransport + * methods. + */ + public void interrupt() {} + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSimpleFileTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSimpleFileTransport.java new file mode 100644 index 00000000..39988d8a --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSimpleFileTransport.java @@ -0,0 +1,216 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.IOException; +import java.io.RandomAccessFile; + + +/** + * Basic file support for the TTransport interface + */ +public final class TSimpleFileTransport extends TTransport { + + private RandomAccessFile file = null; + private boolean readable; + private boolean writable; + private String path_; + + + /** + * Create a transport backed by a simple file + * + * @param path the path to the file to open/create + * @param read true to support read operations + * @param write true to support write operations + * @param openFile true to open the file on construction + * @throws TTransportException if file open fails + */ + public TSimpleFileTransport(String path, boolean read, + boolean write, boolean openFile) + throws TTransportException { + if (path.length() <= 0) { + throw new TTransportException("No path specified"); + } + if (!read && !write) { + throw new TTransportException("Neither READ nor WRITE specified"); + } + readable = read; + writable = write; + path_ = path; + if (openFile) { + open(); + } + } + + /** + * Create a transport backed by a simple file + * Implicitly opens file to conform to C++ behavior. + * + * @param path the path to the file to open/create + * @param read true to support read operations + * @param write true to support write operations + * @throws TTransportException if file open fails + */ + public TSimpleFileTransport(String path, boolean read, boolean write) + throws TTransportException { + this(path, read, write, true); + } + + /** + * Create a transport backed by a simple read only disk file (implicitly opens + * file) + * + * @param path the path to the file to open/create + * @throws TTransportException if file open fails + */ + public TSimpleFileTransport(String path) throws TTransportException { + this(path, true, false, true); + } + + /** + * Test file status + * + * @return true if open, otherwise false + */ + @Override + public boolean isOpen() { + return (file != null); + } + + /** + * Open file if not previously opened. + * + * @throws TTransportException if open fails + */ + @Override + public void open() throws TTransportException { + if (file == null){ + try { + String access = "r"; //RandomAccessFile objects must be readable + if (writable) { + access += "w"; + } + file = new RandomAccessFile(path_, access); + } catch (IOException ioe) { + file = null; + throw new TTransportException(ioe.getMessage()); + } + } + } + + /** + * Close file, subsequent read/write activity will throw exceptions + */ + @Override + public void close() { + if (file != null) { + try { + file.close(); + } catch (Exception e) { + //Nothing to do + } + file = null; + } + } + + /** + * Read up to len many bytes into buf at offset + * + * @param buf houses bytes read + * @param off offset into buff to begin writing to + * @param len maximum number of bytes to read + * @return number of bytes actually read + * @throws TTransportException on read failure + */ + @Override + public int read(byte[] buf, int off, int len) throws TTransportException { + if (!readable) { + throw new TTransportException("Read operation on write only file"); + } + int iBytesRead = 0; + try { + iBytesRead = file.read(buf, off, len); + } catch (IOException ioe) { + file = null; + throw new TTransportException(ioe.getMessage()); + } + return iBytesRead; + } + + /** + * Write len many bytes from buff starting at offset + * + * @param buf buffer containing bytes to write + * @param off offset into buffer to begin writing from + * @param len number of bytes to write + * @throws TTransportException on write failure + */ + @Override + public void write(byte[] buf, int off, int len) throws TTransportException { + try { + file.write(buf, off, len); + } catch (IOException ioe) { + file = null; + throw new TTransportException(ioe.getMessage()); + } + } + + /** + * Move file pointer to specified offset, new read/write calls will act here + * + * @param offset bytes from beginning of file to move pointer to + * @throws TTransportException is seek fails + */ + public void seek(long offset) throws TTransportException { + try { + file.seek(offset); + } catch (IOException ex) { + throw new TTransportException(ex.getMessage()); + } + } + + /** + * Return the length of the file in bytes + * + * @return length of the file in bytes + * @throws TTransportException if file access fails + */ + public long length() throws TTransportException { + try { + return file.length(); + } catch (IOException ex) { + throw new TTransportException(ex.getMessage()); + } + } + + /** + * Return current file pointer position in bytes from beginning of file + * + * @return file pointer position + * @throws TTransportException if file access fails + */ + public long getFilePointer() throws TTransportException { + try { + return file.getFilePointer(); + } catch (IOException ex) { + throw new TTransportException(ex.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSocket.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSocket.java new file mode 100644 index 00000000..b0f21fcb --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TSocket.java @@ -0,0 +1,248 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketException; + +/** + * Socket implementation of the TTransport interface. To be commented soon! + * + */ +public class TSocket extends TIOStreamTransport { + + private static final Logger LOGGER = LoggerFactory.getLogger(TSocket.class.getName()); + + /** + * Wrapped Socket object + */ + private Socket socket_; + + /** + * Remote host + */ + private String host_; + + /** + * Remote port + */ + private int port_; + + /** + * Socket timeout - read timeout on the socket + */ + private int socketTimeout_; + + /** + * Connection timeout + */ + private int connectTimeout_; + + /** + * Constructor that takes an already created socket. + * + * @param socket Already created socket object + * @throws TTransportException if there is an error setting up the streams + */ + public TSocket(Socket socket) throws TTransportException { + socket_ = socket; + try { + socket_.setSoLinger(false, 0); + socket_.setTcpNoDelay(true); + socket_.setKeepAlive(true); + } catch (SocketException sx) { + LOGGER.warn("Could not configure socket.", sx); + } + + if (isOpen()) { + try { + inputStream_ = new BufferedInputStream(socket_.getInputStream(), 1024); + outputStream_ = new BufferedOutputStream(socket_.getOutputStream(), 1024); + } catch (IOException iox) { + close(); + throw new TTransportException(TTransportException.NOT_OPEN, iox); + } + } + } + + /** + * Creates a new unconnected socket that will connect to the given host + * on the given port. + * + * @param host Remote host + * @param port Remote port + */ + public TSocket(String host, int port) { + this(host, port, 0); + } + + /** + * Creates a new unconnected socket that will connect to the given host + * on the given port. + * + * @param host Remote host + * @param port Remote port + * @param timeout Socket timeout and connection timeout + */ + public TSocket(String host, int port, int timeout) { + this(host, port, timeout, timeout); + } + + /** + * Creates a new unconnected socket that will connect to the given host + * on the given port, with a specific connection timeout and a + * specific socket timeout. + * + * @param host Remote host + * @param port Remote port + * @param socketTimeout Socket timeout + * @param connectTimeout Connection timeout + */ + public TSocket(String host, int port, int socketTimeout, int connectTimeout) { + host_ = host; + port_ = port; + socketTimeout_ = socketTimeout; + connectTimeout_ = connectTimeout; + initSocket(); + } + + /** + * Initializes the socket object + */ + private void initSocket() { + socket_ = new Socket(); + try { + socket_.setSoLinger(false, 0); + socket_.setTcpNoDelay(true); + socket_.setKeepAlive(true); + socket_.setSoTimeout(socketTimeout_); + } catch (SocketException sx) { + LOGGER.error("Could not configure socket.", sx); + } + } + + /** + * Sets the socket timeout and connection timeout. + * + * @param timeout Milliseconds timeout + */ + public void setTimeout(int timeout) { + this.setConnectTimeout(timeout); + this.setSocketTimeout(timeout); + } + + /** + * Sets the time after which the connection attempt will time out + * + * @param timeout Milliseconds timeout + */ + public void setConnectTimeout(int timeout) { + connectTimeout_ = timeout; + } + + /** + * Sets the socket timeout + * + * @param timeout Milliseconds timeout + */ + public void setSocketTimeout(int timeout) { + socketTimeout_ = timeout; + try { + socket_.setSoTimeout(timeout); + } catch (SocketException sx) { + LOGGER.warn("Could not set socket timeout.", sx); + } + } + + /** + * Returns a reference to the underlying socket. + */ + public Socket getSocket() { + if (socket_ == null) { + initSocket(); + } + return socket_; + } + + /** + * Checks whether the socket is connected. + */ + public boolean isOpen() { + if (socket_ == null) { + return false; + } + return socket_.isConnected(); + } + + /** + * Connects the socket, creating a new socket object if necessary. + */ + public void open() throws TTransportException { + if (isOpen()) { + throw new TTransportException(TTransportException.ALREADY_OPEN, "Socket already connected."); + } + + if (host_ == null || host_.length() == 0) { + throw new TTransportException(TTransportException.NOT_OPEN, "Cannot open null host."); + } + if (port_ <= 0 || port_ > 65535) { + throw new TTransportException(TTransportException.NOT_OPEN, "Invalid port " + port_); + } + + if (socket_ == null) { + initSocket(); + } + + try { + socket_.connect(new InetSocketAddress(host_, port_), connectTimeout_); + inputStream_ = new BufferedInputStream(socket_.getInputStream(), 1024); + outputStream_ = new BufferedOutputStream(socket_.getOutputStream(), 1024); + } catch (IOException iox) { + close(); + throw new TTransportException(TTransportException.NOT_OPEN, iox); + } + } + + /** + * Closes the socket. + */ + public void close() { + // Close the underlying streams + super.close(); + + // Close the socket + if (socket_ != null) { + try { + socket_.close(); + } catch (IOException iox) { + LOGGER.warn("Could not close socket.", iox); + } + socket_ = null; + } + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TStandardFile.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TStandardFile.java new file mode 100644 index 00000000..fc36d2ff --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TStandardFile.java @@ -0,0 +1,60 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +public class TStandardFile implements TSeekableFile { + + protected String path_ = null; + protected RandomAccessFile inputFile_ = null; + + public TStandardFile(String path) throws IOException { + path_ = path; + inputFile_ = new RandomAccessFile(path_, "r"); + } + + public InputStream getInputStream() throws IOException { + return new FileInputStream(inputFile_.getFD()); + } + + public OutputStream getOutputStream() throws IOException { + return new FileOutputStream(path_); + } + + public void close() throws IOException { + if(inputFile_ != null) { + inputFile_.close(); + } + } + + public long length() throws IOException { + return inputFile_.length(); + } + + public void seek(long pos) throws IOException { + inputFile_.seek(pos); + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransport.java new file mode 100644 index 00000000..5825a81e --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransport.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.Closeable; + +/** + * Generic class that encapsulates the I/O layer. This is basically a thin + * wrapper around the combined functionality of Java input/output streams. + * + */ +public abstract class TTransport implements Closeable { + + /** + * Queries whether the transport is open. + * + * @return True if the transport is open. + */ + public abstract boolean isOpen(); + + /** + * Is there more data to be read? + * + * @return True if the remote side is still alive and feeding us + */ + public boolean peek() { + return isOpen(); + } + + /** + * Opens the transport for reading/writing. + * + * @throws TTransportException if the transport could not be opened + */ + public abstract void open() + throws TTransportException; + + /** + * Closes the transport. + */ + public abstract void close(); + + /** + * Reads up to len bytes into buffer buf, starting at offset off. + * + * @param buf Array to read into + * @param off Index to start reading at + * @param len Maximum number of bytes to read + * @return The number of bytes actually read + * @throws TTransportException if there was an error reading data + */ + public abstract int read(byte[] buf, int off, int len) + throws TTransportException; + + /** + * Guarantees that all of len bytes are actually read off the transport. + * + * @param buf Array to read into + * @param off Index to start reading at + * @param len Maximum number of bytes to read + * @return The number of bytes actually read, which must be equal to len + * @throws TTransportException if there was an error reading data + */ + public int readAll(byte[] buf, int off, int len) + throws TTransportException { + int got = 0; + int ret = 0; + while (got < len) { + ret = read(buf, off+got, len-got); + if (ret <= 0) { + throw new TTransportException( + "Cannot read. Remote side has closed. Tried to read " + + len + + " bytes, but only got " + + got + + " bytes. (This is often indicative of an internal error on the server side. Please check your server logs.)"); + } + got += ret; + } + return got; + } + + /** + * Writes the buffer to the output + * + * @param buf The output data buffer + * @throws TTransportException if an error occurs writing data + */ + public void write(byte[] buf) throws TTransportException { + write(buf, 0, buf.length); + } + + /** + * Writes up to len bytes from the buffer. + * + * @param buf The output data buffer + * @param off The offset to start writing from + * @param len The number of bytes to write + * @throws TTransportException if there was an error writing data + */ + public abstract void write(byte[] buf, int off, int len) + throws TTransportException; + + /** + * Flush any pending data out of a transport buffer. + * + * @throws TTransportException if there was an error writing out data. + */ + public void flush() + throws TTransportException {} + + /** + * Access the protocol's underlying buffer directly. If this is not a + * buffered transport, return null. + * @return protocol's Underlying buffer + */ + public byte[] getBuffer() { + return null; + } + + /** + * Return the index within the underlying buffer that specifies the next spot + * that should be read from. + * @return index within the underlying buffer that specifies the next spot + * that should be read from + */ + public int getBufferPosition() { + return 0; + } + + /** + * Get the number of bytes remaining in the underlying buffer. Returns -1 if + * this is a non-buffered transport. + * @return the number of bytes remaining in the underlying buffer.
Returns -1 if + * this is a non-buffered transport. + */ + public int getBytesRemainingInBuffer() { + return -1; + } + + /** + * Consume len bytes from the underlying buffer. + * @param len + */ + public void consumeBuffer(int len) {} +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransportException.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransportException.java new file mode 100644 index 00000000..64976761 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransportException.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.transport; + +import com.xiaomi.infra.pegasus.thrift.TException; + +/** + * Transport exceptions. + * + */ +public class TTransportException extends TException { + + private static final long serialVersionUID = 1L; + + public static final int UNKNOWN = 0; + public static final int NOT_OPEN = 1; + public static final int ALREADY_OPEN = 2; + public static final int TIMED_OUT = 3; + public static final int END_OF_FILE = 4; + public static final int CORRUPTED_DATA = 5; + + protected int type_ = UNKNOWN; + + public TTransportException() { + super(); + } + + public TTransportException(int type) { + super(); + type_ = type; + } + + public TTransportException(int type, String message) { + super(message); + type_ = type; + } + + public TTransportException(String message) { + super(message); + } + + public TTransportException(int type, Throwable cause) { + super(cause); + type_ = type; + } + + public TTransportException(Throwable cause) { + super(cause); + } + + public TTransportException(String message, Throwable cause) { + super(message, cause); + } + + public TTransportException(int type, String message, Throwable cause) { + super(message, cause); + type_ = type; + } + + public int getType() { + return type_; + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransportFactory.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransportFactory.java new file mode 100644 index 00000000..aac2a7f8 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TTransportFactory.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.xiaomi.infra.pegasus.thrift.transport; + +/** + * Factory class used to create wrapped instance of Transports. + * This is used primarily in servers, which get Transports from + * a ServerTransport and then may want to mutate them (i.e. create + * a BufferedTransport from the underlying base transport) + * + */ +public class TTransportFactory { + + /** + * Return a wrapped instance of the base Transport. + * + * @param trans The base transport + * @return Wrapped Transport + */ + public TTransport getTransport(TTransport trans) { + return trans; + } + +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TZlibTransport.java b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TZlibTransport.java new file mode 100644 index 00000000..c5d54b29 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/thrift/transport/TZlibTransport.java @@ -0,0 +1,148 @@ +/* + * 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 com.xiaomi.infra.pegasus.thrift.transport; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.Inflater; +import java.util.zip.InflaterInputStream; + +/** + * TZlibTransport deflates on write and inflates on read. + */ +public class TZlibTransport extends TIOStreamTransport { + + private TTransport transport_ = null; + + public static class Factory extends TTransportFactory { + public Factory() { + } + + @Override + public TTransport getTransport(TTransport base) { + return new TZlibTransport(base); + } + } + + /** + * Constructs a new TZlibTransport instance. + * @param transport the underlying transport to read from and write to + */ + public TZlibTransport(TTransport transport) { + this(transport, Deflater.BEST_COMPRESSION); + } + + /** + * Constructs a new TZlibTransport instance. + * @param transport the underlying transport to read from and write to + * @param compressionLevel 0 for no compression, 9 for maximum compression + */ + public TZlibTransport(TTransport transport, int compressionLevel) { + transport_ = transport; + inputStream_ = new InflaterInputStream(new TTransportInputStream(transport_), new Inflater()); + outputStream_ = new DeflaterOutputStream(new TTransportOutputStream(transport_), new Deflater(compressionLevel, false), true); + } + + @Override + public boolean isOpen() { + return transport_.isOpen(); + } + + @Override + public void open() throws TTransportException { + transport_.open(); + } + + @Override + public void close() { + super.close(); + if (transport_.isOpen()) { + transport_.close(); + } + } +} + +class TTransportInputStream extends InputStream { + + private TTransport transport = null; + + public TTransportInputStream(TTransport transport) { + this.transport = transport; + } + + @Override + public int read() throws IOException { + try { + byte[] buf = new byte[1]; + transport.read(buf, 0, 1); + return buf[0]; + } catch (TTransportException e) { + throw new IOException(e); + } + } + + @Override + public int read(byte b[], int off, int len) throws IOException { + try { + return transport.read(b, off, len); + } catch (TTransportException e) { + throw new IOException(e); + } + } +} + +class TTransportOutputStream extends OutputStream { + + private TTransport transport = null; + + public TTransportOutputStream(TTransport transport) { + this.transport = transport; + } + + @Override + public void write(final int b) throws IOException { + try { + transport.write(new byte[]{(byte) b}); + } catch (TTransportException e) { + throw new IOException(e); + } + } + + @Override + public void write(byte b[], int off, int len) throws IOException { + try { + transport.write(b, off, len); + } catch (TTransportException e) { + throw new IOException(e); + } + } + + @Override + public void flush() throws IOException { + try { + transport.flush(); + } catch (TTransportException e) { + throw new IOException(e); + } + } +} + diff --git a/src/main/java/com/xiaomi/infra/pegasus/tools/FlowController.java b/src/main/java/com/xiaomi/infra/pegasus/tools/FlowController.java new file mode 100644 index 00000000..4d46627a --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/tools/FlowController.java @@ -0,0 +1,91 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.tools; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * A tool class to support simple flow control. + * + * Usage: + * + * FlowController cntl = new FlowController(qps); + * while (true) { + * // call getToken before operation + * cntl.getToken(); + * client.set(...); + * } + * cntl.stop(); + * + */ +public class FlowController { + + private final int qps; + private int[] slots; + private int next; + private AtomicInteger token; + private boolean stopped; + + /** + * @param qps_ QPS to control. should > 0. + */ + public FlowController(int qps_) { + this.qps = qps_; + this.slots = new int[10]; + int base = qps / 10; + for (int i = 0; i < 10; i++) { + slots[i] = base; + } + int remain = qps % 10; + for (int i = 0; i < 10 && remain > 0; i++) { + slots[i]++; + remain--; + } + this.next = 1; + this.token = new AtomicInteger(slots[0]); + this.stopped = false; + new Thread(new Runnable() { + @Override + public void run() { + while (!stopped) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + synchronized (token) { + token.set(slots[next]); + token.notifyAll(); + } + next++; + if (next >= 10) + next = 0; + } + } + }).start(); + } + + /** + * Call getToken() to do flow control when send request. + * The method will block for some time if QPS limit is reached to control the flow. + */ + public void getToken() { + int t = token.decrementAndGet(); + while (!stopped && t < 0) { + synchronized (token) { + try { + token.wait(100); + } catch (InterruptedException e) { + } + } + t = token.decrementAndGet(); + } + } + + /** + * Should call stop after use done. + */ + public void stop() { + this.stopped = true; + } +} diff --git a/src/main/java/com/xiaomi/infra/pegasus/tools/tools.java b/src/main/java/com/xiaomi/infra/pegasus/tools/tools.java new file mode 100644 index 00000000..25c9c9d1 --- /dev/null +++ b/src/main/java/com/xiaomi/infra/pegasus/tools/tools.java @@ -0,0 +1,169 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.tools; + +import org.slf4j.Logger; + +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Collections; +import java.util.Date; +import java.util.Iterator; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class tools { + private static class dsn_crc { + public static final long crc64_poly = 0x9a6c9329ac4bc9b5l; + public static final int crc32_poly = 0x82f63b78; + public static final int crc32_table[] = new int[0x100]; + public static final long crc64_table[] = new long[0x100]; + + static { + for (int i = 0; i < 256; ++i) { + int k1 = i; + long k2 = (long) i; + for (int j = 0; j < 8; ++j) { + if ((k1 & 1) == 1) + k1 = (k1 >>> 1) ^ crc32_poly; + else + k1 = (k1 >>> 1); + + if ((k2 & 1) == 1) + k2 = (k2 >>> 1) ^ crc64_poly; + else + k2 = (k2 >>> 1); + } + crc32_table[i] = k1; + crc64_table[i] = k2; + } + } + } + + public static void sleepFor(long ms) { + long startTime = System.currentTimeMillis(); + long elapse; + while (ms > 0) { + try { + Thread.sleep(ms); + break; + } catch (InterruptedException e) { + elapse = System.currentTimeMillis() - startTime; + ms -= elapse; + startTime += elapse; + } + } + } + + public static void waitForever(Object obj) { + try { + obj.wait(); + } catch (InterruptedException e) { + } + } + + public static long waitFor(Object obj, long millseconds) + { + long current = System.currentTimeMillis(); + try { + obj.wait(millseconds); + } catch (InterruptedException e) { + } + return System.currentTimeMillis() - current; + } + + public static void notify(Object obj) { + synchronized (obj) { + obj.notify(); + } + } + + public static T waitUninterruptable(FutureTask task, long millseconds) throws ExecutionException { + long current = System.currentTimeMillis(); + while (millseconds >= 0) { + try { + T result = task.get(millseconds, TimeUnit.MILLISECONDS); + return result; + } catch (InterruptedException e) { + long t = System.currentTimeMillis(); + millseconds -= (t-current); + current = t; + } catch (TimeoutException e) { + return null; + } + } + return null; + } + + public static int dsn_crc32(byte[] array) { + return dsn_crc32(array, 0, array.length); + } + + public static int dsn_crc32(byte[] array, int offset, int length) { + int crc = -1; + int end = offset + length; + for (int i = offset; i < end; ++i) + crc = dsn_crc.crc32_table[(array[i] ^ crc) & 0xFF] ^ (crc >>> 8); + return ~crc; + } + + public static long dsn_crc64(byte[] array) { + return dsn_crc64(array, 0, array.length); + } + + public static long dsn_crc64(byte[] array, int offset, int length) { + long crc = -1; + int end = offset + length; + for (int i = offset; i < end; ++i) + crc = dsn_crc.crc64_table[(array[i] ^ (int) crc) & 0xFF] ^ (crc >>> 8); + return ~crc; + } + + public static int dsn_gpid_to_thread_hash(int app_id, int partition_index) + { + return app_id*7919 + partition_index; + } + + private final static long epoch_begin = 1451606400; // seconds since 2016.01.01-00:00:00 GMT + public static long epoch_now() { + Date d = new Date(); + return d.getTime() / 1000 - epoch_begin; + } + + public static long unixEpochMills() { + Date d = new Date(); + return d.getTime(); + } + + public static InetAddress getLocalHostAddress() { + try { + Iterator e = Collections.list(NetworkInterface.getNetworkInterfaces()).iterator(); + + while(e.hasNext()) { + NetworkInterface iface = (NetworkInterface)e.next(); + Iterator var2 = Collections.list(iface.getInetAddresses()).iterator(); + + while(var2.hasNext()) { + InetAddress addr = (InetAddress)var2.next(); + logger.debug("Checking ip address {}", addr); + // 172.17.42.1 is docker address + if(addr.isSiteLocalAddress() && !addr.isLoopbackAddress() && !(addr instanceof Inet6Address) + && !(addr.getHostAddress().equals("172.17.42.1"))) { + logger.debug("Ok, the ip {} will be used.", addr); + return addr; + } + } + } + } catch (SocketException var5) { + logger.error("Couldn\'t find the local machine ip.", var5); + } + throw new IllegalStateException("Couldn\'t find the local machine ip."); + } + + private static final Logger logger = org.slf4j.LoggerFactory.getLogger(tools.class); +} diff --git a/src/test/java/com/xiaomi/infra/pegasus/client/TestBasic.java b/src/test/java/com/xiaomi/infra/pegasus/client/TestBasic.java new file mode 100644 index 00000000..f54de201 --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/client/TestBasic.java @@ -0,0 +1,1326 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +/** + * @author qinzuoyan + */ + +import io.netty.util.concurrent.Future; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by mi on 16-3-22. + */ +public class TestBasic { + private static final String basicSetGetDelHashKey = "TestBasic_testSetGetDel_hash_key_1"; + private static final String multiSetGetDelHashKey = "TestBasic_testMultiSetGetDel_hash_key_1"; + private static final String multiGetHashKey = "TestBasic_testMultiGet_hash_key_1"; + + private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); + public static String bytesToHex(byte[] bytes) { + char[] hexChars = new char[bytes.length * 2]; + for ( int j = 0; j < bytes.length; j++ ) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = hexArray[v >>> 4]; + hexChars[j * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); + } + + @Test + public void testGenerateKey() throws PException { + Assert.assertEquals("00010A0BFEFF", + bytesToHex(new byte[]{0x00, 0x01, 0x0A, 0x0B, (byte)0xFE, (byte)0xFF})); + + Assert.assertArrayEquals(new byte[]{0x00, 0x00}, + PegasusClient.generateKey(new byte[]{}, new byte[]{})); + Assert.assertArrayEquals(new byte[]{0x00, 0x01, 0x44}, + PegasusClient.generateKey(new byte[]{0x44}, new byte[]{})); + Assert.assertArrayEquals(new byte[]{0x00, 0x00, 0x55}, + PegasusClient.generateKey(new byte[]{}, new byte[]{0x55})); + Assert.assertArrayEquals(new byte[]{0x00, 0x01, 0x44, 0x55}, + PegasusClient.generateKey(new byte[]{0x44}, new byte[]{0x55})); + try { + byte[] k = PegasusClient.generateKey(new byte[64 * 1024], new byte[]{0x55}); + Assert.assertTrue(false); + } + catch (Exception e) { + } + + Assert.assertArrayEquals(new byte[]{0x00, 0x01}, + PegasusClient.generateNextBytes(new byte[]{})); + Assert.assertArrayEquals(new byte[]{0x00, 0x01, 0x0B}, + PegasusClient.generateNextBytes(new byte[]{0x0A})); + Assert.assertArrayEquals(new byte[]{0x00, 0x01, (byte)0xFF}, + PegasusClient.generateNextBytes(new byte[]{(byte)0xFE})); + Assert.assertArrayEquals(new byte[]{0x00, 0x02}, + PegasusClient.generateNextBytes(new byte[]{(byte)0xFF})); + Assert.assertArrayEquals(new byte[]{0x00, 0x02, 0x0B}, + PegasusClient.generateNextBytes(new byte[]{0x0A, (byte)0xFF})); + Assert.assertArrayEquals(new byte[]{0x00, 0x03}, + PegasusClient.generateNextBytes(new byte[]{(byte)0xFF, (byte)0xFF})); + try { + byte[] k = PegasusClient.generateNextBytes(new byte[64 * 1024]); + Assert.assertTrue(false); + } + catch (Exception e) { + } + + Assert.assertArrayEquals(new byte[]{0x00, 0x01}, + PegasusClient.generateNextBytes(new byte[]{}, new byte[]{})); + Assert.assertArrayEquals(new byte[]{0x00, 0x01, 0x45}, + PegasusClient.generateNextBytes(new byte[]{0x44}, new byte[]{})); + Assert.assertArrayEquals(new byte[]{0x00, 0x00, 0x56}, + PegasusClient.generateNextBytes(new byte[]{}, new byte[]{0x55})); + Assert.assertArrayEquals(new byte[]{0x00, 0x01, 0x44, 0x56}, + PegasusClient.generateNextBytes(new byte[]{0x44}, new byte[]{0x55})); + Assert.assertArrayEquals(new byte[]{0x00, 0x01, 0x45}, + PegasusClient.generateNextBytes(new byte[]{0x44}, new byte[]{(byte)0xFF})); + Assert.assertArrayEquals(new byte[]{0x00, 0x02}, + PegasusClient.generateNextBytes(new byte[]{(byte)0xFF}, new byte[]{})); + Assert.assertArrayEquals(new byte[]{0x00, 0x01, (byte)0xFF, 0x56}, + PegasusClient.generateNextBytes(new byte[]{(byte)0xFF}, new byte[]{0x55})); + Assert.assertArrayEquals(new byte[]{0x00, 0x02}, + PegasusClient.generateNextBytes(new byte[]{(byte)0xFF}, new byte[]{(byte)0xFF})); + Assert.assertArrayEquals(new byte[]{0x00, 0x02}, + PegasusClient.generateNextBytes(new byte[]{(byte)0xFF}, new byte[]{(byte)0xFF, (byte)0xFF})); + Assert.assertArrayEquals(new byte[]{0x00, 0x03}, + PegasusClient.generateNextBytes(new byte[]{(byte)0xFF, (byte)0xFF}, new byte[]{(byte)0xFF})); + try { + byte[] k = PegasusClient.generateNextBytes(new byte[64 * 1024], new byte[0]); + Assert.assertTrue(false); + } + catch (Exception e) { + } + } + + @Test + public void testGetSingletonClient() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + PegasusClientInterface client1 = PegasusClientFactory.getSingletonClient(); + Assert.assertEquals(client, client1); + try { + PegasusClientInterface client2 = PegasusClientFactory.getSingletonClient("resource:///xxx.properties"); + Assert.assertTrue(false); + } + catch (PException e) { + } + PegasusClientFactory.closeSingletonClient(); + } + + @Test + public void testSetGetDel() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + byte[] hashKey = basicSetGetDelHashKey.getBytes(); + + try { + // set + client.set(tableName, hashKey, "basic_test_sort_key_1".getBytes(), "basic_test_value_1".getBytes()); + + // check exist + boolean exist = client.exist(tableName, hashKey, "basic_test_sort_key_1".getBytes()); + Assert.assertTrue(exist); + + exist = client.exist(tableName, hashKey, "basic_test_sort_key_2".getBytes()); + Assert.assertFalse(exist); + + // check sortkey count + long sortKeyCount = client.sortKeyCount(tableName, hashKey); + Assert.assertEquals(1, sortKeyCount); + + // get + byte[] value = client.get(tableName, hashKey, "basic_test_sort_key_1".getBytes()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), value); + + value = client.get(tableName, hashKey, "basic_test_sort_key_2".getBytes()); + Assert.assertEquals(null, value); + + // del + client.del(tableName, hashKey, "basic_test_sort_key_1".getBytes()); + + // check exist + exist = client.exist(tableName, hashKey, "basic_test_sort_key_1".getBytes()); + Assert.assertFalse(exist); + + // check sortkey count + sortKeyCount = client.sortKeyCount(tableName, hashKey); + Assert.assertEquals(0, sortKeyCount); + + // check deleted + value = client.get(tableName, hashKey, "basic_test_sort_key_1".getBytes()); + Assert.assertEquals(null, value); + } + catch (PException e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + + PegasusClientFactory.closeSingletonClient(); + } + + @Test + public void testMultiSetGetDel() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + byte[] hashKey = multiSetGetDelHashKey.getBytes(); + + try { + // multi set + List> values = new ArrayList>(); + values.add(Pair.of("basic_test_sort_key_1".getBytes(), "basic_test_value_1".getBytes())); + values.add(Pair.of("basic_test_sort_key_2".getBytes(), "basic_test_value_2".getBytes())); + values.add(Pair.of("basic_test_sort_key_3".getBytes(), "basic_test_value_3".getBytes())); + values.add(Pair.of("basic_test_sort_key_4".getBytes(), "basic_test_value_4".getBytes())); + client.multiSet(tableName, hashKey, values); + + // check exist + boolean exist = client.exist(tableName, hashKey, "basic_test_sort_key_1".getBytes()); + Assert.assertTrue(exist); + + exist = client.exist(tableName, hashKey, "basic_test_sort_key_5".getBytes()); + Assert.assertFalse(exist); + + // check sortkey count + long sortKeyCount = client.sortKeyCount(tableName, hashKey); + Assert.assertEquals(4, sortKeyCount); + + // multi get + List sortKeys = new ArrayList(); + sortKeys.add("basic_test_sort_key_0".getBytes()); + sortKeys.add("basic_test_sort_key_1".getBytes()); + sortKeys.add("basic_test_sort_key_2".getBytes()); + sortKeys.add("basic_test_sort_key_3".getBytes()); + sortKeys.add("basic_test_sort_key_4".getBytes()); + List> newValues = new ArrayList>(); + boolean ret = client.multiGet(tableName, hashKey, sortKeys, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(4, newValues.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), newValues.get(0).getValue()); + Assert.assertArrayEquals("basic_test_sort_key_2".getBytes(), newValues.get(1).getKey()); + Assert.assertArrayEquals("basic_test_value_2".getBytes(), newValues.get(1).getValue()); + Assert.assertArrayEquals("basic_test_sort_key_3".getBytes(), newValues.get(2).getKey()); + Assert.assertArrayEquals("basic_test_value_3".getBytes(), newValues.get(2).getValue()); + Assert.assertArrayEquals("basic_test_sort_key_4".getBytes(), newValues.get(3).getKey()); + Assert.assertArrayEquals("basic_test_value_4".getBytes(), newValues.get(3).getValue()); + + // multi get with count limit + newValues.clear(); + ret = client.multiGet(tableName, hashKey, sortKeys, 1, 0, newValues); + Assert.assertFalse(ret); + Assert.assertEquals(1, newValues.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), newValues.get(0).getValue()); + + // multi get with empty sortKeys + sortKeys.clear(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, sortKeys, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(4, newValues.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), newValues.get(0).getValue()); + Assert.assertArrayEquals("basic_test_sort_key_2".getBytes(), newValues.get(1).getKey()); + Assert.assertArrayEquals("basic_test_value_2".getBytes(), newValues.get(1).getValue()); + Assert.assertArrayEquals("basic_test_sort_key_3".getBytes(), newValues.get(2).getKey()); + Assert.assertArrayEquals("basic_test_value_3".getBytes(), newValues.get(2).getValue()); + Assert.assertArrayEquals("basic_test_sort_key_4".getBytes(), newValues.get(3).getKey()); + Assert.assertArrayEquals("basic_test_value_4".getBytes(), newValues.get(3).getValue()); + + // multi get with null sortKeys + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(4, newValues.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), newValues.get(0).getValue()); + Assert.assertArrayEquals("basic_test_sort_key_2".getBytes(), newValues.get(1).getKey()); + Assert.assertArrayEquals("basic_test_value_2".getBytes(), newValues.get(1).getValue()); + Assert.assertArrayEquals("basic_test_sort_key_3".getBytes(), newValues.get(2).getKey()); + Assert.assertArrayEquals("basic_test_value_3".getBytes(), newValues.get(2).getValue()); + Assert.assertArrayEquals("basic_test_sort_key_4".getBytes(), newValues.get(3).getKey()); + Assert.assertArrayEquals("basic_test_value_4".getBytes(), newValues.get(3).getValue()); + + // multi get sort keys + sortKeys.clear(); + ret = client.multiGetSortKeys(tableName, hashKey, sortKeys); + Assert.assertTrue(ret); + Assert.assertEquals(4, sortKeys.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), sortKeys.get(0)); + Assert.assertArrayEquals("basic_test_sort_key_2".getBytes(), sortKeys.get(1)); + Assert.assertArrayEquals("basic_test_sort_key_3".getBytes(), sortKeys.get(2)); + Assert.assertArrayEquals("basic_test_sort_key_4".getBytes(), sortKeys.get(3)); + + // multi del + sortKeys.clear(); + sortKeys.add("basic_test_sort_key_0".getBytes()); + sortKeys.add("basic_test_sort_key_1".getBytes()); + sortKeys.add("basic_test_sort_key_2".getBytes()); + client.multiDel(tableName, hashKey, sortKeys); + + // check sortkey count + sortKeyCount = client.sortKeyCount(tableName, hashKey); + Assert.assertEquals(2, sortKeyCount); + + // check deleted + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(2, newValues.size()); + Assert.assertArrayEquals("basic_test_sort_key_3".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("basic_test_value_3".getBytes(), newValues.get(0).getValue()); + Assert.assertArrayEquals("basic_test_sort_key_4".getBytes(), newValues.get(1).getKey()); + Assert.assertArrayEquals("basic_test_value_4".getBytes(), newValues.get(1).getValue()); + + // multi del all + sortKeys.clear(); + sortKeys.add("basic_test_sort_key_3".getBytes()); + sortKeys.add("basic_test_sort_key_4".getBytes()); + sortKeys.add("basic_test_sort_key_5".getBytes()); + client.multiDel(tableName, hashKey, sortKeys); + + // check sortkey count + sortKeyCount = client.sortKeyCount(tableName, hashKey); + Assert.assertEquals(0, sortKeyCount); + + // check deleted by multiGet + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // check deleted by multiGetSortKeys + sortKeys.clear(); + ret = client.multiGetSortKeys(tableName, hashKey, sortKeys); + Assert.assertTrue(ret); + Assert.assertEquals(0, sortKeys.size()); + + // multi set many kvs + values.clear(); + for (int i = 1; i <= 200; i++) + { + String sortKey = "basic_test_sort_key_" + String.format("%03d", i); + String value = "basic_test_value_" + String.valueOf(i); + values.add(Pair.of(sortKey.getBytes(), value.getBytes())); + } + client.multiSet(tableName, hashKey, values); + + // multi get with no limit + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, 0, 0, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(200, newValues.size()); + for (int i = 1; i <= 200; i++) + { + String sortKey = "basic_test_sort_key_" + String.format("%03d", i); + String value = "basic_test_value_" + String.valueOf(i); + Assert.assertArrayEquals(sortKey.getBytes(), newValues.get(i - 1).getKey()); + Assert.assertArrayEquals(value.getBytes(), newValues.get(i - 1).getValue()); + } + + // multi del all + sortKeys.clear(); + for (int i = 1; i <= 200; i++) + { + String sortKey = "basic_test_sort_key_" + String.format("%03d", i); + Assert.assertArrayEquals(sortKey.getBytes(), newValues.get(i - 1).getKey()); + sortKeys.add(sortKey.getBytes()); + } + client.multiDel(tableName, hashKey, sortKeys); + + // check sortkey count + sortKeyCount = client.sortKeyCount(tableName, hashKey); + Assert.assertEquals(0, sortKeyCount); + } + catch (PException e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + + PegasusClientFactory.closeSingletonClient(); + } + + @Test + public void testMultiGet() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + byte[] hashKey = multiGetHashKey.getBytes(); + + try { + // multi set + List> values = new ArrayList>(); + values.add(Pair.of("".getBytes(), "0".getBytes())); + values.add(Pair.of("1".getBytes(), "1".getBytes())); + values.add(Pair.of("1-abcdefg".getBytes(), "1-abcdefg".getBytes())); + values.add(Pair.of("2".getBytes(), "2".getBytes())); + values.add(Pair.of("2-abcdefg".getBytes(), "2-abcdefg".getBytes())); + values.add(Pair.of("3".getBytes(), "3".getBytes())); + values.add(Pair.of("3-efghijk".getBytes(), "3-efghijk".getBytes())); + values.add(Pair.of("4".getBytes(), "4".getBytes())); + values.add(Pair.of("4-hijklmn".getBytes(), "4-hijklmn".getBytes())); + values.add(Pair.of("5".getBytes(), "5".getBytes())); + values.add(Pair.of("5-hijklmn".getBytes(), "5-hijklmn".getBytes())); + values.add(Pair.of("6".getBytes(), "6".getBytes())); + values.add(Pair.of("7".getBytes(), "7".getBytes())); + client.multiSet(tableName, hashKey, values); + + // check sortkey count + long sortKeyCount = client.sortKeyCount(tableName, hashKey); + Assert.assertEquals(13, sortKeyCount); + + // [null, null) + MultiGetOptions options = new MultiGetOptions(); + Assert.assertTrue(options.startInclusive); + Assert.assertFalse(options.stopInclusive); + List> newValues = new ArrayList>(); + boolean ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(13, newValues.size()); + Assert.assertArrayEquals("".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(1).getKey()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(2).getKey()); + Assert.assertArrayEquals("2".getBytes(), newValues.get(3).getKey()); + Assert.assertArrayEquals("2-abcdefg".getBytes(), newValues.get(4).getKey()); + Assert.assertArrayEquals("3".getBytes(), newValues.get(5).getKey()); + Assert.assertArrayEquals("3-efghijk".getBytes(), newValues.get(6).getKey()); + Assert.assertArrayEquals("4".getBytes(), newValues.get(7).getKey()); + Assert.assertArrayEquals("4-hijklmn".getBytes(), newValues.get(8).getKey()); + Assert.assertArrayEquals("5".getBytes(), newValues.get(9).getKey()); + Assert.assertArrayEquals("5-hijklmn".getBytes(), newValues.get(10).getKey()); + Assert.assertArrayEquals("6".getBytes(), newValues.get(11).getKey()); + Assert.assertArrayEquals("7".getBytes(), newValues.get(12).getKey()); + + // [null, null] + options = new MultiGetOptions(); + options.startInclusive = true; + options.stopInclusive = true; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(13, newValues.size()); + Assert.assertArrayEquals("".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(1).getKey()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(2).getKey()); + Assert.assertArrayEquals("2".getBytes(), newValues.get(3).getKey()); + Assert.assertArrayEquals("2-abcdefg".getBytes(), newValues.get(4).getKey()); + Assert.assertArrayEquals("3".getBytes(), newValues.get(5).getKey()); + Assert.assertArrayEquals("3-efghijk".getBytes(), newValues.get(6).getKey()); + Assert.assertArrayEquals("4".getBytes(), newValues.get(7).getKey()); + Assert.assertArrayEquals("4-hijklmn".getBytes(), newValues.get(8).getKey()); + Assert.assertArrayEquals("5".getBytes(), newValues.get(9).getKey()); + Assert.assertArrayEquals("5-hijklmn".getBytes(), newValues.get(10).getKey()); + Assert.assertArrayEquals("6".getBytes(), newValues.get(11).getKey()); + Assert.assertArrayEquals("7".getBytes(), newValues.get(12).getKey()); + + // (null, null) + options = new MultiGetOptions(); + options.startInclusive = false; + options.stopInclusive = false; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(12, newValues.size()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(1).getKey()); + Assert.assertArrayEquals("2".getBytes(), newValues.get(2).getKey()); + Assert.assertArrayEquals("2-abcdefg".getBytes(), newValues.get(3).getKey()); + Assert.assertArrayEquals("3".getBytes(), newValues.get(4).getKey()); + Assert.assertArrayEquals("3-efghijk".getBytes(), newValues.get(5).getKey()); + Assert.assertArrayEquals("4".getBytes(), newValues.get(6).getKey()); + Assert.assertArrayEquals("4-hijklmn".getBytes(), newValues.get(7).getKey()); + Assert.assertArrayEquals("5".getBytes(), newValues.get(8).getKey()); + Assert.assertArrayEquals("5-hijklmn".getBytes(), newValues.get(9).getKey()); + Assert.assertArrayEquals("6".getBytes(), newValues.get(10).getKey()); + Assert.assertArrayEquals("7".getBytes(), newValues.get(11).getKey()); + + // (null, null] + options = new MultiGetOptions(); + options.startInclusive = false; + options.stopInclusive = true; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(12, newValues.size()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(1).getKey()); + Assert.assertArrayEquals("2".getBytes(), newValues.get(2).getKey()); + Assert.assertArrayEquals("2-abcdefg".getBytes(), newValues.get(3).getKey()); + Assert.assertArrayEquals("3".getBytes(), newValues.get(4).getKey()); + Assert.assertArrayEquals("3-efghijk".getBytes(), newValues.get(5).getKey()); + Assert.assertArrayEquals("4".getBytes(), newValues.get(6).getKey()); + Assert.assertArrayEquals("4-hijklmn".getBytes(), newValues.get(7).getKey()); + Assert.assertArrayEquals("5".getBytes(), newValues.get(8).getKey()); + Assert.assertArrayEquals("5-hijklmn".getBytes(), newValues.get(9).getKey()); + Assert.assertArrayEquals("6".getBytes(), newValues.get(10).getKey()); + Assert.assertArrayEquals("7".getBytes(), newValues.get(11).getKey()); + + // [null, 1] + options = new MultiGetOptions(); + options.startInclusive = true; + options.stopInclusive = true; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, "1".getBytes(), options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(2, newValues.size()); + Assert.assertArrayEquals("".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(1).getKey()); + + // [null, 1) + options = new MultiGetOptions(); + options.startInclusive = true; + options.stopInclusive = false; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, "1".getBytes(), options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(1, newValues.size()); + Assert.assertArrayEquals("".getBytes(), newValues.get(0).getKey()); + + // (null, 1] + options = new MultiGetOptions(); + options.startInclusive = false; + options.stopInclusive = true; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, "1".getBytes(), options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(1, newValues.size()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(0).getKey()); + + // (null, 1) + options = new MultiGetOptions(); + options.startInclusive = false; + options.stopInclusive = false; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, "1".getBytes(), options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // [1, 1] + options = new MultiGetOptions(); + options.startInclusive = true; + options.stopInclusive = true; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, "1".getBytes(), "1".getBytes(), options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(1, newValues.size()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(0).getKey()); + + // [1, 1) + options = new MultiGetOptions(); + options.startInclusive = true; + options.stopInclusive = false; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, "1".getBytes(), "1".getBytes(), options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // (1, 1] + options = new MultiGetOptions(); + options.startInclusive = false; + options.stopInclusive = true; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, "1".getBytes(), "1".getBytes(), options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // (1, 1) + options = new MultiGetOptions(); + options.startInclusive = false; + options.stopInclusive = false; + newValues.clear(); + ret = client.multiGet(tableName, hashKey, "1".getBytes(), "1".getBytes(), options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // match-anywhere("-") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_ANYWHERE; + options.sortKeyFilterPattern = "-".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(5, newValues.size()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("2-abcdefg".getBytes(), newValues.get(1).getKey()); + Assert.assertArrayEquals("3-efghijk".getBytes(), newValues.get(2).getKey()); + Assert.assertArrayEquals("4-hijklmn".getBytes(), newValues.get(3).getKey()); + Assert.assertArrayEquals("5-hijklmn".getBytes(), newValues.get(4).getKey()); + + // match-anywhere("1") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_ANYWHERE; + options.sortKeyFilterPattern = "1".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(2, newValues.size()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(1).getKey()); + + // match-anywhere("1-") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_ANYWHERE; + options.sortKeyFilterPattern = "1-".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(1, newValues.size()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(0).getKey()); + + // match-anywhere("abc") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_ANYWHERE; + options.sortKeyFilterPattern = "abc".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(2, newValues.size()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("2-abcdefg".getBytes(), newValues.get(1).getKey()); + + // match-prefix("1") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_PREFIX; + options.sortKeyFilterPattern = "1".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(2, newValues.size()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(1).getKey()); + + // match-prefix("1-") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_PREFIX; + options.sortKeyFilterPattern = "1-".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(1, newValues.size()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(0).getKey()); + + // match-prefix("1-x") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_PREFIX; + options.sortKeyFilterPattern = "1-x".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // match-prefix("abc") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_PREFIX; + options.sortKeyFilterPattern = "abc".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // match-prefix("efg") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_PREFIX; + options.sortKeyFilterPattern = "efg".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // match-prefix("ijk") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_PREFIX; + options.sortKeyFilterPattern = "ijk".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // match-prefix("lnm") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_PREFIX; + options.sortKeyFilterPattern = "lmn".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // match-postfix("5-hijklmn") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_PREFIX; + options.sortKeyFilterPattern = "5-hijklmn".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(1, newValues.size()); + Assert.assertArrayEquals("5-hijklmn".getBytes(), newValues.get(0).getKey()); + + // match-postfix("1") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_POSTFIX; + options.sortKeyFilterPattern = "1".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(1, newValues.size()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(0).getKey()); + + // match-postfix("1-") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_POSTFIX; + options.sortKeyFilterPattern = "1-".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // match-postfix("1-x") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_POSTFIX; + options.sortKeyFilterPattern = "1-x".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // match-postfix("abc") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_POSTFIX; + options.sortKeyFilterPattern = "abc".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(0, newValues.size()); + + // match-postfix("efg") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_POSTFIX; + options.sortKeyFilterPattern = "efg".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(2, newValues.size()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("2-abcdefg".getBytes(), newValues.get(1).getKey()); + + // match-postfix("ijk") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_POSTFIX; + options.sortKeyFilterPattern = "ijk".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(1, newValues.size()); + Assert.assertArrayEquals("3-efghijk".getBytes(), newValues.get(0).getKey()); + + // match-postfix("lmn") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_POSTFIX; + options.sortKeyFilterPattern = "lmn".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(2, newValues.size()); + Assert.assertArrayEquals("4-hijklmn".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("5-hijklmn".getBytes(), newValues.get(1).getKey()); + + // match-postfix("5-hijklmn") + options = new MultiGetOptions(); + options.sortKeyFilterType = FilterType.FT_MATCH_POSTFIX; + options.sortKeyFilterPattern = "5-hijklmn".getBytes(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, newValues); + Assert.assertTrue(ret); + Assert.assertEquals(1, newValues.size()); + Assert.assertArrayEquals("5-hijklmn".getBytes(), newValues.get(0).getKey()); + + // maxCount = 4 + options = new MultiGetOptions(); + newValues.clear(); + ret = client.multiGet(tableName, hashKey, null, null, options, 4, -1, newValues); + Assert.assertFalse(ret); + Assert.assertEquals(4, newValues.size()); + Assert.assertArrayEquals("".getBytes(), newValues.get(0).getKey()); + Assert.assertArrayEquals("1".getBytes(), newValues.get(1).getKey()); + Assert.assertArrayEquals("1-abcdefg".getBytes(), newValues.get(2).getKey()); + Assert.assertArrayEquals("2".getBytes(), newValues.get(3).getKey()); + + // multi del all + List sortKeys = new ArrayList(); + sortKeys.add("".getBytes()); + sortKeys.add("1".getBytes()); + sortKeys.add("1-abcdefg".getBytes()); + sortKeys.add("2".getBytes()); + sortKeys.add("2-abcdefg".getBytes()); + sortKeys.add("3".getBytes()); + sortKeys.add("3-efghijk".getBytes()); + sortKeys.add("4".getBytes()); + sortKeys.add("4-hijklmn".getBytes()); + sortKeys.add("5".getBytes()); + sortKeys.add("5-hijklmn".getBytes()); + sortKeys.add("6".getBytes()); + sortKeys.add("7".getBytes()); + client.multiDel(tableName, hashKey, sortKeys); + + // check sortkey count + sortKeyCount = client.sortKeyCount(tableName, hashKey); + Assert.assertEquals(0, sortKeyCount); + } + catch (PException e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + + PegasusClientFactory.closeSingletonClient(); + } + + @Test + public void testBatchSetGetDel() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + + try { + // batch set + List items = new ArrayList(); + items.add(new SetItem("TestBasic_testBatchSetGetDel_hash_key_1".getBytes(), + "basic_test_sort_key".getBytes(), "basic_test_value_1".getBytes())); + items.add(new SetItem("TestBasic_testBatchSetGetDel_hash_key_2".getBytes(), + "basic_test_sort_key".getBytes(), "basic_test_value_2".getBytes())); + items.add(new SetItem("TestBasic_testBatchSetGetDel_hash_key_3".getBytes(), + "basic_test_sort_key".getBytes(), "basic_test_value_3".getBytes())); + client.batchSet(tableName, items); + + // check exist + boolean exist = client.exist(tableName, + "TestBasic_testBatchSetGetDel_hash_key_1".getBytes(), + "basic_test_sort_key".getBytes()); + Assert.assertTrue(exist); + exist = client.exist(tableName, + "TestBasic_testBatchSetGetDel_hash_key_2".getBytes(), + "basic_test_sort_key".getBytes()); + Assert.assertTrue(exist); + exist = client.exist(tableName, + "TestBasic_testBatchSetGetDel_hash_key_3".getBytes(), + "basic_test_sort_key".getBytes()); + Assert.assertTrue(exist); + + // batch get + List> keys = new ArrayList>(); + keys.add(Pair.of("TestBasic_testBatchSetGetDel_hash_key_1".getBytes(), + "basic_test_sort_key".getBytes())); + keys.add(Pair.of("TestBasic_testBatchSetGetDel_hash_key_2".getBytes(), + "basic_test_sort_key".getBytes())); + keys.add(Pair.of("TestBasic_testBatchSetGetDel_hash_key_3".getBytes(), + "basic_test_sort_key".getBytes())); + List values = new ArrayList(); + client.batchGet(tableName, keys, values); + Assert.assertEquals(3, values.size()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), values.get(0)); + Assert.assertArrayEquals("basic_test_value_2".getBytes(), values.get(1)); + Assert.assertArrayEquals("basic_test_value_3".getBytes(), values.get(2)); + + // batch del + client.batchDel(tableName, keys); + + // check deleted + client.batchGet(tableName, keys, values); + Assert.assertEquals(3, values.size()); + Assert.assertNull(values.get(0)); + Assert.assertNull(values.get(1)); + Assert.assertNull(values.get(2)); + } + catch (PException e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + + PegasusClientFactory.closeSingletonClient(); + } + + @Test + public void testBatchSetGetDel2() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + + try { + // batch set + List items = new ArrayList(); + items.add(new SetItem("TestBasic_testBatchSetGetDel2_hash_key_1".getBytes(), + "basic_test_sort_key".getBytes(), "basic_test_value_1".getBytes())); + items.add(new SetItem("TestBasic_testBatchSetGetDel2_hash_key_2".getBytes(), + "basic_test_sort_key".getBytes(), "basic_test_value_2".getBytes())); + items.add(new SetItem("TestBasic_testBatchSetGetDel2_hash_key_3".getBytes(), + "basic_test_sort_key".getBytes(), "basic_test_value_3".getBytes())); + List resultsBatchSet = new ArrayList(); + int count = client.batchSet2(tableName, items, resultsBatchSet); + Assert.assertEquals(3, count); + Assert.assertEquals(3, resultsBatchSet.size()); + Assert.assertNull(resultsBatchSet.get(0)); + Assert.assertNull(resultsBatchSet.get(1)); + Assert.assertNull(resultsBatchSet.get(2)); + + // check exist + boolean exist = client.exist(tableName, + "TestBasic_testBatchSetGetDel2_hash_key_1".getBytes(), + "basic_test_sort_key".getBytes()); + Assert.assertTrue(exist); + exist = client.exist(tableName, + "TestBasic_testBatchSetGetDel2_hash_key_2".getBytes(), + "basic_test_sort_key".getBytes()); + Assert.assertTrue(exist); + exist = client.exist(tableName, + "TestBasic_testBatchSetGetDel2_hash_key_3".getBytes(), + "basic_test_sort_key".getBytes()); + Assert.assertTrue(exist); + + // batch get + List> keys = new ArrayList>(); + keys.add(Pair.of("TestBasic_testBatchSetGetDel2_hash_key_1".getBytes(), + "basic_test_sort_key".getBytes())); + keys.add(Pair.of("TestBasic_testBatchSetGetDel2_hash_key_2".getBytes(), + "basic_test_sort_key".getBytes())); + keys.add(Pair.of("TestBasic_testBatchSetGetDel2_hash_key_3".getBytes(), + "basic_test_sort_key".getBytes())); + List> resultsBatchGet = new ArrayList>(); + count = client.batchGet2(tableName, keys, resultsBatchGet); + Assert.assertEquals(3, count); + Assert.assertEquals(3, resultsBatchGet.size()); + Assert.assertNull(resultsBatchGet.get(0).getLeft()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), resultsBatchGet.get(0).getRight()); + Assert.assertNull(resultsBatchGet.get(1).getLeft()); + Assert.assertArrayEquals("basic_test_value_2".getBytes(), resultsBatchGet.get(1).getRight()); + Assert.assertNull(resultsBatchGet.get(2).getLeft()); + Assert.assertArrayEquals("basic_test_value_3".getBytes(), resultsBatchGet.get(2).getRight()); + + // batch del + List resultsBatchDel = new ArrayList(); + count = client.batchDel2(tableName, keys, resultsBatchDel); + Assert.assertEquals(3, count); + Assert.assertEquals(3, resultsBatchSet.size()); + Assert.assertNull(resultsBatchSet.get(0)); + Assert.assertNull(resultsBatchSet.get(1)); + Assert.assertNull(resultsBatchSet.get(2)); + + // check deleted + List values = new ArrayList(); + client.batchGet(tableName, keys, values); + Assert.assertEquals(3, values.size()); + Assert.assertNull(values.get(0)); + Assert.assertNull(values.get(1)); + Assert.assertNull(values.get(2)); + } + catch (PException e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + + PegasusClientFactory.closeSingletonClient(); + } + + @Test + public void testBatchMultiSetGetDel() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + + try { + // batch multi set + List items = new ArrayList(); + items.add(new HashKeyData("TestBasic_testBatchMultiSetGetDel_hash_key_1".getBytes())); + items.get(items.size()-1).addData("basic_test_sort_key_1".getBytes(), "basic_test_value_1".getBytes()); + items.get(items.size()-1).addData("basic_test_sort_key_2".getBytes(), "basic_test_value_2".getBytes()); + items.get(items.size()-1).addData("basic_test_sort_key_3".getBytes(), "basic_test_value_3".getBytes()); + items.add(new HashKeyData("TestBasic_testBatchMultiSetGetDel_hash_key_2".getBytes())); + items.get(items.size()-1).addData("basic_test_sort_key_1".getBytes(), "basic_test_value_1".getBytes()); + items.get(items.size()-1).addData("basic_test_sort_key_2".getBytes(), "basic_test_value_2".getBytes()); + items.add(new HashKeyData("TestBasic_testBatchMultiSetGetDel_hash_key_3".getBytes())); + items.get(items.size()-1).addData("basic_test_sort_key_1".getBytes(), "basic_test_value_1".getBytes()); + client.batchMultiSet(tableName, items); + + // batch multi get + List>> keys = new ArrayList>>(); + List nullSortKeys = null; + keys.add(Pair.of("TestBasic_testBatchMultiSetGetDel_hash_key_1".getBytes(), nullSortKeys)); + keys.add(Pair.of("TestBasic_testBatchMultiSetGetDel_hash_key_2".getBytes(), nullSortKeys)); + keys.add(Pair.of("TestBasic_testBatchMultiSetGetDel_hash_key_3".getBytes(), nullSortKeys)); + keys.add(Pair.of("TestBasic_testBatchMultiSetGetDel_hash_key_4".getBytes(), nullSortKeys)); + List values = new ArrayList(); + client.batchMultiGet(tableName, keys, values); + Assert.assertEquals(4, values.size()); + + Assert.assertArrayEquals(keys.get(0).getLeft(), values.get(0).hashKey); + Assert.assertEquals(3, values.get(0).values.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), values.get(0).values.get(0).getLeft()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), values.get(0).values.get(0).getRight()); + Assert.assertArrayEquals("basic_test_sort_key_2".getBytes(), values.get(0).values.get(1).getLeft()); + Assert.assertArrayEquals("basic_test_value_2".getBytes(), values.get(0).values.get(1).getRight()); + Assert.assertArrayEquals("basic_test_sort_key_3".getBytes(), values.get(0).values.get(2).getLeft()); + Assert.assertArrayEquals("basic_test_value_3".getBytes(), values.get(0).values.get(2).getRight()); + + Assert.assertArrayEquals(keys.get(1).getLeft(), values.get(1).hashKey); + Assert.assertEquals(2, values.get(1).values.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), values.get(1).values.get(0).getLeft()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), values.get(1).values.get(0).getRight()); + Assert.assertArrayEquals("basic_test_sort_key_2".getBytes(), values.get(1).values.get(1).getLeft()); + Assert.assertArrayEquals("basic_test_value_2".getBytes(), values.get(1).values.get(1).getRight()); + + Assert.assertArrayEquals(keys.get(2).getLeft(), values.get(2).hashKey); + Assert.assertEquals(1, values.get(2).values.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), values.get(2).values.get(0).getLeft()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), values.get(2).values.get(0).getRight()); + + Assert.assertArrayEquals(keys.get(3).getLeft(), values.get(3).hashKey); + Assert.assertEquals(0, values.get(3).values.size()); + + // batch multi del + List>> delKeys = new ArrayList>>(); + List delSortKeys = new ArrayList(); + delSortKeys.add("basic_test_sort_key_1".getBytes()); + delSortKeys.add("basic_test_sort_key_2".getBytes()); + delSortKeys.add("basic_test_sort_key_3".getBytes()); + delSortKeys.add("basic_test_sort_key_4".getBytes()); + delKeys.add(Pair.of("TestBasic_testBatchMultiSetGetDel_hash_key_1".getBytes(), delSortKeys)); + delKeys.add(Pair.of("TestBasic_testBatchMultiSetGetDel_hash_key_2".getBytes(), delSortKeys)); + delKeys.add(Pair.of("TestBasic_testBatchMultiSetGetDel_hash_key_3".getBytes(), delSortKeys)); + client.batchMultiDel(tableName, delKeys); + + // check deleted + client.batchMultiGet(tableName, keys, values); + Assert.assertEquals(4, values.size()); + Assert.assertEquals(0, values.get(0).values.size()); + Assert.assertEquals(0, values.get(1).values.size()); + Assert.assertEquals(0, values.get(2).values.size()); + Assert.assertEquals(0, values.get(3).values.size()); + } + catch (PException e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + + PegasusClientFactory.closeSingletonClient(); + } + + @Test + public void testBatchMultiSetGetDel2() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + + try { + // batch multi set + List items = new ArrayList(); + items.add(new HashKeyData("TestBasic_testBatchMultiSetGetDel2_hash_key_1".getBytes())); + items.get(items.size()-1).addData("basic_test_sort_key_1".getBytes(), "basic_test_value_1".getBytes()); + items.get(items.size()-1).addData("basic_test_sort_key_2".getBytes(), "basic_test_value_2".getBytes()); + items.get(items.size()-1).addData("basic_test_sort_key_3".getBytes(), "basic_test_value_3".getBytes()); + items.add(new HashKeyData("TestBasic_testBatchMultiSetGetDel2_hash_key_2".getBytes())); + items.get(items.size()-1).addData("basic_test_sort_key_1".getBytes(), "basic_test_value_1".getBytes()); + items.get(items.size()-1).addData("basic_test_sort_key_2".getBytes(), "basic_test_value_2".getBytes()); + items.add(new HashKeyData("TestBasic_testBatchMultiSetGetDel2_hash_key_3".getBytes())); + items.get(items.size()-1).addData("basic_test_sort_key_1".getBytes(), "basic_test_value_1".getBytes()); + List resultsBatchMultiSet = new ArrayList(); + int count = client.batchMultiSet2(tableName, items, resultsBatchMultiSet); + Assert.assertEquals(3, count); + Assert.assertEquals(3, resultsBatchMultiSet.size()); + Assert.assertNull(resultsBatchMultiSet.get(0)); + Assert.assertNull(resultsBatchMultiSet.get(1)); + Assert.assertNull(resultsBatchMultiSet.get(2)); + + // batch multi get + List>> keys = new ArrayList>>(); + List nullSortKeys = null; + keys.add(Pair.of("TestBasic_testBatchMultiSetGetDel2_hash_key_1".getBytes(), nullSortKeys)); + keys.add(Pair.of("TestBasic_testBatchMultiSetGetDel2_hash_key_2".getBytes(), nullSortKeys)); + keys.add(Pair.of("TestBasic_testBatchMultiSetGetDel2_hash_key_3".getBytes(), nullSortKeys)); + keys.add(Pair.of("TestBasic_testBatchMultiSetGetDel2_hash_key_4".getBytes(), nullSortKeys)); + List> resultsBatchMultiGet = new ArrayList>(); + count = client.batchMultiGet2(tableName, keys, resultsBatchMultiGet); + Assert.assertEquals(4, count); + Assert.assertEquals(4, resultsBatchMultiGet.size()); + + Assert.assertNull(resultsBatchMultiGet.get(0).getLeft()); + Assert.assertArrayEquals(keys.get(0).getLeft(), resultsBatchMultiGet.get(0).getRight().hashKey); + Assert.assertEquals(3, resultsBatchMultiGet.get(0).getRight().values.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), resultsBatchMultiGet.get(0).getRight().values.get(0).getLeft()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), resultsBatchMultiGet.get(0).getRight().values.get(0).getRight()); + Assert.assertArrayEquals("basic_test_sort_key_2".getBytes(), resultsBatchMultiGet.get(0).getRight().values.get(1).getLeft()); + Assert.assertArrayEquals("basic_test_value_2".getBytes(), resultsBatchMultiGet.get(0).getRight().values.get(1).getRight()); + Assert.assertArrayEquals("basic_test_sort_key_3".getBytes(), resultsBatchMultiGet.get(0).getRight().values.get(2).getLeft()); + Assert.assertArrayEquals("basic_test_value_3".getBytes(), resultsBatchMultiGet.get(0).getRight().values.get(2).getRight()); + + Assert.assertNull(resultsBatchMultiGet.get(1).getLeft()); + Assert.assertArrayEquals(keys.get(1).getLeft(), resultsBatchMultiGet.get(1).getRight().hashKey); + Assert.assertEquals(2, resultsBatchMultiGet.get(1).getRight().values.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), resultsBatchMultiGet.get(1).getRight().values.get(0).getLeft()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), resultsBatchMultiGet.get(1).getRight().values.get(0).getRight()); + Assert.assertArrayEquals("basic_test_sort_key_2".getBytes(), resultsBatchMultiGet.get(1).getRight().values.get(1).getLeft()); + Assert.assertArrayEquals("basic_test_value_2".getBytes(), resultsBatchMultiGet.get(1).getRight().values.get(1).getRight()); + + Assert.assertNull(resultsBatchMultiGet.get(2).getLeft()); + Assert.assertArrayEquals(keys.get(2).getLeft(), resultsBatchMultiGet.get(2).getRight().hashKey); + Assert.assertEquals(1, resultsBatchMultiGet.get(2).getRight().values.size()); + Assert.assertArrayEquals("basic_test_sort_key_1".getBytes(), resultsBatchMultiGet.get(2).getRight().values.get(0).getLeft()); + Assert.assertArrayEquals("basic_test_value_1".getBytes(), resultsBatchMultiGet.get(2).getRight().values.get(0).getRight()); + + Assert.assertNull(resultsBatchMultiGet.get(3).getLeft()); + Assert.assertArrayEquals(keys.get(3).getLeft(),resultsBatchMultiGet.get(3).getRight().hashKey); + Assert.assertEquals(0, resultsBatchMultiGet.get(3).getRight().values.size()); + + // batch multi del + List>> delKeys = new ArrayList>>(); + List delSortKeys = new ArrayList(); + delSortKeys.add("basic_test_sort_key_1".getBytes()); + delSortKeys.add("basic_test_sort_key_2".getBytes()); + delSortKeys.add("basic_test_sort_key_3".getBytes()); + delSortKeys.add("basic_test_sort_key_4".getBytes()); + delKeys.add(Pair.of("TestBasic_testBatchMultiSetGetDel2_hash_key_1".getBytes(), delSortKeys)); + delKeys.add(Pair.of("TestBasic_testBatchMultiSetGetDel2_hash_key_2".getBytes(), delSortKeys)); + delKeys.add(Pair.of("TestBasic_testBatchMultiSetGetDel2_hash_key_3".getBytes(), delSortKeys)); + List resultsBatchMultiDel = new ArrayList(); + count = client.batchMultiDel2(tableName, delKeys, resultsBatchMultiDel); + Assert.assertEquals(3, count); + Assert.assertEquals(3, resultsBatchMultiSet.size()); + Assert.assertNull(resultsBatchMultiSet.get(0)); + Assert.assertNull(resultsBatchMultiSet.get(1)); + Assert.assertNull(resultsBatchMultiSet.get(2)); + + // check deleted + List values = new ArrayList(); + client.batchMultiGet(tableName, keys, values); + Assert.assertEquals(4, values.size()); + Assert.assertEquals(0, values.get(0).values.size()); + Assert.assertEquals(0, values.get(1).values.size()); + Assert.assertEquals(0, values.get(2).values.size()); + Assert.assertEquals(0, values.get(3).values.size()); + } + catch (PException e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + + PegasusClientFactory.closeSingletonClient(); + } + + @Test + public void asyncApiTest() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + PegasusTableInterface tb = client.openTable("temp"); + + String asyncHashPrefix = "AsyncApiTestHash"; + String asyncSortPrefix = "AsyncApiTestSort"; + String asyncValuePrefix = "AsyncApiTestValue"; + String key = asyncHashPrefix + "_0"; + + // Exist + System.out.println("Test exist"); + try { + Assert.assertFalse(tb.asyncExist(key.getBytes(), key.getBytes(), 0).await().getNow()); + Assert.assertFalse(tb.asyncExist(null, null, 0).await().getNow()); + Assert.assertFalse(tb.asyncExist(null, key.getBytes(), 0).await().getNow()); + Assert.assertFalse(tb.asyncExist(key.getBytes(), null, 0).await().getNow()); + } catch (Throwable e) { + e.printStackTrace(); + Assert.fail(); + } + + try { + Assert.assertNull( tb.asyncSet(key.getBytes(), key.getBytes(), key.getBytes(),0).await().getNow() ); + Assert.assertTrue( tb.asyncExist(key.getBytes(), key.getBytes(), 0).await().getNow() ); + } catch (Throwable e) { + e.printStackTrace(); + Assert.fail(); + } + + // SortKeyCount + System.out.println("Test sortkeycount"); + try { + Long ans = tb.asyncSortKeyCount(key.getBytes(), 0).await().getNow(); + Assert.assertEquals(1, (long)ans); + + Assert.assertNull( tb.asyncDel(key.getBytes(), key.getBytes(), 0).await().getNow() ); + ans = tb.asyncSortKeyCount(key.getBytes(), 0).await().getNow(); + Assert.assertEquals(0, (long)ans); + + Future future = tb.asyncSortKeyCount(null, 0).await(); + Assert.assertFalse( future.isSuccess() ); + Assert.assertTrue( future.cause() instanceof PException ); + } catch (Throwable e) { + e.printStackTrace(); + Assert.fail(); + } + + // Get + System.out.println("Test get"); + try { + Assert.assertNull( tb.asyncGet(null, null, 0).await().getNow() ); + Assert.assertNull( tb.asyncGet(null, key.getBytes(), 0).await().getNow() ); + Assert.assertNull( tb.asyncGet(key.getBytes(), null, 0).await().getNow() ); + Assert.assertNull( tb.asyncGet(key.getBytes(), key.getBytes(), 0).await().getNow() ); + + Assert.assertNull( tb.asyncSet(key.getBytes(), key.getBytes(), key.getBytes(), 0).await().getNow() ); + Assert.assertArrayEquals( key.getBytes(), tb.asyncGet(key.getBytes(), key.getBytes(), 0).await().getNow() ); + + Assert.assertNull( tb.asyncDel(key.getBytes(), key.getBytes(), 0).await().getNow() ); + } catch (Throwable e) { + e.printStackTrace(); + Assert.fail(); + } + + // Set & ttl + System.out.println("Test set & ttl"); + try { + Assert.assertNull( tb.asyncSet(key.getBytes(), key.getBytes(), key.getBytes(), 5, 0).await().getNow() ); + Assert.assertArrayEquals( key.getBytes(), tb.asyncGet(key.getBytes(), key.getBytes(), 0).await().getNow() ); + + Integer ttlSeconds = tb.asyncTTL(key.getBytes(), key.getBytes(), 0).await().getNow(); + Assert.assertEquals( 5, (int)ttlSeconds ); + + Thread.sleep(6000); + Assert.assertFalse( tb.asyncExist(key.getBytes(), key.getBytes(), 0).await().getNow() ); + } catch (Throwable e) { + e.printStackTrace(); + Assert.fail(); + } + + // multiGet exeception handle + System.out.println("Test multiget exception handle"); + try { + Future f = tb.asyncMultiGet(null, null, 0).await(); + Assert.assertFalse( f.isSuccess() ); + Assert.assertTrue( f.cause() instanceof PException ); + + f = tb.asyncMultiGet("".getBytes(), null, 0).await(); + Assert.assertFalse(f.isSuccess()); + Assert.assertTrue( f.cause() instanceof PException ); + } catch (Throwable e) { + e.printStackTrace(); + Assert.fail(); + } + + // multiset exception handle + System.out.println("Test multiset exception handle"); + try { + Future f = tb.asyncMultiSet(null, null, 0).await(); + Assert.assertFalse( f.isSuccess() ); + Assert.assertTrue( f.cause() instanceof PException ); + + f = tb.asyncMultiSet("hehe".getBytes(), null, 0).await(); + Assert.assertFalse(f.isSuccess()); + Assert.assertTrue( f.cause() instanceof PException ); + + f = tb.asyncMultiSet("hehe".getBytes(), new ArrayList>(), 0).await(); + Assert.assertFalse(f.isSuccess()); + Assert.assertTrue( f.cause() instanceof PException ); + } catch (Throwable e) { + e.printStackTrace(); + Assert.fail(); + } + + // multiDel exception handle + System.out.println("Test multidel exception handle"); + try { + Future f = tb.asyncMultiDel(null, null, 0).await(); + Assert.assertFalse( f.isSuccess() ); + Assert.assertTrue( f.cause() instanceof PException ); + + f = tb.asyncMultiDel("hehe".getBytes(), null, 0).await(); + Assert.assertFalse(f.isSuccess()); + Assert.assertTrue( f.cause() instanceof PException ); + + f = tb.asyncMultiDel("hehe".getBytes(), new ArrayList(), 0).await(); + Assert.assertFalse(f.isSuccess()); + Assert.assertTrue( f.cause() instanceof PException ); + } catch (Throwable e) { + e.printStackTrace(); + Assert.fail(); + } + + // Set/get pipeline + System.out.println("Test set/get pipeline"); + try { + ArrayList> fl = new ArrayList>(); + + int totalNumber = 100; + for (int i=0; i f = tb.asyncSet(asyncHashPrefix.getBytes(), sortKey.getBytes(), value.getBytes(), 0, 0); + fl.add(f); + } + + for (int i=0; i> fl2 = new ArrayList>(); + for (byte[] sortKey: result.keys) { + Future f = tb.asyncGet(asyncHashPrefix.getBytes(), sortKey, 0); + fl2.add(f); + } + + for (int i=0; i f = tb.asyncDel(asyncHashPrefix.getBytes(), sortKey, 0); + fl.add(f); + } + + for (Future f: fl) { + f.await(); + Assert.assertTrue( f.isSuccess() ); + } + + Long sortKeyCount = tb.sortKeyCount(asyncHashPrefix.getBytes(), 0); + Assert.assertEquals(0, (long)sortKeyCount); + + } catch (Throwable e) { + e.printStackTrace(); + Assert.fail(); + } + } + + @Test + public void asyncApiSample() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + PegasusTableInterface table = client.openTable("temp"); + + String key = "hello"; + String value = "world"; + + Future f = table.asyncSet(null, null, null, 0); + f.addListener( + new PegasusTableInterface.SetListener() { + @Override + public void operationComplete(Future future) throws Exception { + if (future.isSuccess()) { + System.out.println("set succeed"); + Assert.fail(); + } + else { + assert future.cause() instanceof PException; + } + } + } + ); + f.awaitUninterruptibly(); + } +} diff --git a/src/test/java/com/xiaomi/infra/pegasus/client/TestBench.java b/src/test/java/com/xiaomi/infra/pegasus/client/TestBench.java new file mode 100644 index 00000000..e36501c7 --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/client/TestBench.java @@ -0,0 +1,123 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Created by mi on 16-3-23. + */ +public class TestBench { + @Test + public void testBench() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + + System.out.println("start to run single-thread test"); + + int total_count = 10000; + ArrayList keys = new ArrayList(); + ArrayList values = new ArrayList(); + for (int i = 0; i < total_count; i++) { + String key = "testBench-" + String.format("%06d", i); + String value = key + "-"; + StringBuilder sb = new StringBuilder(); + sb.append(key); + sb.append("-"); + while (sb.length() < 100) { + sb.append('0'); + } + keys.add(key.getBytes()); + values.add(value.getBytes()); + } + + { + long min_time = Long.MAX_VALUE; + long max_time = 0; + long start_time = System.nanoTime(); + long last_time = start_time; + for (int i = 0; i < total_count; i++) { + long begin_time = System.nanoTime(); + client.set(tableName, keys.get(i), null, values.get(i), 0); + long end_time = System.nanoTime(); + long dur_time = end_time - begin_time; + if (dur_time < min_time) { + min_time = dur_time; + } + if (dur_time > max_time) { + max_time = dur_time; + } + if ((i + 1) % 1000 == 0) { + long cur_time = System.nanoTime(); + long last_dur_time = cur_time - last_time; + String last_dur_time_str = String.format("%d.%06d", last_dur_time / 1000000000, last_dur_time % 1000000000 / 1000); + long total_dur_time = cur_time - start_time; + String total_dur_time_str = String.format("%d.%06d", total_dur_time / 1000000000, total_dur_time % 1000000000 / 1000); + double last_qps = (double) 1000 / last_dur_time * 1000000000; + double total_qps = (double) (i + 1) / total_dur_time * 1000000000; + String last_qps_str = String.format("%.1f", last_qps); + String total_qps_str = String.format("%.1f", total_qps); + System.out.println("testBench: (1000," + (i + 1) + ") ops and (" + last_qps_str + "," + total_qps_str + ") ops/second in (" + last_dur_time_str + "," + total_dur_time_str + ") seconds"); + last_time = cur_time; + } + } + double avg_time = (double)(last_time - start_time) / 100000 / 1000; + String avg_time_str = String.format("%.4f", avg_time); + double total_qps = (double) 100000 / (last_time - start_time) * 1000000000; + String total_qps_str = String.format("%.1f", total_qps); + System.out.println("fillseq : " + avg_time_str + " micros/op " + total_qps_str + " ops/sec"); + System.out.println("Microseconds per op:"); + System.out.println("Count: 100000 Average: " + avg_time_str); + System.out.println("Min: " + (min_time / 1000) + ".0000 Max:" + (max_time / 1000) + ".0000"); + } + + { + long min_time = Long.MAX_VALUE; + long max_time = 0; + long start_time = System.nanoTime(); + long last_time = start_time; + for (int i = 0; i < total_count; i++) { + long begin_time = System.nanoTime(); + byte[] value = client.get(tableName, keys.get(i), null); + long end_time = System.nanoTime(); + Assert.assertTrue(value != null); + Assert.assertTrue(Arrays.equals(values.get(i), value)); + long dur_time = end_time - begin_time; + if (dur_time < min_time) { + min_time = dur_time; + } + if (dur_time > max_time) { + max_time = dur_time; + } + if ((i + 1) % 1000 == 0) { + long cur_time = System.nanoTime(); + long last_dur_time = cur_time - last_time; + String last_dur_time_str = String.format("%d.%06d", last_dur_time / 1000000000, last_dur_time % 1000000000 / 1000); + long total_dur_time = cur_time - start_time; + String total_dur_time_str = String.format("%d.%06d", total_dur_time / 1000000000, total_dur_time % 1000000000 / 1000); + double last_qps = (double) 1000 / last_dur_time * 1000000000; + double total_qps = (double) (i + 1) / total_dur_time * 1000000000; + String last_qps_str = String.format("%.1f", last_qps); + String total_qps_str = String.format("%.1f", total_qps); + System.out.println("testBench: (1000," + (i + 1) + ") ops and (" + last_qps_str + "," + total_qps_str + ") ops/second in (" + last_dur_time_str + "," + total_dur_time_str + ") seconds"); + last_time = cur_time; + } + } + double avg_time = (double)(last_time - start_time) / 100000 / 1000; + String avg_time_str = String.format("%.4f", avg_time); + double total_qps = (double) 100000 / (last_time - start_time) * 1000000000; + String total_qps_str = String.format("%.1f", total_qps); + System.out.println("readrandom : " + avg_time_str + " micros/op " + total_qps_str + " ops/sec"); + System.out.println("Microseconds per op:"); + System.out.println("Count: 100000 Average: " + avg_time_str); + System.out.println("Min: " + (min_time / 1000) + ".0000 Max:" + (max_time / 1000) + ".0000"); + } + + PegasusClientFactory.closeSingletonClient(); + } +} diff --git a/src/test/java/com/xiaomi/infra/pegasus/client/TestMultiThread.java b/src/test/java/com/xiaomi/infra/pegasus/client/TestMultiThread.java new file mode 100644 index 00000000..347f9947 --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/client/TestMultiThread.java @@ -0,0 +1,172 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; + +/** + * Created by mi on 16-3-23. + */ +public class TestMultiThread { + public static final String TABLE_NAME = "temp"; + + private static class VisitThread extends Thread { + // so total operations = total_keys + removed_keys + private static int total_keys = 3000; + private static int removed_keys = 2000; + + private String name; + private PegasusClientInterface client; + + public VisitThread(String name, PegasusClientInterface client) { + this.name = name; + this.client = client; + } + + public void run() { + ArrayList values = new ArrayList(total_keys); + + long value_sum = 0; + for (int i = 0; i < total_keys; ++i) { + values.add((int) (Math.random() * 1000)); + } + + int left_put = total_keys; + int key_cursor = 0; + int total_count = total_keys + removed_keys; + + for (int i = 1; i <= total_count; ++i) { + if (i % 1000 == 0) { + System.out.println(name + "round " + i); + } + int t = (int) (Math.random() * (total_count - i)); + if (t < left_put) { + String key = name + String.valueOf(key_cursor); + String value = String.valueOf(values.get(key_cursor)); + try { + client.set(TABLE_NAME, key.getBytes(), null, value.getBytes(), 0); + } catch (PException e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + --left_put; + ++key_cursor; + } else { + int index = (int) (Math.random() * Math.min(key_cursor + 100, total_keys)); + String key = name + String.valueOf(index); + try { + client.del(TABLE_NAME, key.getBytes(), null); + if (index < key_cursor) { + values.set(index, 0); + } + } catch (PException e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + } + } + + for (int i = 1; i <= total_keys; ++i) { + if (i % 1000 == 0) { + System.out.println(name + "get round " + i); + } + String key = name + String.valueOf(i-1); + try { + byte[] resp = client.get(TABLE_NAME, key.getBytes(), null); + if (resp != null) { + value_sum += Integer.valueOf(new String(resp)); + } + } catch (PException e) { + e.printStackTrace(); + } + } + + long expected_sum = 0; + for (int v : values) { + expected_sum += v; + } + Assert.assertEquals(expected_sum, value_sum); + } + } + + @Test + public void testMultiThread() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + + System.out.println("start to run multi-thread test"); + + ArrayList threadList = new ArrayList(); + for (int i = 0; i < 10; ++i) { + threadList.add(new VisitThread("Thread_" + String.valueOf(i) + "_", client)); + } + for (VisitThread vt : threadList) { + vt.start(); + } + for (VisitThread vt : threadList) { + while (true) { + try { + vt.join(); + break; + } catch (InterruptedException e) { + } + } + } + + PegasusClientFactory.closeSingletonClient(); + } + +// private static final class FillThread extends Thread { +// private String name; +// private PegasusClientInterface client; +// +// public FillThread(String aName, PegasusClientInterface aClient) { +// name = aName; +// client = aClient; +// } +// +// public void run() { +// long i = 1; +// while (true) { +// String value = String.valueOf(i%10000); +// try { +// client.set(TABLE_NAME, value.getBytes(), value.getBytes(), value.getBytes()); +// i++; +// } catch (PException ex) { +// ex.printStackTrace(); +// } +// +// if (i%1000 == 0) { +// System.out.println(name + " round " + i); +// } +// } +// } +// } +// +// @Test +// public void testFillValue() throws PException { +// PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); +// +// System.out.println("start to run multithread fill"); +// +// ArrayList ftList = new ArrayList(); +// for (int i=0; i<3; ++i) { +// ftList.add(new FillThread("Thread" + String.valueOf(i), client)); +// } +// +// for (int i=0; i<3; ++i) { +// ftList.get(i).start(); +// } +// +// for (int i=0; i<3; ++i) { +// try { +// ftList.get(i).join(); +// } catch (Exception ex) { +// ex.printStackTrace(); +// } +// } +// } +} diff --git a/src/test/java/com/xiaomi/infra/pegasus/client/TestNoOperate.java b/src/test/java/com/xiaomi/infra/pegasus/client/TestNoOperate.java new file mode 100644 index 00000000..3ec07e5f --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/client/TestNoOperate.java @@ -0,0 +1,35 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.junit.Test; + +/** + * Created by weijiesun on 16-11-24. + */ +public class TestNoOperate { + @Test + public void testNoOperate() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + + System.out.println("start to write some keys"); + for (int i = 0; i < 100; ++i) { + String hashKey = "hello" + String.valueOf(i); + String sortKey = "0"; + String value = "world"; + client.set(tableName, hashKey.getBytes(), sortKey.getBytes(), value.getBytes()); + } + + System.out.println("start to wait some time"); + + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + PegasusClientFactory.closeSingletonClient(); + } +} \ No newline at end of file diff --git a/src/test/java/com/xiaomi/infra/pegasus/client/TestPing.java b/src/test/java/com/xiaomi/infra/pegasus/client/TestPing.java new file mode 100644 index 00000000..ddf1b1b8 --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/client/TestPing.java @@ -0,0 +1,115 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.Assert; +import org.junit.Test; + +import java.util.*; + +/** + * Created by mi on 16-3-22. + */ +public class TestPing { + @Test + public void testPing() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + + byte[] hashKey = "hello".getBytes(); + byte[] sortKey = "0".getBytes(); + byte[] value = "world".getBytes(); + byte[] sortKey1 = "1".getBytes(); + byte[] value1 = "pegasus".getBytes(); + + try { + System.out.println("set value ..."); + client.set(tableName, hashKey, sortKey, value, 0); + System.out.println("set value ok"); + + System.out.println("set value1 ..."); + client.set(tableName, hashKey, sortKey1, value1, 0); + System.out.println("set value1 ok"); + + System.out.println("multi set ..."); + List> setValues = new ArrayList>(); + for (int i = 2; i < 9; ++i) { + byte[] k = Integer.toString(i).getBytes(); + byte[] v = ("value" + i).getBytes(); + setValues.add(new ImmutablePair(k, v)); + } + client.multiSet(tableName, hashKey, setValues); + System.out.println("multi set ..."); + + System.out.println("get value ..."); + byte[] result = client.get(tableName, hashKey, sortKey); + Assert.assertTrue(Arrays.equals(value, result)); + System.out.println("get value ok"); + + System.out.println("get ttl ..."); + int ttl = client.ttl(tableName, hashKey, sortKey); + Assert.assertEquals(-1, ttl); + System.out.println("get ttl ok"); + + System.out.println("multi get ..."); + List sortKeys = new ArrayList(); + sortKeys.add("unexist-sort-key".getBytes()); + sortKeys.add(sortKey1); + sortKeys.add(sortKey1); + sortKeys.add(sortKey); + List> values = new ArrayList>(); + boolean getAll = client.multiGet(tableName, hashKey, sortKeys, values); + Assert.assertTrue(getAll); + Assert.assertEquals(2, values.size()); + Assert.assertEquals(sortKey, values.get(0).getKey()); + Assert.assertArrayEquals(sortKey, values.get(0).getKey()); + Assert.assertArrayEquals(value, values.get(0).getValue()); + Assert.assertEquals(sortKey1, values.get(1).getKey()); + Assert.assertArrayEquals(sortKey1, values.get(1).getKey()); + Assert.assertArrayEquals(value1, values.get(1).getValue()); + System.out.println("multi get ok"); + + System.out.println("multi get partial ..."); + sortKeys.clear(); + values.clear(); + sortKeys.add(sortKey); + sortKeys.add(sortKey1); + for (Pair p : setValues) { + sortKeys.add(p.getKey()); + } + getAll = client.multiGet(tableName, hashKey, sortKeys, 5, 1000000, values); + Assert.assertFalse(getAll); + Assert.assertEquals(5, values.size()); + Assert.assertEquals(sortKey, values.get(0).getKey()); + Assert.assertArrayEquals(sortKey, values.get(0).getKey()); + Assert.assertArrayEquals(value, values.get(0).getValue()); + Assert.assertEquals(sortKey1, values.get(1).getKey()); + Assert.assertArrayEquals(sortKey1, values.get(1).getKey()); + Assert.assertArrayEquals(value1, values.get(1).getValue()); + for (int i = 2; i < 5; ++i) { + Assert.assertEquals(setValues.get(i - 2).getKey(), values.get(i).getKey()); + Assert.assertArrayEquals(setValues.get(i - 2).getKey(), values.get(i).getKey()); + Assert.assertArrayEquals(setValues.get(i - 2).getValue(), values.get(i).getValue()); + } + System.out.println("multi get partial ok"); + + System.out.println("del value ..."); + client.del(tableName, hashKey,sortKey); + System.out.println("del value ok"); + + System.out.println("get deleted value ..."); + result = client.get(tableName, hashKey, sortKey); + Assert.assertEquals(result, null); + System.out.println("get deleted value ok"); + } + catch (PException e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + + PegasusClientFactory.closeSingletonClient(); + } +} diff --git a/src/test/java/com/xiaomi/infra/pegasus/client/TestPingZK.java b/src/test/java/com/xiaomi/infra/pegasus/client/TestPingZK.java new file mode 100644 index 00000000..ca300d22 --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/client/TestPingZK.java @@ -0,0 +1,76 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.junit.Assert; +import org.junit.Test; + +import org.I0Itec.zkclient.ZkClient; +import org.I0Itec.zkclient.serialize.BytesPushThroughSerializer; + +import java.io.InputStream; +import java.util.Arrays; +import java.util.Scanner; + +/** + * @author qinzuoyan + */ +public class TestPingZK { + + @Test + public void testPingZK() throws PException { + String zkServer = "127.0.0.1:22181"; + String zkPath = "/databases/pegasus/test-java-client"; + String configPath = "zk://" + zkServer + zkPath; + + // init zk config + ZkClient zkClient = new ZkClient(zkServer, 30000, 30000, new BytesPushThroughSerializer()); + String[] components = zkPath.split("/"); + String curPath = ""; + for (int i = 0; i < components.length; ++i) { + if (components[i].isEmpty()) + continue; + curPath += "/" + components[i]; + if (!zkClient.exists(curPath)) { + zkClient.createPersistent(curPath); + } + } + InputStream is = PegasusClient.class.getResourceAsStream("/pegasus.properties"); + Scanner s = new java.util.Scanner(is).useDelimiter("\\A"); + String configData = s.hasNext() ? s.next() : ""; + System.out.println("write config to " + configPath); + zkClient.writeData(zkPath, configData.getBytes()); + + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(configPath); + String tableName = "temp"; + + byte[] hashKey = "hello".getBytes(); + byte[] sortKey = "0".getBytes(); + byte[] value = "world".getBytes(); + + System.out.println("set value ..."); + client.set(tableName, hashKey, sortKey, value, 0); + System.out.println("set value ok"); + + System.out.println("get value ..."); + byte[] result = client.get(tableName, hashKey, sortKey); + Assert.assertTrue(Arrays.equals(value, result)); + System.out.println("get value ok"); + + System.out.println("del value ..."); + client.del(tableName, hashKey,sortKey); + System.out.println("del value ok"); + + System.out.println("get deleted value ..."); + result = client.get(tableName, hashKey, sortKey); + Assert.assertEquals(result, null); + System.out.println("get deleted value ok"); + + System.out.println("set value ..."); + client.set(tableName, hashKey, sortKey, value, 0); + System.out.println("set value ok"); + + PegasusClientFactory.closeSingletonClient(); + } +} diff --git a/src/test/java/com/xiaomi/infra/pegasus/client/TestScan.java b/src/test/java/com/xiaomi/infra/pegasus/client/TestScan.java new file mode 100644 index 00000000..36b1d074 --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/client/TestScan.java @@ -0,0 +1,425 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import io.netty.util.concurrent.*; + +import org.apache.commons.lang3.tuple.Pair; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestScan { + static char[] CCH = "_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); + static char[] buffer = new char[256]; + static Random random; + + private static PegasusClientInterface client; + private static String tableName = "temp"; + + private static TreeMap> base; + private static String expectedHashKey; + + @BeforeClass + public static void setupTestCase() throws PException { + client = PegasusClientFactory.getSingletonClient(); + random = new Random(); + base = new TreeMap>(); + expectedHashKey = randomString(); + + for (int i = 0; i < buffer.length; i++) { + buffer[i] = CCH[random.nextInt(CCH.length)]; + } + + clearDatabase(); + + TreeMap hashMap = new TreeMap(); + for (int i = 0; i < 1000 || hashMap.size() < 1000; i++) { + String sortKey = randomString(); + String value = randomString(); + + client.set(tableName, expectedHashKey.getBytes(), sortKey.getBytes(), + value.getBytes(), 0); + hashMap.put(sortKey, value); + } + base.put(expectedHashKey, hashMap); + + for (int i = 0; i < 1000 || base.size() < 1000; i++) + { + String hashKey = randomString(); + TreeMap sortMap = base.get(hashKey); + if (sortMap == null) { + sortMap = new TreeMap(); + base.put(hashKey, sortMap); + } + for (int j = 0; j < 10 || sortMap.size() < 10; j++) { + String sortKey = randomString(); + String value = randomString(); + client.set(tableName, hashKey.getBytes(), sortKey.getBytes(), value.getBytes(), 0); + sortMap.put(sortKey, value); + } + } + } + + @Test + public void testAllSortKey() throws PException { + /**** ALL SORT_KEYS ****/ + System.out.println("TESTING_HASH_SCAN, ALL SORT_KEYS ...."); + ScanOptions options = new ScanOptions(); + TreeMap data = new TreeMap(); + PegasusScannerInterface scanner = + client.getScanner(tableName, expectedHashKey.getBytes(), new byte[]{}, new byte[]{}, options); + Assert.assertNotNull(scanner); + Pair, byte[]> item; + while((item = scanner.next()) != null) { + Assert.assertEquals(expectedHashKey, new String(item.getLeft().getLeft())); + checkAndPutSortMap(data, expectedHashKey, + new String(item.getLeft().getRight()), new String(item.getRight())); + } + scanner.close(); + compareSortMap(data, base.get(expectedHashKey), expectedHashKey); + } + + @Test + public void testInclusive() throws PException { + /**** [start, stop] ****/ + System.out.println("TESTING_HASH_SCAN, [start, stop]..."); + Iterator iterator = base.get(expectedHashKey).keySet().iterator(); + for (int i = random.nextInt(500); i >= 0; i--) + iterator.next(); + String start = iterator.next(); + for (int i = random.nextInt(400) + 50; i >= 0; i--) + iterator.next(); + String stop = iterator.next(); + + ScanOptions options = new ScanOptions(); + options.startInclusive = true; + options.stopInclusive = true; + TreeMap data = new TreeMap(); + PegasusScannerInterface scanner = client.getScanner(tableName, + expectedHashKey.getBytes(), start.getBytes(), stop.getBytes(), options); + Assert.assertNotNull(scanner); + Pair, byte[]> item; + while((item = scanner.next()) != null) { + Assert.assertEquals(expectedHashKey, new String(item.getLeft().getLeft())); + checkAndPutSortMap(data, expectedHashKey, + new String(item.getLeft().getRight()), new String(item.getRight())); + } + scanner.close(); + compareSortMap(data, + base.get(expectedHashKey).subMap(start, true, stop, true), + expectedHashKey); + } + + @Test + public void testExclusive() throws PException { + /**** (start, stop) ****/ + System.out.println("TESTING_HASH_SCAN, (start, stop)..."); + Iterator iterator = base.get(expectedHashKey).keySet().iterator(); + for (int i = random.nextInt(500); i >= 0; i--) + iterator.next(); + String start = iterator.next(); + for (int i = random.nextInt(400) + 50; i >= 0; i--) + iterator.next(); + String stop = iterator.next(); + + ScanOptions options = new ScanOptions(); + options.startInclusive = false; + options.stopInclusive = false; + TreeMap data = new TreeMap(); + PegasusScannerInterface scanner = client.getScanner(tableName, + expectedHashKey.getBytes(), start.getBytes(), stop.getBytes(), options); + Assert.assertNotNull(scanner); + Pair, byte[]> item; + while((item = scanner.next()) != null) { + Assert.assertEquals(expectedHashKey, new String(item.getLeft().getLeft())); + checkAndPutSortMap(data, expectedHashKey, + new String(item.getLeft().getRight()), new String(item.getRight())); + } + scanner.close(); + compareSortMap(data, + base.get(expectedHashKey).subMap(start, false, stop, false), + expectedHashKey); + } + + @Test + public void testOnePoint() throws PException { + System.out.println("TESTING_HASH_SCAN, [start, start]"); + Iterator iterator = base.get(expectedHashKey).keySet().iterator(); + for (int i = random.nextInt(800); i >= 0; i--) + iterator.next(); + String start = iterator.next(); + + ScanOptions options = new ScanOptions(); + options.startInclusive = true; + options.stopInclusive = true; + PegasusScannerInterface scanner = client.getScanner(tableName, + expectedHashKey.getBytes(), start.getBytes(), start.getBytes(), options); + Assert.assertNotNull(scanner); + Pair, byte[]> item = scanner.next(); + Assert.assertEquals(start, new String(item.getLeft().getRight())); + item = scanner.next(); + Assert.assertNull(item); + scanner.close(); + } + + @Test + public void testHalfInclusive() throws PException { + System.out.println("TESTING_HASH_SCAN, [start, start)"); + Iterator iterator = base.get(expectedHashKey).keySet().iterator(); + for (int i = random.nextInt(800); i >= 0; i--) + iterator.next(); + String start = iterator.next(); + + ScanOptions options = new ScanOptions(); + options.startInclusive = true; + options.stopInclusive = false; + PegasusScannerInterface scanner = client.getScanner(tableName, + expectedHashKey.getBytes(), start.getBytes(), start.getBytes(), options); + Assert.assertNotNull(scanner); + Pair, byte[]> item = scanner.next(); + Assert.assertNull(item); + scanner.close(); + } + + @Test + public void testVoidSpan() throws PException { + /**** [stop, start] ****/ + System.out.println("TESTING_HASH_SCAN, [stop, start]..."); + Iterator iterator = base.get(expectedHashKey).keySet().iterator(); + for (int i = random.nextInt(500); i >= 0; i--) + iterator.next(); + String start = iterator.next(); + for (int i = random.nextInt(400) + 50; i >= 0; i--) + iterator.next(); + String stop = iterator.next(); + + ScanOptions options = new ScanOptions(); + options.startInclusive = true; + options.stopInclusive = true; + PegasusScannerInterface scanner = client.getScanner(tableName, + expectedHashKey.getBytes(), stop.getBytes(), start.getBytes(), options); + Assert.assertNotNull(scanner); + Pair, byte[]> item = scanner.next(); + Assert.assertNull(item); + scanner.close(); + } + + @Test + public void testOverallScan() throws PException { + System.out.println("TEST OVERALL_SCAN..."); + + ScanOptions options = new ScanOptions(); + TreeMap> data = new TreeMap>(); + List scanners = client.getUnorderedScanners(tableName, 3, options); + Assert.assertTrue(scanners.size() <= 3); + + for (int i = scanners.size() - 1; i >= 0; i--) + { + PegasusScannerInterface scanner = scanners.get(i); + Assert.assertNotNull(scanner); + Pair, byte[]> item; + while((item = scanner.next()) != null) { + checkAndPut(data, new String(item.getLeft().getLeft()), new String(item.getLeft().getRight()), + new String(item.getRight())); + } + scanner.close(); + } + compare(data, base); + } + + @Test + public void testAsyncScan() throws PException { + System.out.println("TEST asyncNext..."); + + ScanOptions options = new ScanOptions(); + TreeMap> data = new TreeMap>(); + List scanners = client.getUnorderedScanners(tableName, 3, options); + Assert.assertTrue(scanners.size() <= 3); + + for (int i = scanners.size() - 1; i >= 0; i--) + { + PegasusScannerInterface scanner = scanners.get(i); + Assert.assertNotNull(scanner); + Future, byte[]>> item; + while (true) { + item = scanner.asyncNext(); + try { + Pair, byte[]> pair = item.get(); + if (pair == null) + break; + checkAndPut(data, new String(pair.getLeft().getLeft()), new String(pair.getLeft().getRight()), + new String(pair.getRight())); + } catch (Exception e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + } + } + compare(data, base); + } + + @Test + public void testConcurrentCallAsyncScan() throws PException { + int [] batchSizes = {10, 100, 500, 1000}; + int totalKvSize = 10000; // we just use scan to acquire 10000 kv-pairs + long start_time_ms = 0, end_time_ms = 0; + Deque, byte[]>>> futures = + new LinkedList,byte[]>>>(); + for (int idx = 0; idx < batchSizes.length; idx ++) { + int batchSize = batchSizes[idx]; + ScanOptions options = new ScanOptions(); + options.batchSize = batchSize; + TreeMap> data = new TreeMap>(); + List scanners = client.getUnorderedScanners(tableName, 1, options); + Assert.assertTrue(scanners.size() <= 1); + System.out.println("start to scan " + totalKvSize + " kv-pairs with scan batch size " + batchSize); + start_time_ms = System.currentTimeMillis(); + futures.clear(); + for (int cnt = 0; cnt < totalKvSize; cnt ++) { + futures.add(scanners.get(0).asyncNext()); + } + try { + for (Future, byte[]>> fu : futures) { + fu.get(); + } + } catch (Exception e) { + e.printStackTrace(); + Assert.assertTrue(false); + } + end_time_ms = System.currentTimeMillis(); + System.out.println("consuing time: " + (end_time_ms - start_time_ms) + "ms"); + } + } + + private static void clearDatabase() throws PException { + ScanOptions options = new ScanOptions(); + List scanners = client.getUnorderedScanners(tableName, 1, options); + Assert.assertEquals(1, scanners.size()); + Assert.assertNotNull(scanners.get(0)); + + Pair, byte[]> item; + while((item = scanners.get(0).next()) != null ) { + client.del(tableName, item.getLeft().getLeft(), item.getLeft().getRight()); + } + scanners.get(0).close(); + + scanners = client.getUnorderedScanners(tableName, 1, options); + Assert.assertEquals(1, scanners.size()); + Assert.assertNotNull(scanners.get(0)); + item = scanners.get(0).next(); + scanners.get(0).close(); + Assert.assertNull( + item == null ? null : String.format("Database is cleared but not empty, hashKey=%s, sortKey=%s", + new String(item.getLeft().getLeft()), new String(item.getLeft().getRight())), + item); + } + + private static String randomString() { + int pos = random.nextInt(buffer.length); + buffer[pos] = CCH[random.nextInt(CCH.length)]; + int length = random.nextInt(buffer.length) + 1; + if (pos + length < buffer.length) { + return new String(buffer, pos, length); + } else { + return new String(buffer, pos, buffer.length - pos) + + new String(buffer, 0, length + pos - buffer.length); + } + } + + private static void checkAndPut(TreeMap> data, + String hashKey, String sortKey, String value) { + TreeMap sortMap = data.get(hashKey); + if (sortMap == null) { + sortMap = new TreeMap(); + data.put(hashKey, sortMap); + } else { + Assert.assertNull( + String.format("Duplicate: hashKey=%s, sortKye=%s, oldValue=%s, newValue=%s", + hashKey, sortKey, sortMap.get(sortKey), value), + sortMap.get(sortKey)); + } + sortMap.put(sortKey, value); + } + + private static void checkAndPutSortMap(TreeMap data, + String hashKey, String sortKey, String value) { + Assert.assertNull( + String.format("Duplicate: hashKey=%s, sortKye=%s, oldValue=%s, newValue=%s", + hashKey, sortKey, data.get(sortKey), value), + data.get(sortKey)); + data.put(sortKey, value); + } + + private static void compare(TreeMap> data, + TreeMap> base) { + Iterator>> iterator1 = data.entrySet().iterator(); + Iterator>> iterator2 = base.entrySet().iterator(); + while(true) { + Map.Entry> kv1 = + iterator1.hasNext() ? iterator1.next() : null; + Map.Entry> kv2 = + iterator2.hasNext() ? iterator2.next() : null; + if (kv1 == null) { + Assert.assertNull( + kv2 == null ? null : String.format("Only in base: hashKey=%s", kv2.getKey()), + kv2); + break; + } + Assert.assertNotNull(String.format("Only in data: hashKey=%s", kv1.getKey()), + kv2); + Assert.assertEquals( + String.format("Diff: dataHashKey=%s, baseHashKey=%s", kv1.getKey(), kv2.getKey()), + kv1.getKey(), kv2.getKey()); + Iterator> iterator3 = kv1.getValue().entrySet().iterator(); + Iterator> iterator4 = kv2.getValue().entrySet().iterator(); + while(true) { + Map.Entry kv3 = iterator3.hasNext() ? iterator3.next() : null; + Map.Entry kv4 = iterator4.hasNext() ? iterator4.next() : null; + if (kv3 == null) { + Assert.assertNull( + kv4 == null ? null : String.format("Only in base: hashKey=%s, sortKey=%s, value=%s", + kv1.getKey(), kv4.getKey(), kv4.getValue()), + kv4); + break; + } + Assert.assertNotNull( + String.format("Only in data: hashKey=%s, sortKey=%s, value=%s", + kv1.getKey(), kv3.getKey(), kv3.getValue()), + kv4); + Assert.assertEquals( + String.format("Diff: hashKey=%s, dataSortKey=%s, dataValue=%s, baseSortKey=%s, baseValue=%s", + kv1.getKey(), kv3.getKey(), kv3.getValue(), kv4.getKey(), kv4.getValue()), + kv3, kv4); + } + } + } + + private static void compareSortMap(NavigableMap data, NavigableMap base, + String hashKey) { + Iterator> iterator1 = data.entrySet().iterator(); + Iterator> iterator2 = base.entrySet().iterator(); + while(true) { + Map.Entry kv1 = iterator1.hasNext() ? iterator1.next() : null; + Map.Entry kv2 = iterator2.hasNext() ? iterator2.next() : null; + if (kv1 == null) { + Assert.assertNull( + kv2 == null ? null : String.format("Only in base: hashKey=%s, sortKey=%s, value=%s", + hashKey, kv2.getKey(), kv2.getValue()), + kv2); + break; + } + Assert.assertNotNull( String.format("Only in data: hashKey=%s, sortKey=%s, value=%s", + hashKey, kv1.getKey(), kv1.getValue()), + kv2); + Assert.assertEquals( + String.format("Diff: hashKey=%s, dataSortKey=%s, dataValue=%s, baseSortKey=%s, baseValue=%s", + hashKey, kv1.getKey(), kv1.getValue(), kv2.getKey(), kv2.getValue()), + kv1, kv2); + } + } +} diff --git a/src/test/java/com/xiaomi/infra/pegasus/client/TestTimeout.java b/src/test/java/com/xiaomi/infra/pegasus/client/TestTimeout.java new file mode 100644 index 00000000..c86581cc --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/client/TestTimeout.java @@ -0,0 +1,41 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.client; + +import org.junit.*; + +public class TestTimeout { + @Test + public void testTimeout() throws PException { + PegasusClientInterface client = PegasusClientFactory.getSingletonClient(); + String tableName = "temp"; + + for (int i=0; i<1; ++i) { + byte[] hashKey = "hello".getBytes(); + byte[] sortKey = "0".getBytes(); + byte[] value = ("world" + String.valueOf(i)).getBytes(); + + long current = System.currentTimeMillis(); + try { + client.set(tableName, hashKey, sortKey, value, 0); + System.out.println("set succeed, time takes: " + (System.currentTimeMillis() - current) + " ms"); + } catch (PException e) { + System.out.println("set encounter exception, time takes: " + (System.currentTimeMillis() - current) + " ms, " + e.getMessage()); + } + + current = System.currentTimeMillis(); + try { + byte[] result = client.get(tableName, hashKey, sortKey); + System.out.println("get succeed, time takes: " + (System.currentTimeMillis() - current) + " ms"); + if (result != null) { + System.out.println("get result: " + new String(result)); + } + } catch (PException e) { + System.out.println("get encounter exception, time takes: " + (System.currentTimeMillis() - current) + " ms, " + e.getMessage()); + e.printStackTrace(); + } + } + PegasusClientFactory.closeSingletonClient(); + } +} diff --git a/src/test/java/com/xiaomi/infra/pegasus/metrics/MetricsPoolTest.java b/src/test/java/com/xiaomi/infra/pegasus/metrics/MetricsPoolTest.java new file mode 100644 index 00000000..dfa049e3 --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/metrics/MetricsPoolTest.java @@ -0,0 +1,143 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.metrics; + +import com.codahale.metrics.Histogram; +import com.codahale.metrics.Meter; +import com.codahale.metrics.MetricRegistry; +import junit.framework.Assert; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; + +/** + * Created by weijiesun on 18-3-9. + */ +public class MetricsPoolTest { + @Before + public void before() { + r = new MetricRegistry(); + } + + @Test + public void genJsonsFromMeter() throws Exception { + String host = "simple-test-host.bj"; + String tags = "what=you,like=another"; + MetricsPool pool = new MetricsPool(host, tags, 20); + Meter m = r.meter("TestName"); + + m.mark(1); + m.mark(1); + + StringBuilder builder = new StringBuilder(); + pool.genJsonsFromMeter("TestName", m, builder); + + JSONArray array = new JSONArray("[" + builder.toString() + "]"); + Assert.assertEquals(4, array.length()); + + String[] metrics = { + "TestName.cps-1sec", + "TestName.cps-1min", + "TestName.cps-5min", + "TestName.cps-15min" + }; + + for (int i=0; i> callbacks = new ArrayList>(); + for (int i=0; i<1000; ++i) { + query_cfg_request req = new query_cfg_request("temp", new ArrayList()); + final client_operator op = new query_cfg_operator(new gpid(-1, -1), req); + FutureTask callback = new FutureTask(new Callable() { + @Override + public Void call() throws Exception { + Assert.assertEquals(error_code.error_types.ERR_OK, op.rpc_error.errno); + return null; + } + }); + callbacks.add(callback); + session.asyncQuery(op, callback, 10); + } + + com.xiaomi.infra.pegasus.tools.Toollet.closeServer(addr); + for (FutureTask cb: callbacks) { + try { + tools.waitUninterruptable(cb, Integer.MAX_VALUE); + } catch (ExecutionException e) { + e.printStackTrace(); + Assert.fail(); + } + } + } +} diff --git a/src/test/java/com/xiaomi/infra/pegasus/rpc/async/ReplicaSessionTest.java b/src/test/java/com/xiaomi/infra/pegasus/rpc/async/ReplicaSessionTest.java new file mode 100644 index 00000000..7d1fa554 --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/rpc/async/ReplicaSessionTest.java @@ -0,0 +1,149 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc.async; + +import com.xiaomi.infra.pegasus.base.error_code; +import com.xiaomi.infra.pegasus.tools.Toollet; +import com.xiaomi.infra.pegasus.tools.tools; +import org.junit.Assert; +import org.junit.Test; +import org.junit.Before; +import org.junit.After; + +import com.xiaomi.infra.pegasus.operator.*; +import org.slf4j.Logger; + +import java.util.ArrayList; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; + +/** +* ReplicaSession Tester. +* +* @author sunweijie@xiaomi.com +* @version 1.0 +*/ +public class ReplicaSessionTest { + private String[] metaList = {"127.0.0.1:34601", "127.0.0.1:34602", "127.0.0.1:34603"}; + private final Logger logger = org.slf4j.LoggerFactory.getLogger(ReplicaSessionTest.class); + private ClusterManager manager; + + @Before + public void before() throws Exception { + manager = new ClusterManager(1000, 1, false, + null, 60, metaList); + } + + @After + public void after() throws Exception { + } + + /** + * Method: connect() + */ + @Test + public void testConnect() throws Exception { + //test1: connect to a invalid address + com.xiaomi.infra.pegasus.base.rpc_address addr = new com.xiaomi.infra.pegasus.base.rpc_address(); + addr.fromString("127.0.0.1:12345"); + ReplicaSession rs = manager.getReplicaSession(addr); + + ArrayList > callbacks = new ArrayList>(); + + for (int i=0; i<100; ++i) { + final client_operator op = new rrdb_put_operator(new com.xiaomi.infra.pegasus.base.gpid(-1, -1), + "", + null); + final FutureTask cb = new FutureTask(new Callable() { + @Override + public Void call() throws Exception { + Assert.assertEquals(error_code.error_types.ERR_SESSION_RESET, op.rpc_error.errno); + return null; + } + }); + + callbacks.add(cb); + rs.asyncSend(op, cb, 1000); + } + + for (FutureTask cb: callbacks) { + try { + tools.waitUninterruptable(cb, Integer.MAX_VALUE); + } catch (ExecutionException e) { + Assert.fail(); + } + } + + final ReplicaSession cp_rs = rs; + Toollet.waitCondition(new Toollet.BoolCallable() { + @Override + public boolean call() { + return ReplicaSession.ConnState.DISCONNECTED==cp_rs.getState(); + } + }, 5); + + //test2: connect to an valid address, and then close the server + addr.fromString("127.0.0.1:34801"); + callbacks.clear(); + + rs = manager.getReplicaSession(addr); + for (int i=0; i<20; ++i) { + // we send query request to replica server. We expect it to discard it. + final int index = i; + com.xiaomi.infra.pegasus.apps.update_request req = new com.xiaomi.infra.pegasus.apps.update_request( + new com.xiaomi.infra.pegasus.base.blob("hello".getBytes()), + new com.xiaomi.infra.pegasus.base.blob("world".getBytes()), + 0); + + final client_operator op = new Toollet.test_operator(new com.xiaomi.infra.pegasus.base.gpid(-1, -1), req); + final com.xiaomi.infra.pegasus.base.rpc_address cp_addr = addr; + final FutureTask cb = new FutureTask(new Callable() { + @Override + public Void call() throws Exception { + Assert.assertEquals(error_code.error_types.ERR_TIMEOUT, op.rpc_error.errno); + // for the last request, we kill the server + if (index == 19) { + com.xiaomi.infra.pegasus.tools.Toollet.closeServer(cp_addr); + } + return null; + } + }); + + callbacks.add(cb); + rs.asyncSend(op, cb, 500); + } + + for (int i=0; i<80; ++i) { + // then we still send query request to replica server. But the timeout is longer. + com.xiaomi.infra.pegasus.apps.update_request req = new com.xiaomi.infra.pegasus.apps.update_request( + new com.xiaomi.infra.pegasus.base.blob("hello".getBytes()), + new com.xiaomi.infra.pegasus.base.blob("world".getBytes()), + 0); + final client_operator op = new Toollet.test_operator(new com.xiaomi.infra.pegasus.base.gpid(-1, -1), req); + final FutureTask cb = new FutureTask(new Callable() { + @Override + public Void call() throws Exception { + Assert.assertEquals(error_code.error_types.ERR_SESSION_RESET, op.rpc_error.errno); + return null; + } + }); + + callbacks.add(cb); + //these requests have longer timeout, so they should be responsed later than the server is killed + rs.asyncSend(op, cb, 2000); + } + + for (FutureTask cb: callbacks) { + try { + tools.waitUninterruptable(cb, Integer.MAX_VALUE); + } catch (ExecutionException e) { + e.printStackTrace(); + Assert.fail(); + } + } + + com.xiaomi.infra.pegasus.tools.Toollet.tryStartServer(addr); + } +} diff --git a/src/test/java/com/xiaomi/infra/pegasus/rpc/async/TableHandlerTest.java b/src/test/java/com/xiaomi/infra/pegasus/rpc/async/TableHandlerTest.java new file mode 100644 index 00000000..f7af50e5 --- /dev/null +++ b/src/test/java/com/xiaomi/infra/pegasus/rpc/async/TableHandlerTest.java @@ -0,0 +1,190 @@ +// Copyright (c) 2017, Xiaomi, Inc. All rights reserved. +// This source code is licensed under the Apache License Version 2.0, which +// can be found in the LICENSE file in the root directory of this source tree. +package com.xiaomi.infra.pegasus.rpc.async; + +import com.xiaomi.infra.pegasus.rpc.KeyHasher; +import com.xiaomi.infra.pegasus.rpc.ReplicationException; + +import com.xiaomi.infra.pegasus.base.error_code; +import com.xiaomi.infra.pegasus.base.error_code.error_types; +import com.xiaomi.infra.pegasus.base.rpc_address; +import com.xiaomi.infra.pegasus.operator.*; + +import com.xiaomi.infra.pegasus.rpc.async.TableHandler.ReplicaConfiguration; +import com.xiaomi.infra.pegasus.tools.Toollet; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.Before; +import org.junit.After; +import org.slf4j.Logger; + +import java.util.ArrayList; + +/** +* TableHandler Tester. +* +* @author sunweijie@xiaomi.com +* @version 1.0 +*/ +public class TableHandlerTest { + private static final Logger logger = org.slf4j.LoggerFactory.getLogger(TableHandlerTest.class); + + private String[] addr_list = {"127.0.0.1:34601", "127.0.0.1:34602", "127.0.0.1:34603"}; + private String[] replica_servers = {"127.0.0.1:34801", "127.0.0.1:34802", "127.0.01:34803"}; + + private ClusterManager testManager; + + @Before + public void before() throws Exception { + testManager = new ClusterManager(1000, 1, false, + null, 60, addr_list); + } + + @After + public void after() throws Exception { + } + + private com.xiaomi.infra.pegasus.base.rpc_address getValidWrongServer(final com.xiaomi.infra.pegasus.base.rpc_address right_address) { + ArrayList replicas = new ArrayList(); + for (int i=0; i/dev/null | " + + "grep %d | grep LISTEN | " + + "awk '{print $7}' | " + + "cut -d \"/\" -f 1 | " + + "xargs kill -9", server.get_port()); + return tryExecuteCommand(command); + } + + public static boolean tryStartServer(rpc_address server) { + String role; + int index; + + if (server.get_port() < 34800) { + // so this is meta server + assert server.get_port() > 34600; + role = "-m"; + index = server.get_port() - 34600; + } + else { + // so this is replica server + assert server.get_port() < 34900; + role = "-r"; + index = server.get_port() - 34800; + } + + String startCommand = String.format("pushd %s && ./run.sh start_onebox_instance %s %d && popd", PegasusRunScriptPath, role, index); + boolean ans = tryExecuteCommand(startCommand); + try { + logger.info("sleep for a while for a killed server to recover"); + Thread.sleep(15000); + } catch (Throwable e) { + e.printStackTrace(); + } + + return ans; + } + + public static boolean waitCondition(BoolCallable callable, int seconds) { + do { + if (callable.call()) + return true; + try { + Thread.sleep(1000l); + } catch (Throwable e) { + e.printStackTrace(); + } + seconds--; + } while (seconds>0); + return false; + } + + public static interface BoolCallable { + public boolean call(); + } + + public static class test_operator extends rrdb_put_operator { + public test_operator(gpid gpid, update_request request) { + super(gpid, "", request); + } + + public void send_data(com.xiaomi.infra.pegasus.thrift.protocol.TProtocol oprot, int seqid) throws TException { + TMessage msg = new TMessage("RPC_RRDB_RRDB_TEST_PUT", TMessageType.CALL, seqid); + oprot.writeMessageBegin(msg); + rrdb.put_args put_args = new rrdb.put_args(req); + put_args.write(oprot); + oprot.writeMessageEnd(); + } + + public void recv_data(TProtocol iprot) throws TException { + rrdb.put_result result = new rrdb.put_result(); + result.read(iprot); + if (result.isSetSuccess()) + resp = result.success; + else + throw new com.xiaomi.infra.pegasus.thrift.TApplicationException( + com.xiaomi.infra.pegasus.thrift.TApplicationException.MISSING_RESULT, + "put failed: unknown result"); + } + + private update_request req; + private update_response resp; + } +}